OLINGO-861: Fixing the recursive load of the references, and nested annotations
This commit is contained in:
parent
89a6a69de7
commit
548c6e4a15
|
@ -100,6 +100,7 @@ public class MetadataParser {
|
|||
private ReferenceResolver referenceResolver = new DefaultReferenceResolver();
|
||||
private boolean useLocalCoreVocabularies = true;
|
||||
private boolean implicitlyLoadCoreVocabularies = false;
|
||||
private boolean recusivelyLoadReferences = false;
|
||||
|
||||
/**
|
||||
* Avoid reading the annotations in the $metadata
|
||||
|
@ -131,6 +132,16 @@ public class MetadataParser {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the core libraries from local classpath
|
||||
* @param load true for yes; false otherwise
|
||||
* @return
|
||||
*/
|
||||
public MetadataParser recursivelyLoadReferences(boolean load) {
|
||||
this.recusivelyLoadReferences = load;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the core vocabularies, irrespective of if they are defined in the $metadata
|
||||
* @param load
|
||||
|
@ -143,7 +154,7 @@ public class MetadataParser {
|
|||
|
||||
public ServiceMetadata buildServiceMetadata(Reader csdl) throws XMLStreamException {
|
||||
SchemaBasedEdmProvider provider = buildEdmProvider(csdl, this.referenceResolver,
|
||||
this.implicitlyLoadCoreVocabularies, this.useLocalCoreVocabularies);
|
||||
this.implicitlyLoadCoreVocabularies, this.useLocalCoreVocabularies, true);
|
||||
return new ServiceMetadataImpl(provider, provider.getReferences(), null);
|
||||
}
|
||||
|
||||
|
@ -151,27 +162,27 @@ public class MetadataParser {
|
|||
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
|
||||
XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
|
||||
return buildEdmProvider(reader, this.referenceResolver,
|
||||
this.implicitlyLoadCoreVocabularies, this.useLocalCoreVocabularies);
|
||||
this.implicitlyLoadCoreVocabularies, this.useLocalCoreVocabularies, true);
|
||||
}
|
||||
|
||||
protected SchemaBasedEdmProvider buildEdmProvider(Reader csdl,
|
||||
ReferenceResolver resolver, boolean loadCore, boolean useLocal)
|
||||
ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas)
|
||||
throws XMLStreamException {
|
||||
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
|
||||
XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
|
||||
return buildEdmProvider(reader, resolver, loadCore, useLocal);
|
||||
return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas);
|
||||
}
|
||||
|
||||
protected SchemaBasedEdmProvider buildEdmProvider(InputStream csdl,
|
||||
ReferenceResolver resolver, boolean loadCore, boolean useLocal)
|
||||
ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas)
|
||||
throws XMLStreamException {
|
||||
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
|
||||
XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
|
||||
return buildEdmProvider(reader, resolver, loadCore, useLocal);
|
||||
return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas);
|
||||
}
|
||||
|
||||
protected SchemaBasedEdmProvider buildEdmProvider(XMLEventReader reader,
|
||||
ReferenceResolver resolver, boolean loadCore, boolean useLocal)
|
||||
ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas)
|
||||
throws XMLStreamException {
|
||||
SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider();
|
||||
|
||||
|
@ -211,7 +222,7 @@ public class MetadataParser {
|
|||
}
|
||||
|
||||
// load all the reference schemas
|
||||
if (resolver != null) {
|
||||
if (resolver != null && loadReferenceSchemas) {
|
||||
loadReferencesSchemas(provider, xmlBase.length() == 0 ? null
|
||||
: fixXmlBase(xmlBase.toString()), resolver, loadCore, useLocal);
|
||||
}
|
||||
|
@ -245,15 +256,17 @@ public class MetadataParser {
|
|||
} else {
|
||||
// do not implicitly load core vocabularies any more. But if the
|
||||
// references loading the core vocabularies try to use local if we can
|
||||
refProvider = buildEdmProvider(is, resolver, false, useLocal);
|
||||
refProvider = buildEdmProvider(is, resolver, false, useLocal, this.recusivelyLoadReferences);
|
||||
}
|
||||
}
|
||||
|
||||
CsdlSchema refSchema = refProvider.getSchema(include.getNamespace(), false);
|
||||
provider.addReferenceSchema(include.getNamespace(), refProvider);
|
||||
if (include.getAlias() != null) {
|
||||
refSchema.setAlias(include.getAlias());
|
||||
provider.addReferenceSchema(include.getAlias(), refProvider);
|
||||
if (refProvider != null) {
|
||||
CsdlSchema refSchema = refProvider.getSchema(include.getNamespace(), false);
|
||||
provider.addReferenceSchema(include.getNamespace(), refProvider);
|
||||
if (include.getAlias() != null) {
|
||||
refSchema.setAlias(include.getAlias());
|
||||
provider.addReferenceSchema(include.getAlias(), refProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (XMLStreamException e) {
|
||||
|
@ -295,7 +308,7 @@ public class MetadataParser {
|
|||
if (schema == null) {
|
||||
InputStream is = this.getClass().getClassLoader().getResourceAsStream(resource);
|
||||
if (is != null) {
|
||||
SchemaBasedEdmProvider childProvider = buildEdmProvider(is, null, false, false);
|
||||
SchemaBasedEdmProvider childProvider = buildEdmProvider(is, null, false, false, true);
|
||||
provider.addVocabularySchema(namespace, childProvider);
|
||||
} else {
|
||||
throw new XMLStreamException("failed to load "+resource+" core vocabulary");
|
||||
|
@ -654,17 +667,19 @@ public class MetadataParser {
|
|||
void build(XMLEventReader reader, StartElement element, T target, String name)
|
||||
throws XMLStreamException {
|
||||
|
||||
// attribute based expressions.
|
||||
readAttributeExpressions(element, target);
|
||||
|
||||
// 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("Annotation")) {
|
||||
// attribute based expressions.
|
||||
readAttributeExpressions(element, target);
|
||||
|
||||
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")) {
|
||||
|
@ -719,6 +734,8 @@ public class MetadataParser {
|
|||
expr.setType(attr(element, "Type"));
|
||||
readPropertyValues(reader, element, expr);
|
||||
write(target, expr);
|
||||
} else if (name.equals("Annotation")) {
|
||||
readAnnotations(reader, element, (CsdlAnnotatable)target);
|
||||
}
|
||||
}
|
||||
}.read(reader, element, target, "Collection", "AnnotationPath",
|
||||
|
@ -726,7 +743,7 @@ public class MetadataParser {
|
|||
"Apply", "Function", "Cast", "If", "IsOf", "LabeledElement",
|
||||
"LabeledElementReference", "Null", "Record","Binary", "Bool", "Date",
|
||||
"DateTimeOffset", "Decimal", "Duration", "EnumMember", "Float", "Guid",
|
||||
"Int", "String", "TimeOfDay");
|
||||
"Int", "String", "TimeOfDay", "Annotation");
|
||||
}
|
||||
|
||||
private <T> void readAttributeExpressions(StartElement element, T target)
|
||||
|
@ -781,13 +798,17 @@ public class MetadataParser {
|
|||
@Override
|
||||
void build(XMLEventReader reader, StartElement element, CsdlRecord record, String name)
|
||||
throws XMLStreamException {
|
||||
CsdlPropertyValue value = new CsdlPropertyValue();
|
||||
value.setProperty(attr(element, "Property"));
|
||||
readAttributeExpressions(element, value);
|
||||
readExpressions(reader, element, value);
|
||||
record.getPropertyValues().add(value);
|
||||
if (name.equals("PropertyValue")) {
|
||||
CsdlPropertyValue value = new CsdlPropertyValue();
|
||||
value.setProperty(attr(element, "Property"));
|
||||
readAttributeExpressions(element, value);
|
||||
readExpressions(reader, element, value);
|
||||
record.getPropertyValues().add(value);
|
||||
} else if (name.equals("Annotation")) {
|
||||
readAnnotations(reader, element, record);
|
||||
}
|
||||
}
|
||||
}.read(reader, element, record, "PropertyValue");
|
||||
}.read(reader, element, record, "PropertyValue", "Annotation");
|
||||
}
|
||||
|
||||
private void readFunction(XMLEventReader reader, StartElement element, CsdlSchema schema)
|
||||
|
@ -1134,7 +1155,7 @@ public class MetadataParser {
|
|||
}
|
||||
|
||||
abstract class ElementReader<T> {
|
||||
void read(XMLEventReader reader, StartElement element, T t, String... names)
|
||||
void read(XMLEventReader reader, StartElement parentElement, T t, String... names)
|
||||
throws XMLStreamException {
|
||||
while (reader.hasNext()) {
|
||||
XMLEvent event = reader.peek();
|
||||
|
@ -1153,11 +1174,17 @@ public class MetadataParser {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (parentElement != null && event.isEndElement()
|
||||
&& ((EndElement) event).getName().equals(parentElement.getName())) {
|
||||
// end reached
|
||||
break;
|
||||
}
|
||||
|
||||
boolean hit = false;
|
||||
|
||||
for (String name : names) {
|
||||
if (event.isStartElement()) {
|
||||
element = event.asStartElement();
|
||||
StartElement element = event.asStartElement();
|
||||
if (element.getName().getLocalPart().equals(name)) {
|
||||
reader.nextEvent(); // advance cursor start which is current
|
||||
build(reader, element, t, name);
|
||||
|
|
|
@ -110,6 +110,9 @@ public class MetadataParserAnnotationsTest {
|
|||
assertEquals(7, apply.getParameters().size());
|
||||
assertTrue(apply.getParameters().get(1) instanceof CsdlPath);
|
||||
assertTrue(apply.getParameters().get(4) instanceof CsdlConstantExpression);
|
||||
|
||||
assertEquals("OData.Description", apply.getAnnotations().get(0).getTerm());
|
||||
assertEquals("concat apply", apply.getAnnotations().get(0).getExpression().asConstant().getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -148,6 +151,10 @@ public class MetadataParserAnnotationsTest {
|
|||
CsdlIsOf isOf = (CsdlIsOf)a.getExpression();
|
||||
assertEquals("Self.PreferredCustomer", isOf.getType());
|
||||
assertTrue(isOf.getValue() instanceof CsdlPath);
|
||||
|
||||
assertEquals("OData.Description", isOf.getAnnotations().get(0).getTerm());
|
||||
assertEquals("preferred customer", isOf.getAnnotations().get(0).getExpression().asConstant().getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -186,6 +193,8 @@ public class MetadataParserAnnotationsTest {
|
|||
CsdlPropertyValue value = expr.getPropertyValues().get(0);
|
||||
assertEquals("NonUpdatableNavigationProperties", value.getProperty());
|
||||
assertTrue(value.getValue() instanceof CsdlCollection);
|
||||
assertEquals("OData.Description", expr.getAnnotations().get(0).getTerm());
|
||||
assertEquals("descripiton test", expr.getAnnotations().get(0).getExpression().asConstant().getValue());
|
||||
|
||||
CsdlCollection collection = (CsdlCollection)value.getValue();
|
||||
assertEquals(2, collection.getItems().size());
|
||||
|
|
|
@ -24,7 +24,11 @@ import static org.junit.Assert.assertNotNull;
|
|||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.olingo.commons.api.ex.ODataException;
|
||||
|
@ -187,5 +191,26 @@ public class MetadataParserTest {
|
|||
public void testParsingWithNoFormat() throws Exception {
|
||||
MetadataParser parser = new MetadataParser();
|
||||
provider = (CsdlEdmProvider) parser.buildEdmProvider(new FileReader("src/test/resources/skip-annotation.xml"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferenceLoad() throws Exception {
|
||||
MetadataParser parser = new MetadataParser();
|
||||
parser.recursivelyLoadReferences(false);
|
||||
parser.referenceResolver(new ReferenceResolver() {
|
||||
@Override
|
||||
public InputStream resolveReference(URI uri, String xmlBase) {
|
||||
String str = uri.toASCIIString();
|
||||
if (str.startsWith("http://localhost/")) {
|
||||
try {
|
||||
return new FileInputStream("src/test/resources/"+str.substring(17));
|
||||
} catch (FileNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
provider = (CsdlEdmProvider) parser.buildEdmProvider(new FileReader("src/test/resources/test.xml"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?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:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/errata03/csd01/complete/vocabularies/Org.OData.Core.V1.xml">
|
||||
<edmx:Include Namespace="Org.OData.Core.V1" Alias="OData"/>
|
||||
</edmx:Reference>
|
||||
|
||||
<edmx:Reference Uri="http://localhost/b.xml">
|
||||
<edmx:Include Namespace="org.apache.olingo.b" Alias="B"/>
|
||||
</edmx:Reference>
|
||||
|
||||
<edmx:DataServices>
|
||||
|
||||
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="org.apache.olingo.a">
|
||||
|
||||
<Term Name="ExtendedInfo" Type="Collection(Message.Message)" Nullable="false">
|
||||
<Annotation Term="OData.Description" String="The ExtendedInfo annotation can be applied to any object or property to provide additional information about the item."/>
|
||||
</Term>
|
||||
|
||||
</Schema>
|
||||
|
||||
</edmx:DataServices>
|
||||
</edmx:Edmx>
|
|
@ -52,6 +52,7 @@
|
|||
</String>
|
||||
<Path>Available/Unit</Path>
|
||||
<String> available)</String>
|
||||
<Annotation Term="OData.Description" String="concat apply"/>
|
||||
</Apply>
|
||||
</Annotation>
|
||||
|
||||
|
@ -79,6 +80,7 @@
|
|||
<Annotation Term="Self.IsPreferredCustomer">
|
||||
<IsOf Type="Self.PreferredCustomer">
|
||||
<Path>Customer</Path>
|
||||
<Annotation Term="OData.Description" String="preferred customer"/>
|
||||
</IsOf>
|
||||
</Annotation>
|
||||
|
||||
|
@ -105,6 +107,7 @@
|
|||
<NavigationPropertyPath>Category</NavigationPropertyPath>
|
||||
</Collection>
|
||||
</PropertyValue>
|
||||
<Annotation Term="OData.Description" String="descripiton test"/>
|
||||
</Record>
|
||||
</Annotation>
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?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:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/errata03/csd01/complete/vocabularies/Org.OData.Core.V1.xml">
|
||||
<edmx:Include Namespace="Org.OData.Core.V1" Alias="OData"/>
|
||||
</edmx:Reference>
|
||||
|
||||
<edmx:Reference Uri="http://localhost/a.xml">
|
||||
<edmx:Include Namespace="org.apache.olingo.a" Alias="A2"/>
|
||||
</edmx:Reference>
|
||||
|
||||
<edmx:DataServices>
|
||||
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="org.apache.olingo.b">
|
||||
<Term Name="ExtendedInfo" Type="Collection(Message.Message)" Nullable="false">
|
||||
<Annotation Term="OData.Description" String="The ExtendedInfo annotation can be applied to any object or property to provide additional information about the item."/>
|
||||
</Term>
|
||||
</Schema>
|
||||
</edmx:DataServices>
|
||||
</edmx:Edmx>
|
|
@ -0,0 +1,26 @@
|
|||
<?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 Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
|
||||
<edmx:Reference Uri="http://localhost/a.xml">
|
||||
<edmx:Include Alias="A" Namespace="org.apache.olingo.a" />
|
||||
</edmx:Reference>
|
||||
<edmx:DataServices>
|
||||
<Schema Namespace="Microsoft.OData.SampleService.Models.TripPin"
|
||||
xmlns="http://docs.oasis-open.org/odata/ns/edm">
|
||||
<ComplexType Name="City">
|
||||
<Property Name="CountryRegion" Type="Edm.String" Nullable="false" />
|
||||
<Property Name="Name" Type="Edm.String" Nullable="false" />
|
||||
<Property Name="Region" Type="Edm.String" Nullable="false" />
|
||||
</ComplexType>
|
||||
</Schema>
|
||||
</edmx:DataServices>
|
||||
</edmx:Edmx>
|
Loading…
Reference in New Issue