OLINGO-1252: adding ability load reference schemas recursively, but locallized to the schema they represent
This commit is contained in:
parent
d9aff6300f
commit
fd8bfa33d4
|
@ -27,6 +27,8 @@ import java.net.URISyntaxException;
|
|||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
|
@ -100,7 +102,8 @@ public class MetadataParser {
|
|||
private ReferenceResolver referenceResolver = new DefaultReferenceResolver();
|
||||
private boolean useLocalCoreVocabularies = true;
|
||||
private boolean implicitlyLoadCoreVocabularies = false;
|
||||
private boolean recusivelyLoadReferences = false;
|
||||
private boolean recursivelyLoadReferences = false;
|
||||
private Map<String, SchemaBasedEdmProvider> globalReferenceMap = new HashMap<String, SchemaBasedEdmProvider>();
|
||||
|
||||
/**
|
||||
* Avoid reading the annotations in the $metadata
|
||||
|
@ -138,7 +141,7 @@ public class MetadataParser {
|
|||
* @return
|
||||
*/
|
||||
public MetadataParser recursivelyLoadReferences(boolean load) {
|
||||
this.recusivelyLoadReferences = load;
|
||||
this.recursivelyLoadReferences = load;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -154,35 +157,37 @@ public class MetadataParser {
|
|||
|
||||
public ServiceMetadata buildServiceMetadata(Reader csdl) throws XMLStreamException {
|
||||
SchemaBasedEdmProvider provider = buildEdmProvider(csdl, this.referenceResolver,
|
||||
this.implicitlyLoadCoreVocabularies, this.useLocalCoreVocabularies, true);
|
||||
this.implicitlyLoadCoreVocabularies, this.useLocalCoreVocabularies, true, null);
|
||||
return new ServiceMetadataImpl(provider, provider.getReferences(), null);
|
||||
}
|
||||
|
||||
public SchemaBasedEdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException {
|
||||
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
|
||||
XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
|
||||
return buildEdmProvider(reader, this.referenceResolver,
|
||||
this.implicitlyLoadCoreVocabularies, this.useLocalCoreVocabularies, true);
|
||||
return buildEdmProvider(reader, this.referenceResolver, this.implicitlyLoadCoreVocabularies,
|
||||
this.useLocalCoreVocabularies, true, null);
|
||||
}
|
||||
|
||||
protected SchemaBasedEdmProvider buildEdmProvider(Reader csdl,
|
||||
ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas)
|
||||
protected SchemaBasedEdmProvider buildEdmProvider(Reader csdl, ReferenceResolver resolver,
|
||||
boolean loadCore, boolean useLocal,
|
||||
boolean loadReferenceSchemas, String namespace)
|
||||
throws XMLStreamException {
|
||||
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
|
||||
XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
|
||||
return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas);
|
||||
return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas, namespace);
|
||||
}
|
||||
|
||||
protected SchemaBasedEdmProvider buildEdmProvider(InputStream csdl,
|
||||
ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas)
|
||||
protected SchemaBasedEdmProvider buildEdmProvider(InputStream csdl, ReferenceResolver resolver,
|
||||
boolean loadCore, boolean useLocal,
|
||||
boolean loadReferenceSchemas, String namespace)
|
||||
throws XMLStreamException {
|
||||
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
|
||||
XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
|
||||
return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas);
|
||||
return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas, namespace);
|
||||
}
|
||||
|
||||
protected SchemaBasedEdmProvider buildEdmProvider(XMLEventReader reader,
|
||||
ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas)
|
||||
ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas, String namespace)
|
||||
throws XMLStreamException {
|
||||
SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider();
|
||||
|
||||
|
@ -221,6 +226,10 @@ public class MetadataParser {
|
|||
loadCoreVocabulary(provider, "Org.OData.Measures.V1");
|
||||
}
|
||||
|
||||
if (namespace != null && !namespace.equals("") && !globalReferenceMap.containsKey(namespace)) {
|
||||
globalReferenceMap.put(namespace, provider);
|
||||
}
|
||||
|
||||
// load all the reference schemas
|
||||
if (resolver != null && loadReferenceSchemas) {
|
||||
loadReferencesSchemas(provider, xmlBase.length() == 0 ? null
|
||||
|
@ -239,8 +248,8 @@ public class MetadataParser {
|
|||
|
||||
for (EdmxReferenceInclude include : reference.getIncludes()) {
|
||||
|
||||
// check if the schema is already loaded before.
|
||||
if (provider.getSchema(include.getNamespace()) != null) {
|
||||
// check if the schema is already loaded before in current provider.
|
||||
if (provider.getSchemaDirectly(include.getNamespace()) != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -249,6 +258,9 @@ public class MetadataParser {
|
|||
continue;
|
||||
}
|
||||
|
||||
// check if the schema is already loaded before in parent providers
|
||||
refProvider = this.globalReferenceMap.get(include.getNamespace());
|
||||
|
||||
if (refProvider == null) {
|
||||
InputStream is = this.referenceResolver.resolveReference(reference.getUri(), xmlBase);
|
||||
if (is == null) {
|
||||
|
@ -256,7 +268,8 @@ 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, this.recusivelyLoadReferences);
|
||||
refProvider = buildEdmProvider(is, resolver, false, useLocal,
|
||||
this.recursivelyLoadReferences, include.getNamespace());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,7 +321,7 @@ public class MetadataParser {
|
|||
if (schema == null) {
|
||||
InputStream is = this.getClass().getClassLoader().getResourceAsStream(resource);
|
||||
if (is != null) {
|
||||
SchemaBasedEdmProvider childProvider = buildEdmProvider(is, null, false, false, true);
|
||||
SchemaBasedEdmProvider childProvider = buildEdmProvider(is, null, false, false, true, "");
|
||||
provider.addVocabularySchema(namespace, childProvider);
|
||||
} else {
|
||||
throw new XMLStreamException("failed to load "+resource+" core vocabulary");
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
package org.apache.olingo.server.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.olingo.commons.api.edm.FullQualifiedName;
|
||||
|
@ -88,38 +90,44 @@ public class SchemaBasedEdmProvider implements CsdlEdmProvider {
|
|||
}
|
||||
|
||||
CsdlSchema getSchema(String ns, boolean checkReferences) {
|
||||
if (checkReferences) {
|
||||
return getSchemaRecursively(ns, new HashSet<String>());
|
||||
} else {
|
||||
return getSchemaDirectly(ns);
|
||||
}
|
||||
}
|
||||
|
||||
CsdlSchema getSchemaDirectly(String ns) {
|
||||
for (CsdlSchema s : this.edmSchemas) {
|
||||
if (s.getNamespace().equals(ns)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
CsdlSchema s = null;
|
||||
if (checkReferences) {
|
||||
s = getReferenceSchema(ns);
|
||||
if (s == null) {
|
||||
s = getVocabularySchema(ns);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
CsdlSchema getReferenceSchema(String ns) {
|
||||
if (ns == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.referenceSchemas.get(ns) != null) {
|
||||
return this.referenceSchemas.get(ns).getSchema(ns);
|
||||
CsdlSchema getSchemaRecursively(String ns, Set<String> parsedPath) {
|
||||
// find the schema by namespace in current provider
|
||||
CsdlSchema schema = getSchemaDirectly(ns);
|
||||
if (schema != null) {
|
||||
return schema;
|
||||
}
|
||||
|
||||
// it is possible that we may be looking for Reference schema of Reference
|
||||
for (SchemaBasedEdmProvider provider:this.referenceSchemas.values()) {
|
||||
CsdlSchema schema = provider.getSchema(ns);
|
||||
// find the schema by namespace in the reference schema provider
|
||||
for (Map.Entry<String, SchemaBasedEdmProvider> entry : this.referenceSchemas.entrySet()) {
|
||||
String namespace = entry.getKey();
|
||||
if (parsedPath.contains(namespace)) {
|
||||
continue;
|
||||
}
|
||||
SchemaBasedEdmProvider provider = entry.getValue();
|
||||
parsedPath.add(namespace);
|
||||
schema = provider.getSchemaRecursively(ns, parsedPath);
|
||||
if (schema != null) {
|
||||
return schema;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
return getVocabularySchema(ns);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.apache.olingo.commons.api.edm.provider.CsdlNavigationPropertyBinding;
|
|||
import org.apache.olingo.commons.api.edm.provider.CsdlParameter;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
|
||||
import org.apache.olingo.commons.api.edm.provider.CsdlSingleton;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -56,6 +57,21 @@ public class MetadataParserTest {
|
|||
|
||||
CsdlEdmProvider provider = null;
|
||||
|
||||
ReferenceResolver testReferenceResolver = 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;
|
||||
}
|
||||
};
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MetadataParser parser = new MetadataParser();
|
||||
|
@ -197,20 +213,47 @@ public class MetadataParserTest {
|
|||
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;
|
||||
}
|
||||
});
|
||||
parser.referenceResolver(this.testReferenceResolver);
|
||||
provider = (CsdlEdmProvider) parser.buildEdmProvider(new FileReader("src/test/resources/test.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferenceLoadRecursively() throws Exception {
|
||||
MetadataParser parser = new MetadataParser();
|
||||
parser.recursivelyLoadReferences(true);
|
||||
parser.referenceResolver(testReferenceResolver);
|
||||
SchemaBasedEdmProvider providerTest = parser.buildEdmProvider(new FileReader("src/test/resources/test.xml"));
|
||||
|
||||
Assert.assertNotNull(providerTest.getSchema("Microsoft.OData.SampleService.Models.TripPin", false));
|
||||
|
||||
Assert.assertNull(providerTest.getSchema("org.apache.olingo.a", false));
|
||||
Assert.assertNull(providerTest.getSchema("org.apache.olingo.b", false));
|
||||
|
||||
Assert.assertNotNull(providerTest.getSchema("org.apache.olingo.a", true));
|
||||
Assert.assertNotNull(providerTest.getSchema("org.apache.olingo.b", true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCircleReferenceShouldNotStackOverflow() throws Exception {
|
||||
MetadataParser parser = new MetadataParser();
|
||||
parser.recursivelyLoadReferences(true);
|
||||
parser.referenceResolver(testReferenceResolver);
|
||||
SchemaBasedEdmProvider providerTest = parser.buildEdmProvider(new FileReader("src/test/resources/test.xml"));
|
||||
|
||||
Assert.assertNull(providerTest.getSchema("Not Found", true));
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadCoreVocabulary() throws Exception {
|
||||
MetadataParser parser = new MetadataParser();
|
||||
parser.implicitlyLoadCoreVocabularies(true);
|
||||
parser.referenceResolver(testReferenceResolver);
|
||||
SchemaBasedEdmProvider provider = parser.buildEdmProvider(new FileReader("src/test/resources/test.xml"));
|
||||
|
||||
Assert.assertNotNull(provider.getVocabularySchema("Org.OData.Core.V1"));
|
||||
Assert.assertNotNull(provider.getSchema("Org.OData.Core.V1"));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue