OLINGO-861, OLINGO-863, OLINGO-868, OLINGO-869 : Improvements to MetadataParser for annotation support
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/6d94f0e3 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/6d94f0e3 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/6d94f0e3 Branch: refs/heads/master Commit: 6d94f0e386b7f3126f1023c87c78670fb55e2d5a Parents: b317b90 Author: Ramesh Reddy <[email protected]> Authored: Sat Feb 6 13:31:26 2016 -0600 Committer: Ramesh Reddy <[email protected]> Committed: Sat Feb 6 13:31:26 2016 -0600 ---------------------------------------------------------------------- .../commons/api/edm/provider/CsdlOnDelete.java | 23 +- .../api/edm/provider/CsdlReturnType.java | 23 +- .../olingo/server/api/edmx/EdmxReference.java | 24 +- .../olingo/server/core/MetadataParser.java | 498 ++++++++++-- .../core/MetadataParserAnnotationsTest.java | 208 +++++ .../olingo/server/core/MetadataParserTest.java | 3 +- .../server/core/ServiceDispatcherTest.java | 17 +- .../olingo/server/example/TripPinServlet.java | 9 +- .../src/test/resources/annotations.xml | 153 ++++ .../src/test/resources/trippin.xml | 808 +++++++++++-------- 10 files changed, 1311 insertions(+), 455 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlOnDelete.java ---------------------------------------------------------------------- diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlOnDelete.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlOnDelete.java index 1a326dd..e3ed711 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlOnDelete.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlOnDelete.java @@ -18,13 +18,17 @@ */ package org.apache.olingo.commons.api.edm.provider; +import java.util.ArrayList; +import java.util.List; + /** * The type Csdl on delete. */ -public class CsdlOnDelete extends CsdlAbstractEdmItem { +public class CsdlOnDelete extends CsdlAbstractEdmItem implements CsdlAnnotatable { private CsdlOnDeleteAction action = CsdlOnDeleteAction.None; - + + private List<CsdlAnnotation> annotations = new ArrayList<CsdlAnnotation>(); /** * Gets action. * @@ -45,4 +49,19 @@ public class CsdlOnDelete extends CsdlAbstractEdmItem { return this; } + @Override + public List<CsdlAnnotation> getAnnotations() { + return annotations; + } + + /** + * Sets annotations. + * + * @param annotations the annotations + * @return the annotations + */ + public CsdlOnDelete setAnnotations(final List<CsdlAnnotation> annotations) { + this.annotations = annotations; + return this; + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlReturnType.java ---------------------------------------------------------------------- diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlReturnType.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlReturnType.java index eb94acc..e5cee4e 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlReturnType.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/provider/CsdlReturnType.java @@ -18,13 +18,16 @@ */ package org.apache.olingo.commons.api.edm.provider; +import java.util.ArrayList; +import java.util.List; + import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.edm.geo.SRID; /** * The type Csdl return type. */ -public class CsdlReturnType extends CsdlAbstractEdmItem { +public class CsdlReturnType extends CsdlAbstractEdmItem implements CsdlAnnotatable { private String type; @@ -40,6 +43,8 @@ public class CsdlReturnType extends CsdlAbstractEdmItem { private Integer scale; private SRID srid; + + private List<CsdlAnnotation> annotations = new ArrayList<CsdlAnnotation>(); /** * Gets type. @@ -200,4 +205,20 @@ public class CsdlReturnType extends CsdlAbstractEdmItem { this.srid = srid; return this; } + + @Override + public List<CsdlAnnotation> getAnnotations() { + return annotations; + } + + /** + * Sets annotations. + * + * @param annotations the annotations + * @return the annotations + */ + public CsdlReturnType setAnnotations(final List<CsdlAnnotation> annotations) { + this.annotations = annotations; + return this; + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/commons-api/src/main/java/org/apache/olingo/server/api/edmx/EdmxReference.java ---------------------------------------------------------------------- diff --git a/lib/commons-api/src/main/java/org/apache/olingo/server/api/edmx/EdmxReference.java b/lib/commons-api/src/main/java/org/apache/olingo/server/api/edmx/EdmxReference.java index 38d17fe..e1b735b 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/server/api/edmx/EdmxReference.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/server/api/edmx/EdmxReference.java @@ -23,15 +23,19 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.apache.olingo.commons.api.edm.provider.CsdlAnnotatable; +import org.apache.olingo.commons.api.edm.provider.CsdlAnnotation; +import org.apache.olingo.commons.api.edm.provider.CsdlReturnType; + /** * POJO for Edmx Reference. */ -public class EdmxReference { +public class EdmxReference implements CsdlAnnotatable{ private final URI uri; private final List<EdmxReferenceInclude> edmxIncludes; private final List<EdmxReferenceIncludeAnnotation> edmxIncludeAnnotations; - + private List<CsdlAnnotation> annotations = new ArrayList<CsdlAnnotation>(); /** * Create reference with given uri * @@ -90,4 +94,20 @@ public class EdmxReference { edmxIncludeAnnotations.add(includeAnnotation); return this; } + + @Override + public List<CsdlAnnotation> getAnnotations() { + return annotations; + } + + /** + * Sets annotations. + * + * @param annotations the annotations + * @return the annotations + */ + public EdmxReference setAnnotations(final List<CsdlAnnotation> annotations) { + this.annotations = annotations; + return this; + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java index b5ffd4a..e8122d7 100644 --- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java +++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java @@ -19,9 +19,10 @@ package org.apache.olingo.server.core; import java.io.Reader; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.Arrays; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; @@ -36,6 +37,10 @@ import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.edm.geo.SRID; import org.apache.olingo.commons.api.edm.provider.CsdlAction; import org.apache.olingo.commons.api.edm.provider.CsdlActionImport; +import org.apache.olingo.commons.api.edm.provider.CsdlAnnotatable; +import org.apache.olingo.commons.api.edm.provider.CsdlAnnotation; +import org.apache.olingo.commons.api.edm.provider.CsdlAnnotations; +import org.apache.olingo.commons.api.edm.provider.CsdlBindingTarget; import org.apache.olingo.commons.api.edm.provider.CsdlComplexType; import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider; import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer; @@ -59,33 +64,91 @@ import org.apache.olingo.commons.api.edm.provider.CsdlSchema; import org.apache.olingo.commons.api.edm.provider.CsdlSingleton; import org.apache.olingo.commons.api.edm.provider.CsdlTerm; import org.apache.olingo.commons.api.edm.provider.CsdlTypeDefinition; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlAnnotationPath; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlApply; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlCast; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlCollection; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlConstantExpression; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlConstantExpression.ConstantExpressionType; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlExpression; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlIf; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlIsOf; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlLabeledElement; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlLabeledElementReference; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlNavigationPropertyPath; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlNull; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlPath; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlPropertyPath; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlPropertyValue; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlRecord; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlUrlRef; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.edmx.EdmxReference; +import org.apache.olingo.server.api.edmx.EdmxReferenceInclude; +import org.apache.olingo.server.api.edmx.EdmxReferenceIncludeAnnotation; /** * This class can convert a CSDL document into EDMProvider object */ public class MetadataParser { + private boolean parseAnnotations = false; - public CsdlEdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException { + public void setParseAnnotations(boolean f) { + this.parseAnnotations = true; + } + + public ServiceMetadata buildServiceMetadata(Reader csdl) throws XMLStreamException { XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl); SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider(); + final ArrayList<EdmxReference> references = new ArrayList<EdmxReference>(); + new ElementReader<SchemaBasedEdmProvider>() { @Override void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider, String name) throws XMLStreamException { String version = attr(element, "Version"); if ("4.0".equals(version)) { - readDataServicesAndReference(reader, element, provider); + readDataServicesAndReference(reader, element, provider, references); + } else { + throw new XMLStreamException("Currently only V4 is supported."); } } }.read(reader, null, provider, "Edmx"); - - return provider; + if(reader.hasNext()) { + XMLEvent event = reader.peek(); + throw new XMLStreamException( + "Failed to read complete metadata file. Failed at " + + (event.isStartElement() ? + event.asStartElement().getName().getLocalPart() : + event.asEndElement().getName().getLocalPart())); + } + return new ServiceMetadataImpl(provider, references, null); } - private void readDataServicesAndReference(XMLEventReader reader, StartElement element, - SchemaBasedEdmProvider provider) throws XMLStreamException { + CsdlEdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException { + XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); + XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl); + + SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider(); + new ElementReader<SchemaBasedEdmProvider>() { + @Override + void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider, + String name) throws XMLStreamException { + String version = attr(element, "Version"); + if ("4.0".equals(version)) { + readDataServicesAndReference(reader, element, provider, new ArrayList<EdmxReference>()); + } + } + }.read(reader, null, provider, "Edmx"); + + return provider; + } + + private void readDataServicesAndReference(XMLEventReader reader, + StartElement element, SchemaBasedEdmProvider provider, + final ArrayList<EdmxReference> references) throws XMLStreamException { new ElementReader<SchemaBasedEdmProvider>() { @Override void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider, @@ -93,45 +156,64 @@ public class MetadataParser { if (name.equals("DataServices")) { readSchema(reader, element, provider); } else if (name.equals("Reference")) { - readReference(reader, element, provider, "Reference"); + readReference(reader, element, references, "Reference"); } } }.read(reader, element, provider, "DataServices", "Reference"); } private void readReference(XMLEventReader reader, StartElement element, - SchemaBasedEdmProvider provider, String name) throws XMLStreamException { - new ElementReader<SchemaBasedEdmProvider>() { + final ArrayList<EdmxReference> references, String name) throws XMLStreamException { + EdmxReference reference; + try { + String uri = attr(element, "Uri"); + reference = new EdmxReference(new URI(uri)); + } catch (URISyntaxException e) { + throw new XMLStreamException(e); + } + new ElementReader<EdmxReference>() { @Override - void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider t, String name) - throws XMLStreamException { - // TODO: + void build(XMLEventReader reader, StartElement element, + EdmxReference reference, String name) throws XMLStreamException { + if (name.equals("Include")) { + EdmxReferenceInclude include = new EdmxReferenceInclude(attr(element, "Namespace"), + attr(element, "Alias")); + reference.addInclude(include); + } else if (name.equals("IncludeAnnotations")) { + EdmxReferenceIncludeAnnotation annotation = new EdmxReferenceIncludeAnnotation( + attr(element, "TermNamespace")); + annotation.setTargetNamespace(attr(element, "TargetNamespace")); + annotation.setQualifier(attr(element, "Qualifier")); + reference.addIncludeAnnotation(annotation); + } else if (name.equals("Annotation")) { + readAnnotations(reader, element, reference); + } } - }.read(reader, element, provider, name); + }.read(reader, element, reference, "Include", "IncludeAnnotations", "Annotation"); + references.add(reference); } - + private void readSchema(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider) throws XMLStreamException { - CsdlSchema schema = new CsdlSchema(); - schema.setComplexTypes(new ArrayList<CsdlComplexType>()); - schema.setActions(new ArrayList<CsdlAction>()); - schema.setEntityTypes(new ArrayList<CsdlEntityType>()); - schema.setEnumTypes(new ArrayList<CsdlEnumType>()); - schema.setFunctions(new ArrayList<CsdlFunction>()); - schema.setTerms(new ArrayList<CsdlTerm>()); - schema.setTypeDefinitions(new ArrayList<CsdlTypeDefinition>()); - - new ElementReader<CsdlSchema>() { + new ElementReader<SchemaBasedEdmProvider>() { @Override - void build(XMLEventReader reader, StartElement element, CsdlSchema schema, String name) + void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider, String name) throws XMLStreamException { + CsdlSchema schema = new CsdlSchema(); + schema.setComplexTypes(new ArrayList<CsdlComplexType>()); + schema.setActions(new ArrayList<CsdlAction>()); + schema.setEntityTypes(new ArrayList<CsdlEntityType>()); + schema.setEnumTypes(new ArrayList<CsdlEnumType>()); + schema.setFunctions(new ArrayList<CsdlFunction>()); + schema.setTerms(new ArrayList<CsdlTerm>()); + schema.setTypeDefinitions(new ArrayList<CsdlTypeDefinition>()); schema.setNamespace(attr(element, "Namespace")); schema.setAlias(attr(element, "Alias")); readSchemaContents(reader, schema); + provider.addSchema(schema); } - }.read(reader, element, schema, "Schema"); - provider.addSchema(schema); + }.read(reader, element, provider, "Schema"); } private void readSchemaContents(XMLEventReader reader, CsdlSchema schema) throws XMLStreamException { @@ -141,9 +223,10 @@ public class MetadataParser { throws XMLStreamException { if (name.equals("Action")) { readAction(reader, element, schema); -// } else if (name.equals("Annotations")) { -// } else if (name.equals("Annotation")) { - // TODO: Add support for annotations + } else if (name.equals("Annotations")) { + readAnnotationGroup(reader, element, schema); + } else if (name.equals("Annotation")) { + readAnnotations(reader, element, schema); } else if (name.equals("ComplexType")) { readComplexType(reader, element, schema); } else if (name.equals("EntityContainer")) { @@ -155,9 +238,9 @@ public class MetadataParser { } else if (name.equals("Function")) { readFunction(reader, element, schema); } else if (name.equals("Term")) { - schema.getTerms().add(readTerm(element)); + schema.getTerms().add(readTerm(reader, element)); } else if (name.equals("TypeDefinition")) { - schema.getTypeDefinitions().add(readTypeDefinition(element)); + schema.getTypeDefinitions().add(readTypeDefinition(reader, element)); } } }.read(reader, null, schema, "Action", "Annotations", "Annotation", "ComplexType", @@ -196,7 +279,8 @@ public class MetadataParser { return false; } - private void readReturnType(StartElement element, CsdlOperation operation) { + private void readReturnType(XMLEventReader reader, StartElement element, + CsdlOperation operation) throws XMLStreamException { CsdlReturnType returnType = new CsdlReturnType(); returnType.setType(readType(element)); returnType.setCollection(isCollectionType(element)); @@ -216,13 +300,14 @@ public class MetadataParser { } String srid = attr(element, "SRID"); if (srid != null) { - // TODO: no olingo support yet. returnType.setSrid(SRID.valueOf(srid)); } + peekAnnotations(reader, element.getName().getLocalPart(), returnType); operation.setReturnType(returnType); } - private void readParameter(StartElement element, CsdlOperation operation) { + private void readParameter(XMLEventReader reader, StartElement element, + CsdlOperation operation) throws XMLStreamException { CsdlParameter parameter = new CsdlParameter(); parameter.setName(attr(element, "Name")); parameter.setType(readType(element)); @@ -243,13 +328,14 @@ public class MetadataParser { } String srid = attr(element, "SRID"); if (srid != null) { - // TODO: no olingo support yet. parameter.setSrid(SRID.valueOf(srid)); } + peekAnnotations(reader, element.getName().getLocalPart(), parameter); operation.getParameters().add(parameter); } - private CsdlTypeDefinition readTypeDefinition(StartElement element) { + private CsdlTypeDefinition readTypeDefinition(XMLEventReader reader, + StartElement element) throws XMLStreamException { CsdlTypeDefinition td = new CsdlTypeDefinition(); td.setName(attr(element, "Name")); td.setUnderlyingType(new FullQualifiedName(attr(element, "UnderlyingType"))); @@ -269,16 +355,17 @@ public class MetadataParser { } String srid = attr(element, "SRID"); if (srid != null) { - // TODO: no olingo support yet. td.setSrid(SRID.valueOf(srid)); } + peekAnnotations(reader, element.getName().getLocalPart(), td); return td; } - private CsdlTerm readTerm(StartElement element) { + private CsdlTerm readTerm(XMLEventReader reader, StartElement element) throws XMLStreamException { CsdlTerm term = new CsdlTerm(); term.setName(attr(element, "Name")); term.setType(attr(element, "Type")); + if (attr(element, "BaseTerm") != null) { term.setBaseTerm(attr(element, "BaseTerm")); } @@ -286,7 +373,8 @@ public class MetadataParser { term.setDefaultValue(attr(element, "DefaultValue")); } if (attr(element, "AppliesTo") != null) { - term.setAppliesTo(Collections.singletonList(attr(element, "AppliesTo"))); + String[] appliesTo = attr(element, "AppliesTo").split("\\s+"); + term.setAppliesTo(Arrays.asList(appliesTo)); } term.setNullable(Boolean.parseBoolean(attr(element, "Nullable"))); String maxLength = attr(element, "MaxLength"); @@ -303,12 +391,231 @@ public class MetadataParser { } String srid = attr(element, "SRID"); if (srid != null) { - // TODO: no olingo support yet. term.setSrid(SRID.valueOf(srid)); } + peekAnnotations(reader, "Term", term); return term; } + private void readAnnotationGroup(XMLEventReader reader, StartElement element, + CsdlSchema schema) throws XMLStreamException { + final CsdlAnnotations annotations = new CsdlAnnotations(); + annotations.setTarget(attr(element, "Target")); + annotations.setQualifier(attr(element, "Qualifier")); + readAnnotations(reader, element, annotations); + schema.getAnnotationGroups().add(annotations); + } + + private void peekAnnotations(XMLEventReader reader, String endName, + CsdlAnnotatable edmObject) throws XMLStreamException { + if(!parseAnnotations) { + return; + } + while (reader.hasNext()) { + XMLEvent event = reader.peek(); + + if (!event.isStartElement() && !event.isEndElement()) { + reader.nextEvent(); + continue; + } + + if (event.isStartElement()) { + StartElement element = event.asStartElement(); + if (element.getName().getLocalPart().equals("Annotation")) { + reader.nextEvent(); + readAnnotations(reader, element, edmObject); + } + } + + if (event.isEndElement()) { + EndElement element = event.asEndElement(); + if (element.getName().getLocalPart().equals("Annotation")) { + reader.nextEvent(); + } + + if (element.getName().getLocalPart().equals(endName)) { + return; + } + } + } + } + + private void readAnnotations(XMLEventReader reader, StartElement element, + CsdlAnnotatable edmObject) throws XMLStreamException { + if (!parseAnnotations) { + return; + } + final CsdlAnnotation annotation = new CsdlAnnotation(); + annotation.setTerm(attr(element, "Term")); + for (ConstantExpressionType type:ConstantExpressionType.values()) { + if (attr(element, type.name()) != null) { + annotation.setExpression(new CsdlConstantExpression( + type, attr(element, type.name()))); + } + } + readExpressions(reader, element, annotation); + edmObject.getAnnotations().add(annotation); + } + + private <T> void write(T t, CsdlExpression expr) throws XMLStreamException { + if(t instanceof CsdlAnnotation) { + ((CsdlAnnotation)t).setExpression(expr); + } else if (t instanceof CsdlUrlRef) { + ((CsdlUrlRef)t).setValue(expr); + } else if (t instanceof CsdlCast) { + ((CsdlCast)t).setValue(expr); + } else if (t instanceof CsdlLabeledElement) { + ((CsdlLabeledElement)t).setValue(expr); + } else if (t instanceof CsdlIsOf) { + ((CsdlIsOf)t).setValue(expr); + } else if (t instanceof CsdlCollection) { + ((CsdlCollection)t).getItems().add(((CsdlCollection)t).getItems().size(), expr); + } else if (t instanceof CsdlApply) { + ((CsdlApply)t).getParameters().add(expr); + } else if (t instanceof CsdlIf) { + if (((CsdlIf)t).getGuard() == null) { + ((CsdlIf)t).setGuard(expr); + } else if (((CsdlIf)t).getThen() == null) { + ((CsdlIf)t).setThen(expr); + } else { + ((CsdlIf)t).setElse(expr); + } + } else if (t instanceof CsdlPropertyValue) { + ((CsdlPropertyValue)t).setValue(expr); + } else { + throw new XMLStreamException("Unknown expression parent in Annoatation"); + } + } + + private <T> void readExpressions(XMLEventReader reader, + StartElement element, T target) + throws XMLStreamException { + new ElementReader<T>() { + @Override + void build(XMLEventReader reader, StartElement element, T target, String name) + throws XMLStreamException { + + // attribute based expressions + if (attr(element, "AnnotationPath") != null) { + write(target, new CsdlAnnotationPath().setValue(attr(element, "AnnotationPath"))); + } + if (attr(element, "NavigationPropertyPath") != null) { + write(target, new CsdlNavigationPropertyPath() + .setValue(attr(element, "NavigationPropertyPath"))); + } + if (attr(element, "Path") != null) { + write(target, new CsdlPath().setValue(attr(element, "Path"))); + } + if (attr(element, "PropertyPath") != null) { + write(target, new CsdlPropertyPath().setValue(attr(element, "PropertyPath"))); + } + if (attr(element, "UrlRef") != null) { + write(target, new CsdlUrlRef().setValue(new CsdlConstantExpression( + ConstantExpressionType.String, attr(element, "UrlRef")))); + } + + // element based expressions + for (ConstantExpressionType type:ConstantExpressionType.values()) { + if (name.equals(type.name())) { + if (reader.peek().isCharacters()) { + CsdlExpression expr = new CsdlConstantExpression(type, elementValue(reader, element)); + write(target, expr); + } + } + } + if (name.equals("Collection")) { + CsdlCollection expr = new CsdlCollection(); + readExpressions(reader, element, expr); + write(target, expr); + } else if (name.equals("AnnotationPath")) { + write(target, new CsdlAnnotationPath().setValue(elementValue(reader, element))); + } else if (name.equals("NavigationPropertyPath")) { + write(target, new CsdlNavigationPropertyPath() + .setValue(elementValue(reader, element))); + } else if (name.equals("Path")) { + write(target, new CsdlPath().setValue(elementValue(reader, element))); + } else if (name.equals("PropertyPath")) { + write(target, new CsdlPropertyPath().setValue(elementValue(reader, element))); + } else if (name.equals("UrlRef")) { + CsdlUrlRef expr = new CsdlUrlRef(); + readExpressions(reader, element, expr); + write(target, expr); + } else if (name.equals("Apply")) { + CsdlApply expr = new CsdlApply(); + expr.setFunction(attr(element, "Function")); + readExpressions(reader, element, expr); + write(target, expr); + } else if (name.equals("Cast")) { + CsdlCast expr = new CsdlCast(); + expr.setType(attr(element, "Type")); + readExpressions(reader, element, expr); + write(target, expr); + } else if (name.equals("If")) { + CsdlIf expr = new CsdlIf(); + readExpressions(reader, element, expr); + write(target, expr); + } else if (name.equals("IsOf")) { + CsdlIsOf expr = new CsdlIsOf(); + expr.setType(attr(element, "Type")); + readExpressions(reader, element, expr); + write(target, expr); + } else if (name.equals("LabeledElement")) { + CsdlLabeledElement expr = new CsdlLabeledElement(); + expr.setName(attr(element, "Name")); + readExpressions(reader, element, expr); + write(target, expr); + } else if (name.equals("LabeledElementReference")) { + CsdlLabeledElementReference expr = new CsdlLabeledElementReference(); + expr.setValue(elementValue(reader, element)); + write(target, expr); + } else if (name.equals("Null")) { + write(target, new CsdlNull()); + } else if (name.equals("Record")) { + CsdlRecord expr = new CsdlRecord(); + expr.setType(attr(element, "Type")); + readPropertyValues(reader, element, expr); + write(target, expr); + } + } + }.read(reader, element, target, "Collection", "AnnotationPath", + "NavigationPropertyPath", "Path", "PropertyPath", "UrlRef", + "Apply", "Function", "Cast", "If", "IsOf", "LabeledElement", + "LabeledElementReference", "Null", "Record","Binary", "Bool", "Date", + "DateTimeOffset", "Decimal", "Duration", "EnumMember", "Float", "Guid", + "Int", "String", "TimeOfDay"); + } + + private String elementValue(XMLEventReader reader, StartElement element) throws XMLStreamException { + while (reader.hasNext()) { + XMLEvent event = reader.peek(); + if (event.isStartElement() || event.isEndElement()) { + return null; + } else if (event.isCharacters()){ + reader.nextEvent(); + String data = event.asCharacters().getData(); + if (data.trim().length() > 0) { + return data.trim(); + } + } + } + return null; + } + + private void readPropertyValues(XMLEventReader reader, + StartElement element, CsdlRecord record) throws XMLStreamException { + + new ElementReader<CsdlRecord>() { + @Override + void build(XMLEventReader reader, StartElement element, CsdlRecord record, String name) + throws XMLStreamException { + CsdlPropertyValue value = new CsdlPropertyValue(); + value.setProperty(attr(element, "Property")); + readExpressions(reader, element, value); + record.getPropertyValues().add(value); + } + }.read(reader, element, record, "PropertyValue"); + } + private void readFunction(XMLEventReader reader, StartElement element, CsdlSchema schema) throws XMLStreamException { CsdlFunction function = new CsdlFunction(); @@ -332,12 +639,14 @@ public class MetadataParser { void build(XMLEventReader reader, StartElement element, CsdlOperation operation, String name) throws XMLStreamException { if (name.equals("Parameter")) { - readParameter(element, operation); + readParameter(reader, element, operation); } else if (name.equals("ReturnType")) { - readReturnType(element, operation); + readReturnType(reader, element, operation); + } else if (name.equals("Annotation")) { + readAnnotations(reader, element, operation); } } - }.read(reader, null, operation, "Parameter", "ReturnType"); + }.read(reader, null, operation, "Parameter", "ReturnType", "Annotation"); } private void readEnumType(XMLEventReader reader, StartElement element, CsdlSchema schema) @@ -356,16 +665,22 @@ public class MetadataParser { private void readEnumMembers(XMLEventReader reader, StartElement element, CsdlEnumType type) throws XMLStreamException { + new ElementReader<CsdlEnumType>() { @Override void build(XMLEventReader reader, StartElement element, CsdlEnumType type, String name) throws XMLStreamException { - CsdlEnumMember member = new CsdlEnumMember(); - member.setName(attr(element, "Name")); - member.setValue(attr(element, "Value")); - type.getMembers().add(member); + if (name.equals("Member")) { + CsdlEnumMember member = new CsdlEnumMember(); + member.setName(attr(element, "Name")); + member.setValue(attr(element, "Value")); + peekAnnotations(reader, name, member); + type.getMembers().add(member); + } else if (name.equals("Annotation")) { + readAnnotations(reader, element, type); + } } - }.read(reader, element, type, "Member"); + }.read(reader, element, type, "Member", "Annotation"); } private void readEntityType(XMLEventReader reader, StartElement element, CsdlSchema schema) @@ -392,14 +707,16 @@ public class MetadataParser { void build(XMLEventReader reader, StartElement element, CsdlEntityType entityType, String name) throws XMLStreamException { if (name.equals("Property")) { - entityType.getProperties().add(readProperty(element)); + entityType.getProperties().add(readProperty(reader, element)); } else if (name.equals("NavigationProperty")) { entityType.getNavigationProperties().add(readNavigationProperty(reader, element)); } else if (name.equals("Key")) { readKey(reader, element, entityType); + } else if (name.equals("Annotation")) { + readAnnotations(reader, element, entityType); } } - }.read(reader, null, entityType, "Property", "NavigationProperty", "Key"); + }.read(reader, null, entityType, "Property", "NavigationProperty", "Key", "Annotation"); } private void readKey(XMLEventReader reader, StartElement element, CsdlEntityType entityType) @@ -436,12 +753,18 @@ public class MetadataParser { CsdlReferentialConstraint constraint = new CsdlReferentialConstraint(); constraint.setProperty(attr(element, "Property")); constraint.setReferencedProperty(attr(element, "ReferencedProperty")); + peekAnnotations(reader, name, constraint); property.getReferentialConstraints().add(constraint); } else if (name.equals("OnDelete")) { - property.setOnDelete(new CsdlOnDelete().setAction(CsdlOnDeleteAction.valueOf(attr(element, "Action")))); + CsdlOnDelete delete = new CsdlOnDelete(); + delete.setAction(CsdlOnDeleteAction.valueOf(attr(element, "Action"))); + property.setOnDelete(delete); + peekAnnotations(reader, name, delete); + } else if (name.equals("Annotation")) { + readAnnotations(reader, element, property); } } - }.read(reader, element, property, "ReferentialConstraint", "OnDelete"); + }.read(reader, element, property, "ReferentialConstraint", "OnDelete", "Annotation"); return property; } @@ -453,7 +776,8 @@ public class MetadataParser { return null; } - private CsdlProperty readProperty(StartElement element) { + private CsdlProperty readProperty(XMLEventReader reader, StartElement element) + throws XMLStreamException { CsdlProperty property = new CsdlProperty(); property.setName(attr(element, "Name")); property.setType(readType(element)); @@ -476,13 +800,13 @@ public class MetadataParser { } String srid = attr(element, "SRID"); if (srid != null) { - // TODO: no olingo support yet. property.setSrid(SRID.valueOf(srid)); } String defaultValue = attr(element, "DefaultValue"); if (defaultValue != null) { property.setDefaultValue(defaultValue); } + peekAnnotations(reader, element.getName().getLocalPart(), property); return property; } @@ -507,13 +831,17 @@ public class MetadataParser { } else if (name.equals("Singleton")) { readSingleton(reader, element, container); } else if (name.equals("ActionImport")) { - readActionImport(element, container); + readActionImport(reader, element, container); } else if (name.equals("FunctionImport")) { - readFunctionImport(element, container); + readFunctionImport(reader, element, container); + } else if (name.equals("Annotation")) { + readAnnotations(reader, element, container); } } - private void readFunctionImport(StartElement element, CsdlEntityContainer container) { + private void readFunctionImport(XMLEventReader reader, + StartElement element, CsdlEntityContainer container) + throws XMLStreamException { CsdlFunctionImport functionImport = new CsdlFunctionImport(); functionImport.setName(attr(element, "Name")); functionImport.setFunction(new FullQualifiedName(attr(element, "Function"))); @@ -524,10 +852,13 @@ public class MetadataParser { if (entitySet != null) { functionImport.setEntitySet(entitySet); } + peekAnnotations(reader, "FunctionImport", functionImport); container.getFunctionImports().add(functionImport); } - private void readActionImport(StartElement element, CsdlEntityContainer container) { + private void readActionImport(XMLEventReader reader, + StartElement element, CsdlEntityContainer container) + throws XMLStreamException { CsdlActionImport actionImport = new CsdlActionImport(); actionImport.setName(attr(element, "Name")); actionImport.setAction(new FullQualifiedName(attr(element, "Action"))); @@ -536,6 +867,7 @@ public class MetadataParser { if (entitySet != null) { actionImport.setEntitySet(entitySet); } + peekAnnotations(reader, "ActionImport", actionImport); container.getActionImports().add(actionImport); } @@ -546,7 +878,7 @@ public class MetadataParser { singleton.setName(attr(element, "Name")); singleton.setType(new FullQualifiedName(attr(element, "Type"))); singleton.setNavigationPropertyBindings(new ArrayList<CsdlNavigationPropertyBinding>()); - readNavigationPropertyBindings(reader, element, singleton.getNavigationPropertyBindings()); + readNavigationPropertyBindings(reader, element, singleton); container.getSingletons().add(singleton); } @@ -558,25 +890,29 @@ public class MetadataParser { entitySet.setIncludeInServiceDocument(Boolean.parseBoolean(attr(element, "IncludeInServiceDocument"))); entitySet.setNavigationPropertyBindings(new ArrayList<CsdlNavigationPropertyBinding>()); - readNavigationPropertyBindings(reader, element, entitySet.getNavigationPropertyBindings()); + readNavigationPropertyBindings(reader, element, entitySet); container.getEntitySets().add(entitySet); } private void readNavigationPropertyBindings(XMLEventReader reader, StartElement element, - List<CsdlNavigationPropertyBinding> bindings) throws XMLStreamException { - new ElementReader<List<CsdlNavigationPropertyBinding>>() { + CsdlBindingTarget entitySet) throws XMLStreamException { + new ElementReader<CsdlBindingTarget>() { @Override void build(XMLEventReader reader, StartElement element, - List<CsdlNavigationPropertyBinding> bindings, String name) throws XMLStreamException { - CsdlNavigationPropertyBinding binding = new CsdlNavigationPropertyBinding(); - binding.setPath(attr(element, "Path")); - binding.setTarget(attr(element, "Target")); - bindings.add(binding); + CsdlBindingTarget entitySet, String name) throws XMLStreamException { + if (name.equals("NavigationPropertyBinding")) { + CsdlNavigationPropertyBinding binding = new CsdlNavigationPropertyBinding(); + binding.setPath(attr(element, "Path")); + binding.setTarget(attr(element, "Target")); + entitySet.getNavigationPropertyBindings().add(binding); + } else if (name.equals("Annotation")) { + readAnnotations(reader, element, entitySet); + } } - }.read(reader, element, bindings, "NavigationPropertyBinding"); + }.read(reader, element, entitySet, "NavigationPropertyBinding", "Annotation"); } - }.read(reader, element, schema, "EntitySet", "Singleton", "ActionImport", "FunctionImport"); + }.read(reader, element, schema, "EntitySet", "Singleton", "ActionImport", "FunctionImport", "Annotation"); schema.setEntityContainer(container); } @@ -603,12 +939,14 @@ public class MetadataParser { void build(XMLEventReader reader, StartElement element, CsdlComplexType complexType, String name) throws XMLStreamException { if (name.equals("Property")) { - complexType.getProperties().add(readProperty(element)); + complexType.getProperties().add(readProperty(reader, element)); } else if (name.equals("NavigationProperty")) { complexType.getNavigationProperties().add(readNavigationProperty(reader, element)); + } else if (name.equals("Annotation")) { + readAnnotations(reader, element, complexType); } } - }.read(reader, null, complexType, "Property", "NavigationProperty"); + }.read(reader, null, complexType, "Property", "NavigationProperty", "Annotation"); } abstract class ElementReader<T> { @@ -617,7 +955,9 @@ public class MetadataParser { while (reader.hasNext()) { XMLEvent event = reader.peek(); - event = skipAnnotations(reader, event); + if (!parseAnnotations) { + event = skipAnnotations(reader, event); + } if (!event.isStartElement() && !event.isEndElement()) { reader.nextEvent(); @@ -629,17 +969,19 @@ public class MetadataParser { for (String name : names) { if (event.isStartElement()) { element = event.asStartElement(); - if (element.getName().getLocalPart().equals(name)) { - reader.nextEvent(); // advance cursor + if (element.getName().getLocalPart().equals(name)) { + reader.nextEvent(); // advance cursor start which is current build(reader, element, t, name); hit = true; + break; } } if (event.isEndElement()) { EndElement e = event.asEndElement(); if (e.getName().getLocalPart().equals(name)) { - reader.nextEvent(); // advance cursor + reader.nextEvent(); // advance cursor to end which is current hit = true; + break; } } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java new file mode 100644 index 0000000..7912dc8 --- /dev/null +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserAnnotationsTest.java @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.olingo.server.core; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.FileReader; +import java.util.Arrays; + +import org.apache.olingo.commons.api.edm.FullQualifiedName; +import org.apache.olingo.commons.api.edm.provider.CsdlAnnotation; +import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider; +import org.apache.olingo.commons.api.edm.provider.CsdlSchema; +import org.apache.olingo.commons.api.edm.provider.CsdlTerm; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlAnnotationPath; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlApply; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlCast; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlCollection; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlConstantExpression; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlConstantExpression.ConstantExpressionType; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlIf; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlIsOf; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlLabeledElement; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlLabeledElementReference; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlNavigationPropertyPath; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlNull; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlPath; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlPropertyValue; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlRecord; +import org.apache.olingo.commons.api.edm.provider.annotation.CsdlUrlRef; +import org.apache.olingo.commons.api.ex.ODataException; +import org.junit.Before; +import org.junit.Test; + +public class MetadataParserAnnotationsTest { + final String NS = "Org.OData.Core.V1"; + final FullQualifiedName NSF = new FullQualifiedName(NS); + + CsdlEdmProvider provider = null; + + @Before + public void setUp() throws Exception { + MetadataParser parser = new MetadataParser(); + parser.setParseAnnotations(true); + provider = (CsdlEdmProvider) parser.buildEdmProvider(new FileReader("src/test/resources/annotations.xml")); + } + + CsdlAnnotation annotation(String term) throws ODataException { + CsdlSchema schema = provider.getSchemas().get(0); + assertNotNull(schema.getAnnotations()); + + return schema.getAnnotation(term); + } + + @Test + public void testConstantExpressionAttribute() throws ODataException { + CsdlAnnotation a = annotation("Core.Description"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlConstantExpression); + assertEquals("Core terms needed to write vocabularies", ((CsdlConstantExpression)a.getExpression()).getValue()); + assertEquals(ConstantExpressionType.String, ((CsdlConstantExpression)a.getExpression()).getType()); + + a = annotation("org.example.display.LastUpdated"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlConstantExpression); + assertEquals("2000-01-01T16:00:00.000-09:00", ((CsdlConstantExpression)a.getExpression()).getValue()); + assertEquals(ConstantExpressionType.DateTimeOffset, ((CsdlConstantExpression)a.getExpression()).getType()); + } + + @Test + public void testCollection() throws ODataException { + CsdlAnnotation a = annotation("UI.CollectionFacet"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlCollection); + CsdlCollection exprs = ((CsdlCollection)a.getExpression()); + assertEquals(2, exprs.getItems().size()); + assertTrue(exprs.getItems().get(0) instanceof CsdlAnnotationPath); + CsdlAnnotationPath path = (CsdlAnnotationPath) exprs.getItems().get(0); + assertEquals("Supplier/@Communication.Contact", path.getValue()); + } + + @Test + public void testApply() throws ODataException { + CsdlAnnotation a = annotation("org.example.display.DisplayNameApply"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlApply); + CsdlApply apply = ((CsdlApply)a.getExpression()); + + assertEquals("odata.concat", apply.getFunction()); + assertEquals(7, apply.getParameters().size()); + assertTrue(apply.getParameters().get(1) instanceof CsdlPath); + assertTrue(apply.getParameters().get(4) instanceof CsdlConstantExpression); + } + + @Test + public void testCast() throws ODataException { + CsdlAnnotation a = annotation("org.example.display.Threshold"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlCast); + CsdlCast cast= (CsdlCast)a.getExpression(); + + assertEquals("Edm.Decimal", cast.getType()); + assertTrue(cast.getValue() instanceof CsdlPath); + assertEquals("Average", ((CsdlPath)cast.getValue()).getValue()); + } + + @Test + public void testIf() throws ODataException { + CsdlAnnotation a = annotation("org.example.person.Gender"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlIf); + CsdlIf ifexpr = (CsdlIf)a.getExpression(); + + assertTrue(ifexpr.getGuard() instanceof CsdlPath); + assertTrue(ifexpr.getThen() instanceof CsdlConstantExpression); + assertTrue(ifexpr.getElse() instanceof CsdlConstantExpression); + + assertEquals("IsFemale", ((CsdlPath)ifexpr.getGuard()).getValue()); + assertEquals("Female", ((CsdlConstantExpression)ifexpr.getThen()).getValue()); + assertEquals("Male", ((CsdlConstantExpression)ifexpr.getElse()).getValue()); + } + + @Test + public void testIsOf() throws ODataException { + CsdlAnnotation a = annotation("Self.IsPreferredCustomer"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlIsOf); + CsdlIsOf isOf = (CsdlIsOf)a.getExpression(); + assertEquals("Self.PreferredCustomer", isOf.getType()); + assertTrue(isOf.getValue() instanceof CsdlPath); + } + + @Test + public void testLableledElement() throws ODataException { + CsdlAnnotation a = annotation("org.example.display.DisplayNameLabel"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlLabeledElement); + CsdlLabeledElement expr = (CsdlLabeledElement)a.getExpression(); + assertEquals("CustomerFirstName", expr.getName()); + assertTrue(expr.getValue() instanceof CsdlPath); + } + + @Test + public void testLableledReference() throws ODataException { + CsdlAnnotation a = annotation("org.example.display.DisplayNameLabelReference"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlLabeledElementReference); + CsdlLabeledElementReference expr = (CsdlLabeledElementReference)a.getExpression(); + assertEquals("Model.CustomerFirstName", expr.getValue()); + } + + @Test + public void testNull() throws ODataException { + CsdlAnnotation a = annotation("org.example.display.DisplayNameNull"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlNull); + } + + @Test + public void testRecord() throws ODataException { + CsdlAnnotation a = annotation("Capabilities.UpdateRestrictions"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlRecord); + CsdlRecord expr = (CsdlRecord)a.getExpression(); + assertEquals(1, expr.getPropertyValues().size()); + CsdlPropertyValue value = expr.getPropertyValues().get(0); + assertEquals("NonUpdatableNavigationProperties", value.getProperty()); + assertTrue(value.getValue() instanceof CsdlCollection); + + CsdlCollection collection = (CsdlCollection)value.getValue(); + assertEquals(2, collection.getItems().size()); + assertEquals("Category", ((CsdlNavigationPropertyPath)collection.getItems().get(1)).getValue()); + } + + @Test + public void testUrlRef() throws ODataException { + CsdlAnnotation a = annotation("Vocab.Supplier"); + assertNotNull(a); + assertTrue(a.getExpression() instanceof CsdlUrlRef); + CsdlUrlRef expr = (CsdlUrlRef)a.getExpression(); + assertTrue(expr.getValue() instanceof CsdlApply); + assertEquals(2, ((CsdlApply)expr.getValue()).getParameters().size()); + } + + @Test + public void testTermAppliesTo() throws ODataException { + CsdlTerm term = this.provider.getTerm(new FullQualifiedName(NS, "IsURI")); + assertEquals(Arrays.asList("Property", "PropertyPath"), term.getAppliesTo()); + } +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java index 5092357..97f19b5 100644 --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java @@ -54,7 +54,8 @@ public class MetadataParserTest { @Before public void setUp() throws Exception { MetadataParser parser = new MetadataParser(); - provider = parser.buildEdmProvider(new FileReader("src/test/resources/trippin.xml")); + parser.setParseAnnotations(true); + provider = (CsdlEdmProvider) parser.buildEdmProvider(new FileReader("src/test/resources/trippin.xml")); } @Test http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java index a7fc922..90ead94 100644 --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java @@ -26,7 +26,6 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; import java.net.URI; -import java.util.Collections; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -43,12 +42,10 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider; import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataHttpHandler; import org.apache.olingo.server.api.ServiceMetadata; -import org.apache.olingo.server.api.edmx.EdmxReference; import org.apache.olingo.server.core.requests.ActionRequest; import org.apache.olingo.server.core.requests.DataRequest; import org.apache.olingo.server.core.requests.FunctionRequest; @@ -73,20 +70,19 @@ public class ServiceDispatcherTest { public class SampleODataServlet extends HttpServlet { private static final long serialVersionUID = 1L; private final ServiceHandler handler; // must be stateless - private final CsdlEdmProvider provider; // must be stateless + private final ServiceMetadata metadata; // must be stateless - public SampleODataServlet(ServiceHandler handler, CsdlEdmProvider provider) { + public SampleODataServlet(ServiceHandler handler, ServiceMetadata metadata) { this.handler = handler; - this.provider = provider; + this.metadata = metadata; } @Override public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { OData odata = OData4Impl.newInstance(); - ServiceMetadata metadata = odata.createServiceMetadata(this.provider, Collections.<EdmxReference> emptyList()); - ODataHttpHandler handler = odata.createHandler(metadata); + ODataHttpHandler handler = odata.createHandler(this.metadata); handler.register(this.handler); handler.process(request, response); @@ -95,14 +91,13 @@ public class ServiceDispatcherTest { public void beforeTest(ServiceHandler serviceHandler) throws Exception { MetadataParser parser = new MetadataParser(); - CsdlEdmProvider edmProvider = parser.buildEdmProvider(new FileReader( - "src/test/resources/trippin.xml")); + ServiceMetadata metadata = parser.buildServiceMetadata(new FileReader("src/test/resources/trippin.xml")); File baseDir = new File(System.getProperty("java.io.tmpdir")); tomcat.setBaseDir(baseDir.getAbsolutePath()); tomcat.getHost().setAppBase(baseDir.getAbsolutePath()); Context cxt = tomcat.addContext("/trippin", baseDir.getAbsolutePath()); - Tomcat.addServlet(cxt, "trippin", new SampleODataServlet(serviceHandler, edmProvider)); + Tomcat.addServlet(cxt, "trippin", new SampleODataServlet(serviceHandler, metadata)); cxt.addServletMapping("/*", "trippin"); tomcat.setPort(TOMCAT_PORT); tomcat.start(); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java index fbc74ef..036cd78 100644 --- a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java +++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinServlet.java @@ -20,7 +20,6 @@ package org.apache.olingo.server.example; import java.io.FileReader; import java.io.IOException; -import java.util.Collections; import javax.servlet.ServletConfig; import javax.servlet.ServletException; @@ -29,11 +28,9 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.stream.XMLStreamException; -import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataHttpHandler; import org.apache.olingo.server.api.ServiceMetadata; -import org.apache.olingo.server.api.edmx.EdmxReference; import org.apache.olingo.server.core.MetadataParser; import org.apache.olingo.server.core.OData4Impl; @@ -50,16 +47,14 @@ public class TripPinServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { OData odata = OData4Impl.newInstance(); MetadataParser parser = new MetadataParser(); - CsdlEdmProvider edmProvider = null; + ServiceMetadata metadata = null; try { - edmProvider = parser.buildEdmProvider(new FileReader("src/test/resources/trippin.xml")); + metadata = parser.buildServiceMetadata(new FileReader("src/test/resources/trippin.xml")); } catch (XMLStreamException e) { throw new IOException(e); } - ServiceMetadata metadata = odata.createServiceMetadata(edmProvider, Collections.<EdmxReference>emptyList()); - ODataHttpHandler handler = odata.createHandler(metadata); if (this.dataModel == null) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6d94f0e3/lib/server-core-ext/src/test/resources/annotations.xml ---------------------------------------------------------------------- diff --git a/lib/server-core-ext/src/test/resources/annotations.xml b/lib/server-core-ext/src/test/resources/annotations.xml new file mode 100644 index 0000000..fce46a8 --- /dev/null +++ b/lib/server-core-ext/src/test/resources/annotations.xml @@ -0,0 +1,153 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor + license agreements. See the NOTICE file distributed with this work for additional + information regarding copyright ownership. The ASF licenses this file to + you under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of + the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required + by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + OF ANY KIND, either express or implied. See the License for the specific + language governing permissions and limitations under the License. --> +<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" + Version="4.0"> + <edmx:DataServices> + <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" + Namespace="Org.OData.Core.V1" Alias="Core"> + + <Annotation Term="Core.Description"> + <String>Core terms needed to write vocabularies</String> + </Annotation> + + <Annotation Term="org.example.display.Thumbnail"> + <Binary>T0RhdGE</Binary> + </Annotation> + + <Annotation Term="org.example.display.ReadOnly"> + <Bool>true</Bool> + </Annotation> + + <Annotation Term="org.example.display.LastUpdated" + DateTimeOffset="2000-01-01T16:00:00.000-09:00" /> + + <Annotation Term="UI.ReferenceFacet" AnnotationPath="Product/Supplier/@UI.LineItem" /> + + <Annotation Term="UI.CollectionFacet" Qualifier="Contacts"> + <Collection> + <AnnotationPath>Supplier/@Communication.Contact</AnnotationPath> + <AnnotationPath>Customer/@Communication.Contact</AnnotationPath> + </Collection> + </Annotation> + + <Annotation Term="org.example.display.DisplayNameApply"> + <Apply Function="odata.concat"> + <String>Product: </String> + <Path>ProductName</Path> + <String> (</String> + <Path>Available/Quantity</Path> + <String> + </String> + <Path>Available/Unit</Path> + <String> available)</String> + </Apply> + </Annotation> + + <Annotation Term="org.example.display.Threshold"> + <Cast Type="Edm.Decimal"> + <Path>Average</Path> + </Cast> + </Annotation> + <Annotation Term="org.example.seo.SeoTerms"> + <Collection> + <String>Product</String> + <String>Supplier</String> + <String>Customer</String> + </Collection> + </Annotation> + + <Annotation Term="org.example.person.Gender"> + <If> + <Path>IsFemale</Path> + <String>Female</String> + <String>Male</String> + </If> + </Annotation> + + <Annotation Term="Self.IsPreferredCustomer"> + <IsOf Type="Self.PreferredCustomer"> + <Path>Customer</Path> + </IsOf> + </Annotation> + + <Annotation Term="org.example.display.DisplayNameLabel"> + <LabeledElement Name="CustomerFirstName"> + <Path>FirstName</Path> + </LabeledElement> + </Annotation> + + <Annotation Term="org.example.display.DisplayNameLabelReference"> + <LabeledElementReference>Model.CustomerFirstName + </LabeledElementReference> + </Annotation> + + <Annotation Term="org.example.display.DisplayNameNull"> + <Null /> + </Annotation> + + <Annotation Term="Capabilities.UpdateRestrictions"> + <Record> + <PropertyValue Property="NonUpdatableNavigationProperties"> + <Collection> + <NavigationPropertyPath>Supplier</NavigationPropertyPath> + <NavigationPropertyPath>Category</NavigationPropertyPath> + </Collection> + </PropertyValue> + </Record> + </Annotation> + + <Annotation Term="org.example.display.DisplayNamePath"> + <Path>@vCard.Address#work/FullName</Path> + </Annotation> + + <Term Name="IsURI" Type="Core.Tag" DefaultValue="true" + AppliesTo="Property PropertyPath"> + <Annotation Term="Core.Description"> + <String> + Properties and terms annotated with this term MUST contain a valid URI + </String> + </Annotation> + <Annotation Term="Core.RequiresType" String="Edm.String" /> + </Term> + + <Annotation Term="org.example.person.Employee"> + <Record> + <PropertyValue Property="GivenName" Path="FirstName" /> + <PropertyValue Property="Surname" Path="LastName" /> + <PropertyValue Property="Manager" Path="DirectSupervisor" /> + <PropertyValue Property="CostCenter"> + <UrlRef> + <Apply Function="odata.fillUriTemplate"> + <String>http://host/anotherservice/CostCenters('{ccid}') + </String> + <LabeledElement Name="ccid" Path="CostCenterID" /> + </Apply> + </UrlRef> + </PropertyValue> + </Record> + </Annotation> + + <Annotation Term="Vocab.Supplier"> + <UrlRef> + <Apply Function="odata.fillUriTemplate"> + <String>http://host/service/Suppliers({suppID})</String> + <LabeledElement Name="suppID"> + <Apply Function="odata.uriEncode"> + <Path>SupplierId</Path> + </Apply> + </LabeledElement> + </Apply> + </UrlRef> + </Annotation> + </Schema> + </edmx:DataServices> +</edmx:Edmx> \ No newline at end of file
