use of org.oasisopen.odata.csdl.v4.TEntityType in project odata-client by davidmoten.
the class Generator method writeEntityCollectionRequest.
private void writeEntityCollectionRequest(Schema schema, TEntityType entityType, Map<String, List<Action>> collectionTypeActions, Map<String, List<Function>> collectionTypeFunctions, Set<String> collectionTypes) {
EntityType t = new EntityType(entityType, names);
if (!collectionTypes.contains(t.getFullType())) {
return;
}
names.getDirectoryEntityCollectionRequest(schema).mkdirs();
String simpleClassName = names.getSimpleClassNameCollectionRequest(schema, t.getName());
Imports imports = new Imports(names.getFullClassNameCollectionRequest(schema, t.getName()));
Indent indent = new Indent();
StringWriter w = new StringWriter();
try (PrintWriter p = new PrintWriter(w)) {
p.format("package %s;\n\n", names.getPackageCollectionRequest(schema));
p.format(IMPORTSHERE);
p.format("public class %s extends %s<%s, %s>{\n\n", simpleClassName, imports.add(CollectionPageEntityRequest.class), //
imports.add(names.getFullClassNameFromTypeWithoutNamespace(schema, t.getName())), imports.add(names.getFullClassNameEntityRequest(schema, t.getName())));
indent.right();
addContextPathField(imports, indent, p);
// add constructor
//
p.format(//
"\n%spublic %s(%s contextPath, %s<%s> value) {\n", //
indent, //
simpleClassName, //
imports.add(ContextPath.class), //
imports.add(Optional.class), imports.add(Object.class));
//
p.format(//
"%ssuper(contextPath, %s.class, cp -> new %s(cp, Optional.empty()), value);\n", //
indent.right(), //
imports.add(names.getFullClassNameFromTypeWithoutNamespace(schema, t.getName())), imports.add(names.getFullClassNameEntityRequestFromTypeWithoutNamespace(schema, t.getName())));
p.format("%sthis.contextPath = contextPath;\n", indent);
p.format("%s}\n", indent.left());
// write fields from properties
//
t.getNavigationProperties().forEach(x -> {
Schema sch = names.getSchema(names.getInnerType(names.getType(x)));
if (x.getType().get(0).startsWith(COLLECTION_PREFIX)) {
String y = names.getInnerType(names.getType(x));
if (names.isEntityWithNamespace(y)) {
String entityRequestType = names.getFullClassNameEntityRequestFromTypeWithNamespace(sch, y);
EntityType et = names.getEntityType(y);
KeyInfo k = getKeyInfo(et, imports);
if (!k.isEmpty()) {
p.format("\n%spublic %s %s(%s) {\n", indent, imports.add(entityRequestType), Names.getIdentifier(x.getName()), k.typedParams);
p.format("%sreturn new %s(contextPath.addSegment(\"%s\")%s, %s.empty());\n", indent.right(), imports.add(entityRequestType), x.getName(), k.addKeys, imports.add(Optional.class));
p.format("%s}\n", indent.left());
}
}
//
p.format(//
"\n%spublic %s %s() {\n", //
indent, imports.add(//
names.getFullClassNameCollectionRequestFromTypeWithNamespace(sch, y)), Names.getIdentifier(x.getName()));
//
p.format(//
"%sreturn new %s(contextPath.addSegment(\"%s\"), %s.empty());\n", //
indent.right(), imports.add(//
names.getFullClassNameCollectionRequestFromTypeWithNamespace(sch, y)), //
x.getName(), imports.add(Optional.class));
p.format("%s}\n", indent.left());
}
});
Set<String> methodNames = new HashSet<>();
writeBoundActionMethods(t, collectionTypeActions, imports, indent, p, methodNames);
writeBoundFunctionMethods(t, collectionTypeFunctions, imports, indent, p, methodNames);
indent.left();
p.format("\n}\n");
writeToFile(imports, w, t.getClassFileCollectionRequest());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
use of org.oasisopen.odata.csdl.v4.TEntityType in project odata-client by davidmoten.
the class Generator method writeEntityRequest.
private void writeEntityRequest(Schema schema, TEntityType entityType, Map<String, List<Action>> typeActions, Map<String, List<Function>> typeFunctions) {
EntityType t = new EntityType(entityType, names);
names.getDirectoryEntityRequest(schema).mkdirs();
// TODO only write out those requests needed
String simpleClassName = t.getSimpleClassNameEntityRequest();
Imports imports = new Imports(t.getFullClassNameEntityRequest());
Indent indent = new Indent();
StringWriter w = new StringWriter();
try (PrintWriter p = new PrintWriter(w)) {
p.format("package %s;\n\n", t.getPackageEntityRequest());
p.format(IMPORTSHERE);
p.format("@%s\n", imports.add(JsonIgnoreType.class));
// don't make class final because can get extended by EntitySet
p.format("public class %s extends %s {\n\n", simpleClassName, imports.add(EntityRequest.class) + "<" + imports.add(t.getFullClassNameEntity()) + ">");
indent.right();
// add constructor
//
p.format(//
"%spublic %s(%s contextPath, %s<%s> value) {\n", //
indent, //
simpleClassName, //
imports.add(ContextPath.class), imports.add(Optional.class), imports.add(Object.class));
//
p.format(//
"%ssuper(%s.class, contextPath, value, %s);\n", //
indent.right(), //
imports.add(t.getFullClassNameEntity()), t.isMediaEntityOrHasStreamProperty());
p.format("%s}\n", indent.left());
indent.left();
if (t.hasStream()) {
p.format("\n%s/**\n", indent);
p.format("%s * If returning a stream without using object metadata is not supported then", indent);
p.format("%s * returns {@code Optional.empty()}. Otherwise, returns a stream provider\n", indent);
p.format("%s * where the location of the stream is assumed to be the current path + {@code /$value}.\n", indent);
p.format("%s *\n", indent);
p.format("%s * @return StreamProvider if suitable metadata found otherwise returns\n", indent);
p.format("%s * {@code Optional.empty()}\n", indent);
p.format("%s */\n", indent);
p.format("%s@%s\n", indent, imports.add(JsonIgnore.class));
p.format("%spublic %s<%s> getStreamCurrentPath() {\n", indent, imports.add(Optional.class), imports.add(StreamProvider.class));
p.format("%sreturn %s.createStream(contextPath, null);\n", indent.right(), imports.add(RequestHelper.class));
p.format("%s}\n", indent.left());
}
// TODO also support navigation properties with complexTypes?
//
t.getNavigationProperties().stream().filter(x -> {
boolean isEntity = names.isEntityWithNamespace(names.getInnerType(names.getType(x)));
if (!isEntity) {
log("Unexpected entity with non-entity navigation property type: " + simpleClassName + "." + x.getName() + ". If you get this message then raise an issue on the github project for odata-client.");
}
return isEntity;
}).forEach(x -> {
indent.right();
final String returnClass;
String y = x.getType().get(0);
Schema sch = names.getSchema(names.getInnerType(y));
if (Names.isCollection(y)) {
returnClass = toClassName(x, imports);
} else {
returnClass = imports.add(names.getFullClassNameEntityRequestFromTypeWithNamespace(sch, y));
}
// if collection then add with id method (if has ids)
if (Names.isCollection(y)) {
// TODO use actual key name from metadata
String inner = names.getInnerType(y);
// TODO remove redundant check
if (names.isEntityWithNamespace(inner)) {
String entityRequestType = names.getFullClassNameEntityRequestFromTypeWithNamespace(sch, inner);
EntityType et = names.getEntityType(inner);
KeyInfo k = getKeyInfo(et, imports);
if (!k.isEmpty()) {
p.format("\n%spublic %s %s(%s) {\n", indent, imports.add(entityRequestType), Names.getIdentifier(x.getName()), k.typedParams);
p.format("%sreturn new %s(contextPath.addSegment(\"%s\")%s, %s.empty());\n", indent.right(), imports.add(entityRequestType), x.getName(), k.addKeys, imports.add(Optional.class));
p.format("%s}\n", indent.left());
}
}
}
//
p.format(//
"\n%spublic %s %s() {\n", //
indent, //
returnClass, Names.getGetterMethodWithoutGet(x.getName()));
if (isCollection(x)) {
p.format("%sreturn new %s(\n", indent.right(), toClassName(x, imports));
p.format("%scontextPath.addSegment(\"%s\"), %s.empty());\n", indent.right().right().right().right(), x.getName(), imports.add(Optional.class));
indent.left().left().left().left();
} else {
p.format("%sreturn new %s(contextPath.addSegment(\"%s\"), %s.empty());\n", indent.right(), returnClass, x.getName(), imports.add(Optional.class));
}
p.format("%s}\n", indent.left());
indent.left();
});
indent.right();
Set<String> methodNames = new HashSet<>();
writeBoundActionMethods(t, typeActions, imports, indent, p, methodNames);
writeBoundFunctionMethods(t, typeFunctions, imports, indent, p, methodNames);
indent.left();
p.format("\n}\n");
writeToFile(imports, w, t.getClassFileEntityRequest());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
use of org.oasisopen.odata.csdl.v4.TEntityType in project odata-client by davidmoten.
the class Util method replaceAlias.
private static void replaceAlias(Schema schema, Object x) {
if (schema.getAlias() == null) {
return;
}
if (x instanceof TEntityType) {
TEntityType p = (TEntityType) x;
// mutate types to use alias
p.setBaseType(replaceAlias(schema, p.getBaseType()));
//
p.getKeyOrPropertyOrNavigationProperty().forEach(y -> replaceAlias(schema, y));
} else if (x instanceof TComplexType) {
TComplexType p = (TComplexType) x;
// mutate types to use alias
p.setBaseType(replaceAlias(schema, p.getBaseType()));
//
p.getPropertyOrNavigationPropertyOrAnnotation().forEach(y -> replaceAlias(schema, y));
} else if (x instanceof TAction) {
TAction a = (TAction) x;
//
a.getParameterOrAnnotationOrReturnType().forEach(y -> replaceAlias(schema, y));
} else if (x instanceof TFunction) {
TFunction a = (TFunction) x;
//
a.getParameterOrAnnotation().forEach(y -> replaceAlias(schema, y));
replaceAlias(schema, a.getReturnType());
} else if (x instanceof TActionFunctionParameter) {
TActionFunctionParameter p = (TActionFunctionParameter) x;
replaceAlias(schema, p.getType());
} else if (x instanceof TActionFunctionReturnType) {
TActionFunctionReturnType p = (TActionFunctionReturnType) x;
replaceAlias(schema, p.getType());
} else if (x instanceof TProperty) {
TProperty p = (TProperty) x;
replaceAlias(schema, p.getType());
} else if (x instanceof TNavigationProperty) {
TNavigationProperty p = (TNavigationProperty) x;
replaceAlias(schema, p.getType());
} else if (x instanceof TAnnotations) {
TAnnotations a = (TAnnotations) x;
a.setTarget(replaceAlias(schema, a.getTarget()));
} else if (x instanceof TEntityContainer) {
TEntityContainer a = (TEntityContainer) x;
Util.filter(a.getEntitySetOrActionImportOrFunctionImport(), TEntitySet.class).forEach(y -> replaceAlias(schema, y));
} else if (x instanceof TEntitySet) {
TEntitySet a = (TEntitySet) x;
a.setEntityType(replaceAlias(schema, a.getEntityType()));
}
}
use of org.oasisopen.odata.csdl.v4.TEntityType in project odata-client by davidmoten.
the class Generator method writeEntity.
private void writeEntity(TEntityType entityType, Map<String, List<Action>> typeActions, Map<String, List<Function>> typeFunctions) {
EntityType t = new EntityType(entityType, names);
t.getDirectoryEntity().mkdirs();
String simpleClassName = t.getSimpleClassName();
Imports imports = new Imports(t.getFullClassNameEntity());
Indent indent = new Indent();
StringWriter w = new StringWriter();
try (PrintWriter p = new PrintWriter(w)) {
p.format("package %s;\n\n", t.getPackage());
p.format(IMPORTSHERE);
t.printJavadoc(p, indent);
printPropertyOrder(imports, p, t.getProperties());
printJsonIncludesNonNull(indent, imports, p);
p.format("public class %s%s implements %s {\n", simpleClassName, t.getExtendsClause(imports), imports.add(ODataEntityType.class));
indent.right();
if (!t.hasBaseType()) {
addContextPathInjectableField(imports, indent, p);
addUnmappedFieldsField(imports, indent, p);
addChangedFieldsField(imports, indent, p);
}
p.format("\n%s@%s\n", indent, imports.add(Override.class));
p.format("%spublic String odataTypeName() {\n", indent);
p.format("%sreturn \"%s\";\n", indent.right(), t.getFullType());
p.format("%s}\n", indent.left());
// add other fields
printPropertyFields(imports, indent, p, t.getProperties(), t.hasBaseType());
// write constructor
writeNoArgsConstructor(simpleClassName, indent, p, t.hasBaseType());
writeBuilder(t, simpleClassName, imports, indent, p);
p.format("\n%s@%s\n", indent, imports.add(Override.class));
p.format("%s@%s\n", indent, imports.add(JsonIgnore.class));
p.format("%spublic %s getChangedFields() {\n", indent, imports.add(ChangedFields.class));
p.format("%sreturn changedFields;\n", indent.right());
p.format("%s}\n", indent.left());
String nullCheck = //
fieldNames(t).stream().map(//
f -> f + " != null").collect(Collectors.joining(" && "));
if (!nullCheck.isEmpty()) {
nullCheck = " && " + nullCheck;
}
p.format("\n%s@%s\n", indent, imports.add(Override.class));
p.format("%spublic void postInject(boolean addKeysToContextPath) {\n", indent);
p.format("%sif (addKeysToContextPath%s) {\n", indent.right(), nullCheck);
p.format("%scontextPath = contextPath.clearQueries()%s;\n", indent.right(), getAddKeys(t, imports));
p.format("%s}\n", indent.left());
p.format("%s}\n", indent.left());
Set<String> methodNames = new HashSet<>();
// write property getter and setters
printPropertyGetterAndSetters(t, imports, indent, p, simpleClassName, t.getFullType(), t.getProperties(), true, methodNames);
addInheritedPropertyNames(t, methodNames);
printNavigationPropertyGetters(t, imports, indent, p, t.getNavigationProperties(), methodNames);
addUnmappedFieldsSetterAndGetter(imports, indent, p, methodNames);
if (t.hasStream()) {
p.format("\n%s/**\n", indent);
p.format("%s * If suitable metadata found a StreamProvider is returned otherwise returns\n", indent);
p.format("%s * {@code Optional.empty()}. Normally for a stream to be available this entity\n", indent);
p.format("%s * needs to have been hydrated with full metadata. Consider calling the builder\n", indent);
p.format("%s * method {@code .metadataFull()} when getting this instance (either directly or\n", indent);
p.format("%s * as part of a collection).\n", indent);
p.format("%s *\n", indent);
p.format("%s * @return StreamProvider if suitable metadata found otherwise returns\n", indent);
p.format("%s * {@code Optional.empty()}\n", indent);
p.format("%s */\n", indent);
p.format("%s@%s\n", indent, imports.add(JsonIgnore.class));
p.format("%spublic %s<%s> getStream() {\n", indent, imports.add(Optional.class), imports.add(StreamProvider.class));
p.format("%sreturn %s.createStream(contextPath, this);\n", indent.right(), imports.add(RequestHelper.class));
p.format("%s}\n", indent.left());
}
// write Patched class
writePatchAndPutMethods(t, simpleClassName, imports, indent, p);
writeCopyMethod(t, simpleClassName, imports, indent, p, true);
writeBoundActionMethods(t, typeActions, imports, indent, p, methodNames);
writeBoundFunctionMethods(t, typeFunctions, imports, indent, p, methodNames);
// write toString
writeToString(t, simpleClassName, imports, indent, p);
p.format("%s}\n", indent.left());
writeToFile(imports, w, t.getClassFile());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
use of org.oasisopen.odata.csdl.v4.TEntityType in project odata-client by davidmoten.
the class Generator method generate.
public void generate() {
log("-----------------------------------");
log("Generating code for namespaces:");
//
schemas.forEach(s -> log(" " + s.getNamespace()));
log("Types:");
//
schemas.stream().flatMap(s -> Util.filter(s.getComplexTypeOrEntityTypeOrTypeDefinition(), TEntityType.class).map(//
t -> new SchemaAndType<TEntityType>(s, t))).map(//
x -> names.toTypeWithNamespace(x.schema, x.type.getName())).forEach(x -> log(" " + x));
log("-----------------------------------");
log("Replacing aliases");
Util.replaceAliases(schemas);
log("Finding collection types");
Set<String> collectionTypes = findTypesUsedInCollections(names, schemas);
for (Schema schema : schemas) {
log("Generating for namespace=" + schema.getNamespace());
log(" creating maps");
Map<String, List<Action>> typeActions = createTypeActions(schema, names, false);
log(" entity actions count = " + typeActions.size());
Map<String, List<Function>> typeFunctions = createTypeFunctions(schema, names, false);
log(" entity functions count = " + typeFunctions.size());
Map<String, List<Action>> collectionTypeActions = createTypeActions(schema, names, true);
log(" collection actions count = " + collectionTypeActions.size());
Map<String, List<Function>> collectionTypeFunctions = createTypeFunctions(schema, names, true);
System.out.println(" collection functions count = " + collectionTypeFunctions.size());
log(" checking entities have keys");
//
Util.types(schema, TEntityType.class).map(//
x -> new EntityType(x, names)).filter(//
x -> !x.hasKey()).forEach(x -> log(" " + x.getFullType() + " has no keys"));
log(" writing schema info");
writeSchemaInfo(schema);
// write enums
log(" writing enums");
//
Util.types(schema, TEnumType.class).forEach(x -> writeEnum(schema, x));
// write entityTypes
log(" writing entities");
//
Util.types(schema, TEntityType.class).forEach(x -> writeEntity(x, typeActions, typeFunctions));
// write complexTypes
log(" writing complex types");
//
Util.types(schema, TComplexType.class).forEach(x -> writeComplexType(schema, x));
// write entity collection requests
log(" writing entity collection requests");
//
Util.types(schema, TEntityType.class).forEach(x -> writeEntityCollectionRequest(schema, x, collectionTypeActions, collectionTypeFunctions, collectionTypes));
log("writing entity set requests");
//
Util.types(schema, TEntityContainer.class).flatMap(c -> //
Util.filter(c.getEntitySetOrActionImportOrFunctionImport(), //
TEntitySet.class).map(//
x -> new Pair<TEntityContainer, TEntitySet>(c, x))).forEach(x -> writeEntitySet(schema, x));
// write containers
log(" writing container");
//
Util.types(schema, TEntityContainer.class).forEach(x -> writeContainer(schema, x));
// write single requests
log(" writing entity requests");
//
Util.types(schema, TEntityType.class).forEach(x -> writeEntityRequest(schema, x, typeActions, typeFunctions));
log(" writing complex type requests");
//
Util.types(schema, TComplexType.class).forEach(x -> writeComplexTypeRequest(schema, x));
}
}
Aggregations