private EdmFunctionImport.Builder parseEdmFunctionImport( XMLEventReader2 reader, String schemaNamespace, StartElement2 functionImportElement) { String name = functionImportElement.getAttributeByName("Name").getValue(); String entitySet = getAttributeValueIfExists(functionImportElement, "EntitySet"); Attribute2 returnTypeAttr = functionImportElement.getAttributeByName("ReturnType"); String returnType = returnTypeAttr != null ? returnTypeAttr.getValue() : null; List<EdmAnnotation<?>> annotElements = new ArrayList<EdmAnnotation<?>>(); // strict parsing boolean isCollection = returnType != null && returnType.matches("^Collection\\(.*\\)$"); if (isCollection) { returnType = returnType.substring(11, returnType.length() - 1); } String httpMethod = getAttributeValueIfExists(functionImportElement, new QName2(NS_METADATA, "HttpMethod")); List<EdmFunctionParameter.Builder> parameters = new ArrayList<EdmFunctionParameter.Builder>(); while (reader.hasNext()) { XMLEvent2 event = reader.nextEvent(); if (event.isStartElement()) { if (isElement( event, EDM2006_PARAMETER, EDM2007_PARAMETER, EDM2008_1_PARAMETER, EDM2008_9_PARAMETER, EDM2009_8_PARAMETER, EDM2009_11_PARAMETER)) { StartElement2 paramStartElement = event.asStartElement(); EdmFunctionParameter.Builder functionParameter = parseEdmFunctionParameter(reader, paramStartElement); parameters.add(functionParameter); } else { EdmAnnotation<?> anElement = getAnnotationElements(event, reader); if (anElement != null) { annotElements.add(anElement); } } } if (isEndElement(event, functionImportElement.getName())) { return EdmFunctionImport.newBuilder() .setName(name) .setEntitySetName(entitySet) .setReturnTypeName(returnType) .setIsCollection(isCollection) .setHttpMethod(httpMethod) .addParameters(parameters) .setAnnotations(getAnnotations(functionImportElement)) .setAnnotationElements(annotElements); } } throw new UnsupportedOperationException(); }
private static void buildFunctionImports(MetadataStore metadataStore, List<Builder> edmSchemas) { for (Schema schema : metadataStore.getSchemaList()) { EdmSchema.Builder odataSchema = findSchema(edmSchemas, schema.getName()); EdmEntityContainer.Builder entityContainer = findEntityContainer(edmSchemas, schema.getName()); // procedures for (Procedure proc : schema.getProcedures().values()) { EdmFunctionImport.Builder edmProcedure = EdmFunctionImport.newBuilder(); edmProcedure.setName(proc.getName()); String httpMethod = "POST"; for (ProcedureParameter pp : proc.getParameters()) { if (pp.getName().equals("return")) { httpMethod = "GET"; edmProcedure.setReturnType( ODataTypeManager.odataType(pp.getDatatype().getRuntimeTypeName())); continue; } EdmFunctionParameter.Builder param = EdmFunctionParameter.newBuilder(); param.setName(pp.getName()); param.setType(ODataTypeManager.odataType(pp.getDatatype().getRuntimeTypeName())); if (pp.getType() == ProcedureParameter.Type.In) { param.setMode(Mode.In); } else if (pp.getType() == ProcedureParameter.Type.InOut) { param.setMode(Mode.InOut); } else if (pp.getType() == ProcedureParameter.Type.Out) { param.setMode(Mode.Out); } param.setNullable(pp.getNullType() == NullType.Nullable); edmProcedure.addParameters(param); } // add a complex type for return resultset. ColumnSet<Procedure> returnColumns = proc.getResultSet(); if (returnColumns != null) { httpMethod = "GET"; EdmComplexType.Builder complexType = EdmComplexType.newBuilder(); complexType.setName(proc.getName() + "_" + returnColumns.getName()); complexType.setNamespace(schema.getName()); for (Column c : returnColumns.getColumns()) { EdmProperty.Builder property = EdmProperty.newBuilder(c.getName()) .setType(ODataTypeManager.odataType(c.getDatatype().getRuntimeTypeName())) .setNullable(c.getNullType() == NullType.Nullable); if (c.getDatatype() .getRuntimeTypeName() .equals(DataTypeManager.DefaultDataTypes.STRING)) { property .setFixedLength(c.isFixedLength()) .setMaxLength(c.getLength()) .setUnicode(true); } complexType.addProperties(property); } odataSchema.addComplexTypes(complexType); edmProcedure.setIsCollection(true); edmProcedure.setReturnType( EdmCollectionType.newBuilder() .setCollectionType(complexType) .setKind(CollectionKind.Collection)); } edmProcedure.setHttpMethod(httpMethod); entityContainer.addFunctionImports(edmProcedure); } } }
@Override public BaseResponse callFunction( ODataContext context, EdmFunctionImport name, Map<String, OFunctionParameter> params, QueryInfo queryInfo) { BaseResponse response; ServiceOperationsProducerMock.LOGGER.debug("EdmFunctionImport Object: " + name.getName()); ServiceOperationsProducerMock.LOGGER.debug("EdmFunctionImport Parameter: " + params); ServiceOperationsProducerMock.LOGGER.debug("EdmFunctionImport QueryInfo: " + queryInfo); this.queryParameter = params; this.queryInfo = queryInfo; if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING.equals(name.getName())) { response = Responses.simple( EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_PUT.equals( name.getName())) { response = Responses.simple( EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_GET.equals( name.getName())) { response = Responses.simple( EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_DELETE.equals( name.getName())) { response = Responses.simple( EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_PATCH.equals( name.getName())) { response = Responses.simple( EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_MERGE.equals( name.getName())) { response = Responses.simple( EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_STRING_POST.equals( name.getName())) { response = Responses.simple( EdmSimpleType.STRING, name.getName(), ServiceOperationsProducerMock.SOME_TEXT); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_BOOLEAN.equals(name.getName())) { response = Responses.simple( EdmSimpleType.BOOLEAN, name.getName(), ServiceOperationsProducerMock.BOOLEAN_VALUE); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_INT16.equals(name.getName())) { response = Responses.simple( EdmSimpleType.INT16, name.getName(), ServiceOperationsProducerMock.INT16_VALUE); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_ENTITY.equals(name.getName())) { OEntity entity = this.createEmployeeEntity(); response = Responses.entity(entity); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COMPLEX_TYPE.equals( name.getName())) { OComplexObject complexObject = this.createComplexTypeLocation(); response = Responses.complexObject( complexObject, ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COMPLEX_TYPE); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_STRING.equals( name.getName())) { Builder<OObject> collectionBuilder = OCollections.newBuilder(EdmSimpleType.STRING); collectionBuilder .add( OSimpleObjects.create( EdmSimpleType.STRING, ServiceOperationsProducerMock.COLLECTION_STRING1)) .build(); collectionBuilder .add( OSimpleObjects.create( EdmSimpleType.STRING, ServiceOperationsProducerMock.COLLECTION_STRING2)) .build(); OCollection<OObject> collection = collectionBuilder.build(); response = Responses.collection( collection, null, null, null, ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_STRING); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_DOUBLE.equals( name.getName())) { Builder<OObject> collectionBuilder = OCollections.newBuilder(EdmSimpleType.DOUBLE); collectionBuilder .add( OSimpleObjects.create( EdmSimpleType.DOUBLE, ServiceOperationsProducerMock.COLLECTION_DOUBLE1)) .build(); collectionBuilder .add( OSimpleObjects.create( EdmSimpleType.DOUBLE, ServiceOperationsProducerMock.COLLECTION_DOUBLE2)) .build(); OCollection<OObject> collection = collectionBuilder.build(); response = Responses.collection( collection, null, null, null, ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_DOUBLE); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_COMPLEX_TYPE.equals( name.getName())) { OComplexObject complexObject1 = this.createComplexTypeLocation(); OComplexObject complexObject2 = this.createComplexTypeLocation(); EdmComplexType type = this.getMetadata() .findEdmComplexType(ServiceOperationsProducerMock.COMPLEY_TYPE_NAME_LOCATION); Builder<OObject> collectionBuilder = OCollections.newBuilder(type); collectionBuilder.add(complexObject1); collectionBuilder.add(complexObject2); OCollection<OObject> collection = collectionBuilder.build(); response = Responses.collection( collection, null, null, null, ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_COMPLEX_TYPE); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_ENTITY.equals( name.getName())) { OEntity entity = this.createEmployeeEntity(); Builder<OObject> collectionBuilder = OCollections.newBuilder(entity.getType()); collectionBuilder.add(entity); OCollection<OObject> collection = collectionBuilder.build(); response = Responses.collection( collection, entity.getEntitySet(), null, null, ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_COLLECTION_ENTITY); } else if (ServiceOperationsMetadataUtil.TEST_FUNCTION_RETURN_ENTITYSET.equals( name.getName())) { List<OEntity> entities = new ArrayList<OEntity>(); entities.add(createEmployeeEntity()); response = Responses.entities(entities, name.getEntitySet(), null, null); } else { throw new RuntimeException("Unsupported Test Case for FunctionImport: " + name.getName()); } return response; }
public static void write(EdmDataServices services, Writer w) { XMLWriter2 writer = XMLFactoryProvider2.getInstance().newXMLWriterFactory2().createXMLWriter(w); writer.startDocument(); writer.startElement(new QName2(edmx, "Edmx", "edmx")); writer.writeAttribute("Version", "1.0"); writer.writeNamespace("edmx", edmx); writer.writeNamespace("d", d); writer.writeNamespace("m", m); writeExtensionNamespaces(services, writer); writer.startElement(new QName2(edmx, "DataServices", "edmx")); writer.writeAttribute(new QName2(m, "DataServiceVersion", "m"), "1.0"); // Schema for (EdmSchema schema : services.getSchemas()) { writer.startElement(new QName2("Schema"), edm); writer.writeAttribute("Namespace", schema.getNamespace()); writeAnnotationAttributes(schema, writer); writeDocumentation(schema, writer); // ComplexType for (EdmComplexType ect : schema.getComplexTypes()) { writer.startElement(new QName2("ComplexType")); writer.writeAttribute("Name", ect.getName()); if (null != ect.getIsAbstract()) { writer.writeAttribute("Abstract", ect.getIsAbstract().toString()); } writeAnnotationAttributes(ect, writer); writeDocumentation(ect, writer); writeProperties(ect.getProperties(), writer); writeAnnotationElements(ect, writer); writer.endElement("ComplexType"); } // EntityType for (EdmEntityType eet : schema.getEntityTypes()) { writer.startElement(new QName2("EntityType")); writer.writeAttribute("Name", eet.getName()); if (null != eet.getIsAbstract()) { writer.writeAttribute("Abstract", eet.getIsAbstract().toString()); } if (Boolean.TRUE.equals(eet.getHasStream())) { writer.writeAttribute(new QName2(m, "HasStream", "m"), "true"); } // keys only on base types if (eet.isRootType()) { writeAnnotationAttributes(eet, writer); writeDocumentation(eet, writer); writer.startElement(new QName2("Key")); for (String key : eet.getKeys()) { writer.startElement(new QName2("PropertyRef")); writer.writeAttribute("Name", key); writer.endElement("PropertyRef"); } writer.endElement("Key"); } else { writer.writeAttribute("BaseType", eet.getBaseType().getFullyQualifiedTypeName()); writeAnnotationAttributes(eet, writer); writeDocumentation(eet, writer); } writeProperties(eet.getDeclaredProperties(), writer); for (EdmNavigationProperty np : eet.getDeclaredNavigationProperties()) { writer.startElement(new QName2("NavigationProperty")); writer.writeAttribute("Name", np.getName()); writer.writeAttribute("Relationship", np.getRelationship().getFQNamespaceName()); writer.writeAttribute("FromRole", np.getFromRole().getRole()); writer.writeAttribute("ToRole", np.getToRole().getRole()); writeAnnotationAttributes(np, writer); writeDocumentation(np, writer); writeAnnotationElements(np, writer); writer.endElement("NavigationProperty"); } writeAnnotationElements(eet, writer); writer.endElement("EntityType"); } // Association for (EdmAssociation assoc : schema.getAssociations()) { writer.startElement(new QName2("Association")); writer.writeAttribute("Name", assoc.getName()); writeAnnotationAttributes(assoc, writer); writeDocumentation(assoc, writer); writer.startElement(new QName2("End")); writer.writeAttribute("Role", assoc.getEnd1().getRole()); writer.writeAttribute("Type", assoc.getEnd1().getType().getFullyQualifiedTypeName()); writer.writeAttribute("Multiplicity", assoc.getEnd1().getMultiplicity().getSymbolString()); writer.endElement("End"); writer.startElement(new QName2("End")); writer.writeAttribute("Role", assoc.getEnd2().getRole()); writer.writeAttribute("Type", assoc.getEnd2().getType().getFullyQualifiedTypeName()); writer.writeAttribute("Multiplicity", assoc.getEnd2().getMultiplicity().getSymbolString()); writer.endElement("End"); writeAnnotationElements(assoc, writer); writer.endElement("Association"); } // EntityContainer for (EdmEntityContainer container : schema.getEntityContainers()) { writer.startElement(new QName2("EntityContainer")); writer.writeAttribute("Name", container.getName()); writer.writeAttribute( new QName2(m, "IsDefaultEntityContainer", "m"), Boolean.toString(container.isDefault())); writeAnnotationAttributes(container, writer); writeDocumentation(container, writer); for (EdmEntitySet ees : container.getEntitySets()) { writer.startElement(new QName2("EntitySet")); writer.writeAttribute("Name", ees.getName()); writer.writeAttribute("EntityType", ees.getType().getFullyQualifiedTypeName()); writeAnnotationAttributes(ees, writer); writeDocumentation(ees, writer); writeAnnotationElements(ees, writer); writer.endElement("EntitySet"); } for (EdmFunctionImport fi : container.getFunctionImports()) { writer.startElement(new QName2("FunctionImport")); writer.writeAttribute("Name", fi.getName()); if (null != fi.getEntitySet()) { writer.writeAttribute("EntitySet", fi.getEntitySet().getName()); } if (fi.getReturnType() != null) { // TODO: how to differentiate inline ReturnType vs embedded ReturnType? writer.writeAttribute("ReturnType", fi.getReturnType().getFullyQualifiedTypeName()); } writer.writeAttribute(new QName2(m, "HttpMethod", "m"), fi.getHttpMethod()); writeAnnotationAttributes(fi, writer); writeDocumentation(fi, writer); for (EdmFunctionParameter param : fi.getParameters()) { writer.startElement(new QName2("Parameter")); writer.writeAttribute("Name", param.getName()); writer.writeAttribute("Type", param.getType().getFullyQualifiedTypeName()); if (param.getMode() != null) writer.writeAttribute("Mode", param.getMode().toString()); writeAnnotationAttributes(param, writer); writeDocumentation(param, writer); writeAnnotationElements(param, writer); writer.endElement("Parameter"); } writeAnnotationElements(fi, writer); writer.endElement("FunctionImport"); } for (EdmAssociationSet eas : container.getAssociationSets()) { writer.startElement(new QName2("AssociationSet")); writer.writeAttribute("Name", eas.getName()); writer.writeAttribute("Association", eas.getAssociation().getFQNamespaceName()); writeAnnotationAttributes(eas, writer); writeDocumentation(eas, writer); writer.startElement(new QName2("End")); writer.writeAttribute("Role", eas.getEnd1().getRole().getRole()); writer.writeAttribute("EntitySet", eas.getEnd1().getEntitySet().getName()); writer.endElement("End"); writer.startElement(new QName2("End")); writer.writeAttribute("Role", eas.getEnd2().getRole().getRole()); writer.writeAttribute("EntitySet", eas.getEnd2().getEntitySet().getName()); writer.endElement("End"); writeAnnotationElements(eas, writer); writer.endElement("AssociationSet"); } writeAnnotationElements(container, writer); writer.endElement("EntityContainer"); } writeAnnotationElements(schema, writer); writer.endElement("Schema"); } writer.endDocument(); }
private void resolve() { final Map<String, EdmEntityType.Builder> allEetsByFQName = Enumerable.create(dataServices.getEntityTypes()) .toMap(EdmEntityType.Builder.func1_getFullyQualifiedTypeName()); final Map<String, EdmEntityType.Builder> allEetsByFQAliasName = Enumerable.create(dataServices.getEntityTypes()) .where(EdmEntityType.Builder.pred1_hasAlias()) .toMap(EdmEntityType.Builder.func1_getFQAliasName()); final Map<String, EdmAssociation.Builder> allEasByFQName = Enumerable.create(dataServices.getAssociations()) .toMap(EdmAssociation.Builder.func1_getFQNamespaceName()); for (EdmSchema.Builder edmSchema : dataServices.getSchemas()) { // resolve associations for (int i = 0; i < edmSchema.getAssociations().size(); i++) { EdmAssociation.Builder tmpAssociation = edmSchema.getAssociations().get(i); tmpAssociation .getEnd1() .setType(allEetsByFQName.get(tmpAssociation.getEnd1().getTypeName())); tmpAssociation .getEnd2() .setType(allEetsByFQName.get(tmpAssociation.getEnd2().getTypeName())); } // resolve navproperties for (EdmEntityType.Builder eet : edmSchema.getEntityTypes()) { List<EdmNavigationProperty.Builder> navProps = eet.getNavigationProperties(); for (int i = 0; i < navProps.size(); i++) { final EdmNavigationProperty.Builder tmp = navProps.get(i); final EdmAssociation.Builder ea = allEasByFQName.get(tmp.getRelationshipName()); if (ea == null) throw new IllegalArgumentException( "Invalid relationship name " + tmp.getRelationshipName()); List<EdmAssociationEnd.Builder> finalEnds = Enumerable.create(tmp.getFromRoleName(), tmp.getToRoleName()) .select( new Func1<String, EdmAssociationEnd.Builder>() { public EdmAssociationEnd.Builder apply(String input) { if (ea.getEnd1().getRole().equals(input)) return ea.getEnd1(); if (ea.getEnd2().getRole().equals(input)) return ea.getEnd2(); throw new IllegalArgumentException("Invalid role name " + input); } }) .toList(); tmp.setRelationship(ea).setFromTo(finalEnds.get(0), finalEnds.get(1)); } } // resolve entitysets for (EdmEntityContainer.Builder edmEntityContainer : edmSchema.getEntityContainers()) { for (int i = 0; i < edmEntityContainer.getEntitySets().size(); i++) { final EdmEntitySet.Builder tmpEes = edmEntityContainer.getEntitySets().get(i); EdmEntityType.Builder eet = allEetsByFQName.get(tmpEes.getEntityTypeName()); if (eet == null) eet = allEetsByFQAliasName.get(tmpEes.getEntityTypeName()); if (eet == null) throw new IllegalArgumentException("Invalid entity type " + tmpEes.getEntityTypeName()); edmEntityContainer .getEntitySets() .set( i, EdmEntitySet.newBuilder() .setName(tmpEes.getName()) .setEntityType(eet) .setAnnotationElements(tmpEes.getAnnotationElements()) .setAnnotations(tmpEes.getAnnotations())); } } // resolve associationsets for (final EdmEntityContainer.Builder edmEntityContainer : edmSchema.getEntityContainers()) { for (int i = 0; i < edmEntityContainer.getAssociationSets().size(); i++) { final EdmAssociationSet.Builder tmpEas = edmEntityContainer.getAssociationSets().get(i); final EdmAssociation.Builder ea = allEasByFQName.get(tmpEas.getAssociationName()); List<EdmAssociationSetEnd.Builder> finalEnds = Enumerable.create(tmpEas.getEnd1(), tmpEas.getEnd2()) .select( new Func1<EdmAssociationSetEnd.Builder, EdmAssociationSetEnd.Builder>() { public EdmAssociationSetEnd.Builder apply( final EdmAssociationSetEnd.Builder input) { EdmAssociationEnd.Builder eae = ea.getEnd1().getRole().equals(input.getRoleName()) ? ea.getEnd1() : ea.getEnd2().getRole().equals(input.getRoleName()) ? ea.getEnd2() : null; if (eae == null) throw new IllegalArgumentException( "Invalid role name " + input.getRoleName()); EdmEntitySet.Builder ees = Enumerable.create(edmEntityContainer.getEntitySets()) .first( OPredicates.nameEquals( EdmEntitySet.Builder.class, input.getEntitySetName())); return EdmAssociationSetEnd.newBuilder() .setRole(eae) .setEntitySet(ees) .setAnnotationElements(input.getAnnotationElements()) .setAnnotations(input.getAnnotations()); } }) .toList(); tmpEas.setAssociation(ea).setEnds(finalEnds.get(0), finalEnds.get(1)); } } // resolve functionimports for (final EdmEntityContainer.Builder edmEntityContainer : edmSchema.getEntityContainers()) { for (int i = 0; i < edmEntityContainer.getFunctionImports().size(); i++) { final EdmFunctionImport.Builder tmpEfi = edmEntityContainer.getFunctionImports().get(i); EdmEntitySet.Builder ees = Enumerable.create(edmEntityContainer.getEntitySets()) .firstOrNull( new Predicate1<EdmEntitySet.Builder>() { public boolean apply(EdmEntitySet.Builder input) { return input.getName().equals(tmpEfi.getEntitySetName()); } }); EdmType.Builder<?, ?> typeBuilder = null; if (tmpEfi.getReturnTypeName() != null) { typeBuilder = dataServices.resolveType(tmpEfi.getReturnTypeName()); if (typeBuilder == null) throw new RuntimeException("Edm-type not found: " + tmpEfi.getReturnTypeName()); if (tmpEfi.isCollection()) { typeBuilder = EdmCollectionType.newBuilder() .setKind(CollectionKind.Collection) .setCollectionType(typeBuilder); } } edmEntityContainer .getFunctionImports() .set( i, EdmFunctionImport.newBuilder() .setName(tmpEfi.getName()) .setEntitySet(ees) .setReturnType(typeBuilder) .setHttpMethod(tmpEfi.getHttpMethod()) .addParameters(tmpEfi.getParameters()) .setAnnotationElements(tmpEfi.getAnnotationElements()) .setAnnotations(tmpEfi.getAnnotations())); } } // resolve type hierarchy for (Entry<String, EdmEntityType.Builder> entry : allEetsByFQName.entrySet()) { String baseTypeName = entry.getValue().getFQBaseTypeName(); if (baseTypeName != null) { EdmEntityType.Builder baseType = allEetsByFQName.get(baseTypeName); if (baseType == null) { throw new IllegalArgumentException("Invalid baseType: " + baseTypeName); } entry.getValue().setBaseType(baseType); } } } }