You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ra...@apache.org on 2018/04/05 17:42:15 UTC

olingo-odata4 git commit: OLINGO-1252: adding ability load reference schemas recursively, but locallized to the schema they represent

Repository: olingo-odata4
Updated Branches:
  refs/heads/master d9aff6300 -> fd8bfa33d


OLINGO-1252: adding ability load reference schemas recursively, but locallized to the schema they represent


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/fd8bfa33
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/fd8bfa33
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/fd8bfa33

Branch: refs/heads/master
Commit: fd8bfa33d485e6ea158025d468a009cd8bfc19ff
Parents: d9aff63
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Thu Apr 5 12:41:42 2018 -0500
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Thu Apr 5 12:41:42 2018 -0500

----------------------------------------------------------------------
 .../olingo/server/core/MetadataParser.java      | 59 ++++++++++------
 .../server/core/SchemaBasedEdmProvider.java     | 48 +++++++------
 .../olingo/server/core/MetadataParserTest.java  | 73 ++++++++++++++++----
 3 files changed, 122 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fd8bfa33/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 88b8ad2..63b33d7 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
@@ -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)
-      throws XMLStreamException {
+  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);
+    XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
+    return buildEdmProvider(reader, resolver, loadCore, useLocal, loadReferenceSchemas, namespace);
   }
-    
-  protected SchemaBasedEdmProvider buildEdmProvider(InputStream csdl,
-      ReferenceResolver resolver, boolean loadCore, boolean useLocal, boolean loadReferenceSchemas)
-      throws XMLStreamException {
+
+  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();
     
@@ -220,7 +225,11 @@ public class MetadataParser {
       loadCoreVocabulary(provider, "Org.OData.Capabilities.V1");
       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;
           }
           
@@ -248,15 +257,19 @@ public class MetadataParser {
             loadCoreVocabulary(provider, include.getNamespace());
             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) {
               throw new EdmException("Failed to load Reference "+reference.getUri()+" loading failed");
             } 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);
+              // references loading the core vocabularies try to use local if we can
+              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");

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fd8bfa33/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
index 128aecb..e11cffc 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
@@ -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;
+    return null;
   }
 
-  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

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/fd8bfa33/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 a0e6aeb..c3e67e0 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
@@ -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"));
+
+  }
 }