You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by fm...@apache.org on 2013/07/26 13:22:25 UTC

[20/51] [partial] initial commit

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParser.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParser.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParser.java
new file mode 100644
index 0000000..8e3e3dd
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParser.java
@@ -0,0 +1,965 @@
+/*******************************************************************************
+ * 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.odata2.core.edm.parser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAction;
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmContentKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationElement;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.CustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.provider.DataServices;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainer;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.Facets;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImportParameter;
+import org.apache.olingo.odata2.api.edm.provider.Key;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.OnDelete;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.PropertyRef;
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraint;
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraintRole;
+import org.apache.olingo.odata2.api.edm.provider.ReturnType;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.api.edm.provider.Using;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import java.util.HashSet;
+import java.util.Set;
+
+public class EdmParser {
+
+  private Map<String, Set<String>> inscopeMap = new HashMap<String, Set<String>>();
+  private Map<String, String> aliasNamespaceMap = new HashMap<String, String>();
+  private Map<String, String> xmlNamespaceMap;
+  private Map<String, String> mandatoryNamespaces;
+  private Map<FullQualifiedName, EntityType> entityTypesMap = new HashMap<FullQualifiedName, EntityType>();
+  private Map<FullQualifiedName, ComplexType> complexTypesMap = new HashMap<FullQualifiedName, ComplexType>();
+  private Map<FullQualifiedName, Association> associationsMap = new HashMap<FullQualifiedName, Association>();
+  private Map<FullQualifiedName, EntityContainer> containerMap = new HashMap<FullQualifiedName, EntityContainer>();
+  private List<NavigationProperty> navProperties = new ArrayList<NavigationProperty>();
+  private String currentHandledStartTagName;
+  private String currentNamespace;
+  private final String DEFAULT_NAMESPACE = "";
+
+  public DataServices readMetadata(final XMLStreamReader reader, final boolean validate)
+      throws EntityProviderException {
+    try {
+      initialize();
+      DataServices dataServices = new DataServices();
+      List<Schema> schemas = new ArrayList<Schema>();
+
+      while (reader.hasNext()
+          && !(reader.isEndElement() && Edm.NAMESPACE_EDMX_2007_06.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_DATA_SERVICES.equals(reader.getLocalName()))) {
+        reader.next();
+        if (reader.isStartElement()) {
+          extractNamespaces(reader);
+          if (EdmParserConstants.EDM_SCHEMA.equals(reader.getLocalName())) {
+            schemas.add(readSchema(reader));
+          } else if (EdmParserConstants.EDM_DATA_SERVICES.equals(reader
+              .getLocalName())) {
+            dataServices.setDataServiceVersion(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, "DataServiceVersion"));
+          }
+        }
+      }
+      if (validate) {
+        validate();
+      }
+      dataServices.setSchemas(schemas);
+      reader.close();
+      return dataServices;
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+
+  }
+
+  private Schema readSchema(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_SCHEMA);
+
+    Schema schema = new Schema();
+    List<Using> usings = new ArrayList<Using>();
+    List<ComplexType> complexTypes = new ArrayList<ComplexType>();
+    List<EntityType> entityTypes = new ArrayList<EntityType>();
+    List<Association> associations = new ArrayList<Association>();
+    List<EntityContainer> entityContainers = new ArrayList<EntityContainer>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+
+    schema.setNamespace(reader.getAttributeValue(null, EdmParserConstants.EDM_SCHEMA_NAMESPACE));
+    this.inscopeMap.put(schema.getNamespace(), new HashSet<String>());
+    schema.setAlias(reader.getAttributeValue(null, EdmParserConstants.EDM_SCHEMA_ALIAS));
+    schema.setAnnotationAttributes(readAnnotationAttribute(reader));
+    currentNamespace = schema.getNamespace();
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_SCHEMA.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_USING.equals(currentHandledStartTagName)) {
+          usings.add(readUsing(reader, schema.getNamespace()));
+        } else if (EdmParserConstants.EDM_ENTITY_TYPE.equals(currentHandledStartTagName)) {
+          entityTypes.add(readEntityType(reader));
+        } else if (EdmParserConstants.EDM_COMPLEX_TYPE.equals(currentHandledStartTagName)) {
+          complexTypes.add(readComplexType(reader));
+        } else if (EdmParserConstants.EDM_ASSOCIATION.equals(currentHandledStartTagName)) {
+          associations.add(readAssociation(reader));
+        } else if (EdmParserConstants.EDM_ENTITY_CONTAINER.equals(currentHandledStartTagName)) {
+          entityContainers.add(readEntityContainer(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (schema.getAlias() != null) {
+      aliasNamespaceMap.put(schema.getAlias(), schema.getNamespace());
+    }
+    schema.setUsings(usings).setEntityTypes(entityTypes).setComplexTypes(complexTypes).setAssociations(associations).setEntityContainers(entityContainers).setAnnotationElements(annotationElements);
+    return schema;
+  }
+
+    private Using readUsing(final XMLStreamReader reader, final String schemaNamespace) 
+            throws XMLStreamException, EntityProviderException {
+        
+        reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_USING);
+
+        Using using = new Using();
+        using.setNamespace(reader.getAttributeValue(null, EdmParserConstants.EDM_SCHEMA_NAMESPACE));
+        this.inscopeMap.get(schemaNamespace).add(using.getNamespace());
+        using.setAlias(reader.getAttributeValue(null, EdmParserConstants.EDM_SCHEMA_ALIAS));
+        using.setAnnotationAttributes(readAnnotationAttribute(reader));
+
+        List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+        while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI())
+                && EdmParserConstants.EDM_USING.equals(reader.getLocalName()))) {
+            
+            reader.next();
+            if (reader.isStartElement()) {
+                extractNamespaces(reader);
+                currentHandledStartTagName = reader.getLocalName();
+                annotationElements.add(readAnnotationElement(reader));
+            }
+        }
+        using.setAnnotationElements(annotationElements);
+
+        if (using.getAlias() != null) {
+            aliasNamespaceMap.put(using.getAlias(), using.getNamespace());
+        }
+
+        return using;
+    }
+  
+  private EntityContainer readEntityContainer(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ENTITY_CONTAINER);
+    EntityContainer container = new EntityContainer();
+    List<EntitySet> entitySets = new ArrayList<EntitySet>();
+    List<AssociationSet> associationSets = new ArrayList<AssociationSet>();
+    List<FunctionImport> functionImports = new ArrayList<FunctionImport>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+
+    container.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    if (reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, "IsDefaultEntityContainer") != null) {
+      container.setDefaultEntityContainer("true".equalsIgnoreCase(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, "IsDefaultEntityContainer")));
+    }
+    container.setExtendz(reader.getAttributeValue(null, EdmParserConstants.EDM_CONTAINER_EXTENDZ));
+    container.setAnnotationAttributes(readAnnotationAttribute(reader));
+
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ENTITY_CONTAINER.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ENTITY_SET.equals(currentHandledStartTagName)) {
+          entitySets.add(readEntitySet(reader));
+        } else if (EdmParserConstants.EDM_ASSOCIATION_SET.equals(currentHandledStartTagName)) {
+          associationSets.add(readAssociationSet(reader));
+        } else if (EdmParserConstants.EDM_FUNCTION_IMPORT.equals(currentHandledStartTagName)) {
+          functionImports.add(readFunctionImport(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    container.setEntitySets(entitySets).setAssociationSets(associationSets).setFunctionImports(functionImports).setAnnotationElements(annotationElements);
+
+    containerMap.put(new FullQualifiedName(currentNamespace, container.getName()), container);
+    return container;
+  }
+
+  private FunctionImport readFunctionImport(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_FUNCTION_IMPORT);
+    FunctionImport function = new FunctionImport();
+    List<FunctionImportParameter> functionParameters = new ArrayList<FunctionImportParameter>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+
+    function.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    function.setHttpMethod(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.EDM_FUNCTION_IMPORT_HTTP_METHOD));
+    function.setEntitySet(reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_SET));
+    ReturnType returnType = new ReturnType();
+    String returnTypeString = reader.getAttributeValue(null, EdmParserConstants.EDM_FUNCTION_IMPORT_RETURN);
+    if (returnTypeString != null) {
+      if (returnTypeString.startsWith("Collection") || returnTypeString.startsWith("collection")) {
+        returnType.setMultiplicity(EdmMultiplicity.MANY);
+        returnTypeString = returnTypeString.substring(returnTypeString.indexOf("(") + 1, returnTypeString.length() - 1);
+        if (function.getEntitySet() == null) {
+          //				throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("EntitySet");
+        }
+      }
+      FullQualifiedName fqName = extractFQName(returnTypeString);
+      returnType.setTypeName(fqName);
+      function.setReturnType(returnType);
+    }
+    function.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_FUNCTION_IMPORT.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_FUNCTION_PARAMETER.equals(currentHandledStartTagName)) {
+          functionParameters.add(readFunctionImportParameter(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    function.setParameters(functionParameters).setAnnotationElements(annotationElements);
+    return function;
+  }
+
+  private FunctionImportParameter readFunctionImportParameter(final XMLStreamReader reader) throws EntityProviderException, XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_FUNCTION_PARAMETER);
+    FunctionImportParameter functionParameter = new FunctionImportParameter();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+
+    functionParameter.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String type = reader.getAttributeValue(null, EdmParserConstants.EDM_TYPE);
+    if (type == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_TYPE).addContent(EdmParserConstants.EDM_FUNCTION_PARAMETER));
+    }
+    functionParameter.setType(EdmSimpleTypeKind.valueOf(extractFQName(type).getName()));
+    functionParameter.setFacets(readFacets(reader));
+    functionParameter.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_FUNCTION_IMPORT.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    functionParameter.setAnnotationElements(annotationElements);
+    return functionParameter;
+  }
+
+  private AssociationSet readAssociationSet(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION_SET);
+    AssociationSet associationSet = new AssociationSet();
+    List<AssociationSetEnd> ends = new ArrayList<AssociationSetEnd>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+
+    associationSet.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String association = reader.getAttributeValue(null, EdmParserConstants.EDM_ASSOCIATION);
+    if (association != null) {
+      associationSet.setAssociation(extractFQName(association));
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_ASSOCIATION).addContent(EdmParserConstants.EDM_ASSOCIATION_SET));
+    }
+    associationSet.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ASSOCIATION_SET.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ASSOCIATION_END.equals(currentHandledStartTagName)) {
+          AssociationSetEnd associationSetEnd = new AssociationSetEnd();
+          associationSetEnd.setEntitySet(reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_SET));
+          associationSetEnd.setRole(reader.getAttributeValue(null, EdmParserConstants.EDM_ROLE));
+          ends.add(associationSetEnd);
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (ends.size() != 2) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Count of AssociationSet ends should be 2"));
+    } else {
+      associationSet.setEnd1(ends.get(0)).setEnd2(ends.get(1));
+    }
+    associationSet.setAnnotationElements(annotationElements);
+    return associationSet;
+  }
+
+  private EntitySet readEntitySet(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ENTITY_SET);
+    EntitySet entitySet = new EntitySet();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    entitySet.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String entityType = reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_TYPE);
+    if (entityType != null) {
+      FullQualifiedName fqName = extractFQName(entityType);
+      entitySet.setEntityType(fqName);
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_ENTITY_TYPE).addContent(EdmParserConstants.EDM_ENTITY_SET));
+    }
+    entitySet.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ENTITY_SET.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    entitySet.setAnnotationElements(annotationElements);
+    return entitySet;
+  }
+
+  private Association readAssociation(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION);
+
+    Association association = new Association();
+    association.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    List<AssociationEnd> associationEnds = new ArrayList<AssociationEnd>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    association.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ASSOCIATION.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ASSOCIATION_END.equals(currentHandledStartTagName)) {
+          associationEnds.add(readAssociationEnd(reader));
+        } else if (EdmParserConstants.EDM_ASSOCIATION_CONSTRAINT.equals(currentHandledStartTagName)) {
+          association.setReferentialConstraint(readReferentialConstraint(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (associationEnds.size() < 2 && associationEnds.size() > 2) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Count of association ends should be 2"));
+    }
+
+    association.setEnd1(associationEnds.get(0)).setEnd2(associationEnds.get(1)).setAnnotationElements(annotationElements);
+    associationsMap.put(new FullQualifiedName(currentNamespace, association.getName()), association);
+    return association;
+  }
+
+  private ReferentialConstraint readReferentialConstraint(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION_CONSTRAINT);
+    ReferentialConstraint refConstraint = new ReferentialConstraint();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    refConstraint.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ASSOCIATION_CONSTRAINT.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ASSOCIATION_PRINCIPAL.equals(currentHandledStartTagName)) {
+          reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION_PRINCIPAL);
+          refConstraint.setPrincipal(readReferentialConstraintRole(reader));
+        } else if (EdmParserConstants.EDM_ASSOCIATION_DEPENDENT.equals(currentHandledStartTagName)) {
+          reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION_DEPENDENT);
+          refConstraint.setDependent(readReferentialConstraintRole(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    refConstraint.setAnnotationElements(annotationElements);
+    return refConstraint;
+  }
+
+  private ReferentialConstraintRole readReferentialConstraintRole(final XMLStreamReader reader) throws EntityProviderException, XMLStreamException {
+    ReferentialConstraintRole rcRole = new ReferentialConstraintRole();
+    rcRole.setRole(reader.getAttributeValue(null, EdmParserConstants.EDM_ROLE));
+    List<PropertyRef> propertyRefs = new ArrayList<PropertyRef>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    rcRole.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI())
+        && (EdmParserConstants.EDM_ASSOCIATION_PRINCIPAL.equals(reader.getLocalName()) || EdmParserConstants.EDM_ASSOCIATION_DEPENDENT.equals(reader.getLocalName())))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_PROPERTY_REF.equals(currentHandledStartTagName)) {
+          propertyRefs.add(readPropertyRef(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    rcRole.setPropertyRefs(propertyRefs).setAnnotationElements(annotationElements);
+    return rcRole;
+  }
+
+  private ComplexType readComplexType(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_COMPLEX_TYPE);
+
+    ComplexType complexType = new ComplexType();
+    List<Property> properties = new ArrayList<Property>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    complexType.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String baseType = reader.getAttributeValue(null, EdmParserConstants.EDM_BASE_TYPE);
+    if (baseType != null) {
+      complexType.setBaseType(extractFQName(baseType));
+    }
+    if (reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_TYPE_ABSTRACT) != null) {
+      complexType.setAbstract("true".equalsIgnoreCase(reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_TYPE_ABSTRACT)));
+    }
+    complexType.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_COMPLEX_TYPE.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_PROPERTY.equals(currentHandledStartTagName)) {
+          properties.add(readProperty(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    complexType.setProperties(properties).setAnnotationElements(annotationElements);
+    if (complexType.getName() != null) {
+      FullQualifiedName fqName = new FullQualifiedName(currentNamespace, complexType.getName());
+      complexTypesMap.put(fqName, complexType);
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("Name"));
+    }
+    return complexType;
+
+  }
+
+  private EntityType readEntityType(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ENTITY_TYPE);
+    EntityType entityType = new EntityType();
+    List<Property> properties = new ArrayList<Property>();
+    List<NavigationProperty> navProperties = new ArrayList<NavigationProperty>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    Key key = null;
+
+    entityType.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String hasStream = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_ENTITY_TYPE_HAS_STREAM);
+    if (hasStream != null) {
+      entityType.setHasStream("true".equalsIgnoreCase(hasStream));
+    }
+
+    if (reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_TYPE_ABSTRACT) != null) {
+      entityType.setAbstract("true".equalsIgnoreCase(reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_TYPE_ABSTRACT)));
+    }
+    String baseType = reader.getAttributeValue(null, EdmParserConstants.EDM_BASE_TYPE);
+    if (baseType != null) {
+      entityType.setBaseType(extractFQName(baseType));
+    }
+    entityType.setCustomizableFeedMappings(readCustomizableFeedMappings(reader));
+    entityType.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ENTITY_TYPE.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ENTITY_TYPE_KEY.equals(currentHandledStartTagName)) {
+          key = readEntityTypeKey(reader);
+        } else if (EdmParserConstants.EDM_PROPERTY.equals(currentHandledStartTagName)) {
+          properties.add(readProperty(reader));
+        } else if (EdmParserConstants.EDM_NAVIGATION_PROPERTY.equals(currentHandledStartTagName)) {
+          navProperties.add(readNavigationProperty(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+        extractNamespaces(reader);
+      }
+    }
+    entityType.setKey(key).setProperties(properties).setNavigationProperties(navProperties).setAnnotationElements(annotationElements);
+    if (entityType.getName() != null) {
+      FullQualifiedName fqName = new FullQualifiedName(currentNamespace, entityType.getName());
+      entityTypesMap.put(fqName, entityType);
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("Name"));
+    }
+    return entityType;
+  }
+
+  private Key readEntityTypeKey(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ENTITY_TYPE_KEY);
+    List<PropertyRef> keys = new ArrayList<PropertyRef>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    List<AnnotationAttribute> annotationAttributes = readAnnotationAttribute(reader);
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ENTITY_TYPE_KEY.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_PROPERTY_REF.equals(currentHandledStartTagName)) {
+          reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_PROPERTY_REF);
+          keys.add(readPropertyRef(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    return new Key().setKeys(keys).setAnnotationElements(annotationElements).setAnnotationAttributes(annotationAttributes);
+  }
+
+  private PropertyRef readPropertyRef(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_PROPERTY_REF);
+    PropertyRef propertyRef = new PropertyRef();
+    propertyRef.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    propertyRef.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_PROPERTY_REF.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    return propertyRef.setAnnotationElements(annotationElements);
+  }
+
+  private NavigationProperty readNavigationProperty(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_NAVIGATION_PROPERTY);
+
+    NavigationProperty navProperty = new NavigationProperty();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    navProperty.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String relationship = reader.getAttributeValue(null, EdmParserConstants.EDM_NAVIGATION_RELATIONSHIP);
+    if (relationship != null) {
+      FullQualifiedName fqName = extractFQName(relationship);
+      navProperty.setRelationship(fqName);
+
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_NAVIGATION_RELATIONSHIP).addContent(EdmParserConstants.EDM_NAVIGATION_PROPERTY));
+    }
+
+    navProperty.setFromRole(reader.getAttributeValue(null, EdmParserConstants.EDM_NAVIGATION_FROM_ROLE));
+    navProperty.setToRole(reader.getAttributeValue(null, EdmParserConstants.EDM_NAVIGATION_TO_ROLE));
+    navProperty.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_NAVIGATION_PROPERTY.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    navProperty.setAnnotationElements(annotationElements);
+    navProperties.add(navProperty);
+    return navProperty;
+  }
+
+  private Property readProperty(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_PROPERTY);
+    Property property;
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    String type = reader.getAttributeValue(null, EdmParserConstants.EDM_TYPE);
+    if (type == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_TYPE).addContent(EdmParserConstants.EDM_PROPERTY));
+    }
+    FullQualifiedName fqName = extractFQName(type);
+
+    if (EdmSimpleType.EDM_NAMESPACE.equals(fqName.getNamespace())) {
+      property = readSimpleProperty(reader, fqName);
+    } else {
+      property = readComplexProperty(reader, fqName);
+    }
+    property.setFacets(readFacets(reader));
+    property.setCustomizableFeedMappings(readCustomizableFeedMappings(reader));
+    property.setMimeType(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_MIMETYPE));
+    property.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_PROPERTY.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    property.setAnnotationElements(annotationElements);
+    return property;
+  }
+
+  private Property readComplexProperty(final XMLStreamReader reader, final FullQualifiedName fqName) throws XMLStreamException {
+    ComplexProperty property = new ComplexProperty();
+    property.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    property.setType(fqName);
+    return property;
+  }
+
+  private Property readSimpleProperty(final XMLStreamReader reader, final FullQualifiedName fqName) throws XMLStreamException {
+    SimpleProperty property = new SimpleProperty();
+    property.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    property.setType(EdmSimpleTypeKind.valueOf(fqName.getName()));
+    return property;
+  }
+
+  private Facets readFacets(final XMLStreamReader reader) throws XMLStreamException {
+    String isNullable = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_NULLABLE);
+    String maxLength = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_MAX_LENGTH);
+    String precision = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_PRECISION);
+    String scale = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_SCALE);
+    String isFixedLength = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_FIXED_LENGTH);
+    String isUnicode = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_UNICODE);
+    String concurrencyMode = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_CONCURRENCY_MODE);
+    String defaultValue = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_DEFAULT_VALUE);
+    String collation = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_COLLATION);
+    if (isNullable != null || maxLength != null || precision != null || scale != null || isFixedLength != null || isUnicode != null
+        || concurrencyMode != null || defaultValue != null || collation != null) {
+      Facets facets = new Facets();
+      if (isNullable != null) {
+        facets.setNullable("true".equalsIgnoreCase(isNullable));
+      }
+      if (maxLength != null) {
+        if (EdmParserConstants.EDM_PROPERTY_MAX_LENGTH_MAX_VALUE.equals(maxLength)) {
+          facets.setMaxLength(Integer.MAX_VALUE);
+        } else {
+          facets.setMaxLength(Integer.parseInt(maxLength));
+        }
+      }
+      if (precision != null) {
+        facets.setPrecision(Integer.parseInt(precision));
+      }
+      if (scale != null) {
+        facets.setScale(Integer.parseInt(scale));
+      }
+      if (isFixedLength != null) {
+        facets.setFixedLength("true".equalsIgnoreCase(isFixedLength));
+      }
+      if (isUnicode != null) {
+        facets.setUnicode("true".equalsIgnoreCase(isUnicode));
+      }
+      for (int i = 0; i < EdmConcurrencyMode.values().length; i++) {
+        if (EdmConcurrencyMode.values()[i].name().equalsIgnoreCase(concurrencyMode)) {
+          facets.setConcurrencyMode(EdmConcurrencyMode.values()[i]);
+        }
+      }
+      facets.setDefaultValue(defaultValue);
+      facets.setCollation(collation);
+      return facets;
+    } else {
+      return null;
+    }
+  }
+
+  private CustomizableFeedMappings readCustomizableFeedMappings(final XMLStreamReader reader) {
+    String targetPath = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_TARGET_PATH);
+    String sourcePath = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_SOURCE_PATH);
+    String nsUri = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_NS_URI);
+    String nsPrefix = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_PREFIX);
+    String keepInContent = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_KEEP_IN_CONTENT);
+    String contentKind = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_CONTENT_KIND);
+
+    if (targetPath != null || sourcePath != null || nsUri != null || nsPrefix != null || keepInContent != null || contentKind != null) {
+      CustomizableFeedMappings feedMapping = new CustomizableFeedMappings();
+      if (keepInContent != null) {
+        feedMapping.setFcKeepInContent("true".equals(keepInContent));
+      }
+      for (int i = 0; i < EdmContentKind.values().length; i++) {
+        if (EdmContentKind.values()[i].name().equalsIgnoreCase(contentKind)) {
+          feedMapping.setFcContentKind(EdmContentKind.values()[i]);
+        }
+      }
+      feedMapping.setFcTargetPath(targetPath).setFcSourcePath(sourcePath).setFcNsUri(nsUri).setFcNsPrefix(nsPrefix);
+      return feedMapping;
+    } else {
+      return null;
+    }
+
+  }
+
+  private AssociationEnd readAssociationEnd(final XMLStreamReader reader) throws EntityProviderException, XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION_END);
+
+    AssociationEnd associationEnd = new AssociationEnd();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    associationEnd.setRole(reader.getAttributeValue(null, EdmParserConstants.EDM_ROLE));
+    associationEnd.setMultiplicity(EdmMultiplicity.fromLiteral(reader.getAttributeValue(null, EdmParserConstants.EDM_ASSOCIATION_MULTIPLICITY)));
+    String type = reader.getAttributeValue(null, EdmParserConstants.EDM_TYPE);
+    if (type == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_TYPE).addContent(EdmParserConstants.EDM_ASSOCIATION_END));
+    }
+    associationEnd.setType(extractFQName(type));
+    associationEnd.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ASSOCIATION_END.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ASSOCIATION_ONDELETE.equals(currentHandledStartTagName)) {
+          OnDelete onDelete = new OnDelete();
+          for (int i = 0; i < EdmAction.values().length; i++) {
+            if (EdmAction.values()[i].name().equalsIgnoreCase(reader.getAttributeValue(null, EdmParserConstants.EDM_ONDELETE_ACTION))) {
+              onDelete.setAction(EdmAction.values()[i]);
+            }
+          }
+          associationEnd.setOnDelete(onDelete);
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    associationEnd.setAnnotationElements(annotationElements);
+    return associationEnd;
+  }
+
+  private AnnotationElement readAnnotationElement(final XMLStreamReader reader) throws XMLStreamException {
+    AnnotationElement aElement = new AnnotationElement();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    List<AnnotationAttribute> annotationAttributes = new ArrayList<AnnotationAttribute>();
+    aElement.setName(reader.getLocalName());
+    String elementNamespace = reader.getNamespaceURI();
+    if (!Edm.NAMESPACE_EDM_2008_09.equals(elementNamespace)) {
+      aElement.setPrefix(reader.getPrefix());
+      aElement.setNamespace(elementNamespace);
+    }
+    for (int i = 0; i < reader.getAttributeCount(); i++) {
+      AnnotationAttribute annotationAttribute = new AnnotationAttribute();
+      annotationAttribute.setText(reader.getAttributeValue(i));
+      annotationAttribute.setName(reader.getAttributeLocalName(i));
+      annotationAttribute.setPrefix(reader.getAttributePrefix(i));
+      String namespace = reader.getAttributeNamespace(i);
+      if (!DEFAULT_NAMESPACE.equals(namespace)) {
+        annotationAttribute.setNamespace(namespace);
+      }
+      annotationAttributes.add(annotationAttribute);
+    }
+    aElement.setAttributes(annotationAttributes);
+    while (reader.hasNext() && !(reader.isEndElement() && aElement.getName() != null && aElement.getName().equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        annotationElements.add(readAnnotationElement(reader));
+      } else if (reader.isCharacters()) {
+        aElement.setText(reader.getText());
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      aElement.setChildElements(annotationElements);
+    }
+    return aElement;
+  }
+
+  private List<AnnotationAttribute> readAnnotationAttribute(final XMLStreamReader reader) {
+    List<AnnotationAttribute> annotationAttributes = new ArrayList<AnnotationAttribute>();
+    for (int i = 0; i < reader.getAttributeCount(); i++) {
+      if (!mandatoryNamespaces.containsValue(reader.getAttributeNamespace(i)) && !DEFAULT_NAMESPACE.equals(reader.getAttributeNamespace(i))) {
+        annotationAttributes.add(new AnnotationAttribute().setName(reader.getAttributeLocalName(i)).
+            setPrefix(reader.getAttributePrefix(i)).setNamespace(reader.getAttributeNamespace(i)).setText(reader.getAttributeValue(i)));
+      }
+    }
+    if (annotationAttributes.isEmpty()) {
+      return null;
+    }
+    return annotationAttributes;
+  }
+
+  private void checkAllMandatoryNamespacesAvailable() throws EntityProviderException {
+    if (!xmlNamespaceMap.containsValue(Edm.NAMESPACE_EDMX_2007_06)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_EDMX_2007_06));
+    } else if (!xmlNamespaceMap.containsValue(Edm.NAMESPACE_M_2007_08)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_EDMX_2007_06));
+    } else if (!xmlNamespaceMap.containsValue(Edm.NAMESPACE_EDM_2008_09)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_EDMX_2007_06));
+    }
+  }
+
+  private void extractNamespaces(final XMLStreamReader reader) throws EntityProviderException {
+    int namespaceCount = reader.getNamespaceCount();
+    for (int i = 0; i < namespaceCount; i++) {
+      String namespacePrefix = reader.getNamespacePrefix(i);
+      String namespaceUri = reader.getNamespaceURI(i);
+      if (namespacePrefix == null || DEFAULT_NAMESPACE.equals(namespacePrefix)) {
+        namespacePrefix = Edm.PREFIX_EDM;
+      }
+      xmlNamespaceMap.put(namespacePrefix, namespaceUri);
+    }
+  }
+
+  private FullQualifiedName extractFQName(final String name)
+      throws EntityProviderException {
+    // Looking for the last dot
+    String[] names = name.split("\\" + Edm.DELIMITER + "(?=[^\\" + Edm.DELIMITER + "]+$)");
+    if (names.length != 2) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Attribute should specify a namespace qualified name or an alias qualified name"));
+    } else {
+      return new FullQualifiedName(names[0], names[1]);
+    }
+  }
+
+  private FullQualifiedName validateEntityTypeWithAlias(final FullQualifiedName aliasName) throws EntityProviderException {
+    String namespace = aliasNamespaceMap.get(aliasName.getNamespace());
+    FullQualifiedName fqName = new FullQualifiedName(namespace, aliasName.getName());
+    if (!entityTypesMap.containsKey(fqName)) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid Type"));
+    }
+    return fqName;
+  }
+
+  private void validateEntityTypes() throws EntityProviderException {
+    for (Map.Entry<FullQualifiedName, EntityType> entityTypes : entityTypesMap.entrySet()) {
+      if (entityTypes.getValue() != null && entityTypes.getKey() != null) {
+        EntityType entityType = entityTypes.getValue();
+        if (entityType.getBaseType() != null) {
+          FullQualifiedName baseTypeFQName = entityType.getBaseType();
+          EntityType baseEntityType;
+          if (!entityTypesMap.containsKey(baseTypeFQName)) {
+            FullQualifiedName fqName = validateEntityTypeWithAlias(baseTypeFQName);
+            baseEntityType = entityTypesMap.get(fqName);
+          } else {
+            baseEntityType = entityTypesMap.get(baseTypeFQName);
+          }
+          if (baseEntityType.getKey() == null) {
+            throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Missing key for EntityType " + baseEntityType.getName()));
+          }
+        } else if (entityType.getKey() == null) {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Missing key for EntityType " + entityType.getName()));
+        }
+      }
+    }
+  }
+
+  private FullQualifiedName validateComplexTypeWithAlias(final FullQualifiedName aliasName) throws EntityProviderException {
+    String namespace = aliasNamespaceMap.get(aliasName.getNamespace());
+    FullQualifiedName fqName = new FullQualifiedName(namespace, aliasName.getName());
+    if (!complexTypesMap.containsKey(fqName)) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid BaseType").addContent(fqName));
+    }
+    return fqName;
+  }
+
+  private void validateComplexTypes() throws EntityProviderException {
+    for (Map.Entry<FullQualifiedName, ComplexType> complexTypes : complexTypesMap.entrySet()) {
+      if (complexTypes.getValue() != null && complexTypes.getKey() != null) {
+        ComplexType complexType = complexTypes.getValue();
+        if (complexType.getBaseType() != null) {
+          FullQualifiedName baseTypeFQName = complexType.getBaseType();
+          if (!complexTypesMap.containsKey(baseTypeFQName)) {
+            validateComplexTypeWithAlias(baseTypeFQName);
+          }
+        }
+      }
+    }
+  }
+
+  private void validateRelationship() throws EntityProviderException {
+    for (NavigationProperty navProperty : navProperties) {
+      if (associationsMap.containsKey(navProperty.getRelationship())) {
+        Association assoc = associationsMap.get(navProperty.getRelationship());
+        if (!(assoc.getEnd1().getRole().equals(navProperty.getFromRole()) ^ assoc.getEnd1().getRole().equals(navProperty.getToRole())
+        && (assoc.getEnd2().getRole().equals(navProperty.getFromRole()) ^ assoc.getEnd2().getRole().equals(navProperty.getToRole())))) {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid end of association"));
+        }
+        if (!entityTypesMap.containsKey(assoc.getEnd1().getType())) {
+          validateEntityTypeWithAlias(assoc.getEnd1().getType());
+        }
+        if (!entityTypesMap.containsKey(assoc.getEnd2().getType())) {
+          validateEntityTypeWithAlias(assoc.getEnd2().getType());
+        }
+      } else {
+        throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid Relationship"));
+      }
+    }
+
+  }
+
+  private void validateAssociation() throws EntityProviderException {
+    for (Map.Entry<FullQualifiedName, EntityContainer> container : containerMap.entrySet()) {
+      for (AssociationSet associationSet : container.getValue().getAssociationSets()) {
+        FullQualifiedName association = associationSet.getAssociation();
+        if (associationsMap.containsKey(association)) {
+          validateAssociationEnd(associationSet.getEnd1(), associationsMap.get(association));
+          validateAssociationEnd(associationSet.getEnd2(), associationsMap.get(association));
+          boolean end1 = false;
+          boolean end2 = false;
+          for (EntitySet entitySet : container.getValue().getEntitySets()) {
+            if (entitySet.getName().equals(associationSet.getEnd1().getEntitySet())) {
+              end1 = true;
+            }
+            if (entitySet.getName().equals(associationSet.getEnd2().getEntitySet())) {
+              end2 = true;
+            }
+          }
+          if (!(end1 && end2)) {
+            throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid AssociationSet"));
+          }
+        } else {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid AssociationSet"));
+        }
+      }
+    }
+
+  }
+
+  private void validateAssociationEnd(final AssociationSetEnd end, final Association association) throws EntityProviderException {
+    if (!(association.getEnd1().getRole().equals(end.getRole()) ^ association.getEnd2().getRole().equals(end.getRole()))) {
+      throw new EntityProviderException(EntityProviderException.COMMON.addContent("Invalid Association"));
+    }
+  }
+
+  private void validateEntitySet() throws EntityProviderException {
+    for (Map.Entry<FullQualifiedName, EntityContainer> container : containerMap.entrySet()) {
+      for (EntitySet entitySet : container.getValue().getEntitySets()) {
+        FullQualifiedName entityType = entitySet.getEntityType();
+        if (!(entityTypesMap.containsKey(entityType))) {
+          validateEntityTypeWithAlias(entityType);
+        }
+      }
+    }
+  }
+
+  private void validate() throws EntityProviderException {
+    checkAllMandatoryNamespacesAvailable();
+    validateEntityTypes();
+    validateComplexTypes();
+    validateRelationship();
+    validateEntitySet();
+    validateAssociation();
+  }
+
+  private void initialize() {
+    xmlNamespaceMap = new HashMap<String, String>();
+    mandatoryNamespaces = new HashMap<String, String>();
+    mandatoryNamespaces.put(Edm.PREFIX_EDMX, Edm.NAMESPACE_EDMX_2007_06);
+    mandatoryNamespaces.put(Edm.PREFIX_EDM, Edm.NAMESPACE_EDM_2008_09);
+    mandatoryNamespaces.put(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParserConstants.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParserConstants.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParserConstants.java
new file mode 100644
index 0000000..c2a3ae8
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParserConstants.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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.odata2.core.edm.parser;
+
+public class EdmParserConstants {
+
+  public static final String EDM_DATA_SERVICES = "DataServices";
+  public static final String EDM_SCHEMA = "Schema";
+  public static final String EDM_SCHEMA_NAMESPACE = "Namespace";
+  public static final String EDM_SCHEMA_ALIAS = "Alias";
+  public static final String EDM_ENTITY_TYPE = "EntityType";
+  public static final String EDM_COMPLEX_TYPE = "ComplexType";
+  public static final String EDM_ASSOCIATION = "Association";
+  public static final String EDM_USING = "Using";
+
+  public static final String EDM_NAME = "Name";
+  public static final String EDM_TYPE = "Type";
+  public static final String EDM_ENTITY_TYPE_KEY = "Key";
+  public static final String EDM_ENTITY_TYPE_ABSTRACT = "Abstract";
+  public static final String EDM_BASE_TYPE = "BaseType";
+  public static final String EDM_PROPERTY_REF = "PropertyRef";
+
+  public static final String EDM_PROPERTY = "Property";
+  public static final String EDM_PROPERTY_NULLABLE = "Nullable";
+  public static final String EDM_PROPERTY_MAX_LENGTH = "MaxLength";
+  public static final String EDM_PROPERTY_MAX_LENGTH_MAX_VALUE = "Max";
+  public static final String EDM_PROPERTY_DEFAULT_VALUE = "DefaultValue";
+  public static final String EDM_PROPERTY_FIXED_LENGTH = "FixedLength";
+  public static final String EDM_PROPERTY_UNICODE = "Unicode";
+  public static final String EDM_PROPERTY_COLLATION = "Collation";
+  public static final String EDM_PROPERTY_PRECISION = "Precision";
+  public static final String EDM_PROPERTY_SCALE = "Scale";
+  public static final String EDM_PROPERTY_CONCURRENCY_MODE = "ConcurrencyMode";
+
+  public static final String EDM_NAVIGATION_PROPERTY = "NavigationProperty";
+  public static final String EDM_NAVIGATION_FROM_ROLE = "FromRole";
+  public static final String EDM_NAVIGATION_TO_ROLE = "ToRole";
+  public static final String EDM_NAVIGATION_RELATIONSHIP = "Relationship";
+
+  public static final String EDM_ASSOCIATION_CONSTRAINT = "ReferentialConstraint";
+  public static final String EDM_ASSOCIATION_END = "End";
+
+  public static final String EDM_ASSOCIATION_MULTIPLICITY = "Multiplicity";
+  public static final String EDM_ASSOCIATION_ONDELETE = "OnDelete";
+  public static final String EDM_ONDELETE_ACTION = "Action";
+
+  public static final String EDM_ENTITY_CONTAINER = "EntityContainer";
+  public static final String EDM_ENTITY_SET = "EntitySet";
+  public static final String EDM_ASSOCIATION_SET = "AssociationSet";
+  public static final String EDM_FUNCTION_IMPORT = "FunctionImport";
+  public static final String EDM_CONTAINER_EXTENDZ = "Extendz";
+
+  public static final String EDM_FUNCTION_IMPORT_HTTP_METHOD = "HttpMethod";
+  public static final String EDM_FUNCTION_IMPORT_RETURN = "ReturnType";
+  public static final String EDM_FUNCTION_PARAMETER = "Parameter";
+
+  public static final String M_ENTITY_TYPE_HAS_STREAM = "HasStream";
+  public static final String M_MIMETYPE = "MimeType";
+  public static final String M_FC_TARGET_PATH = "FC_TargetPath";
+  public static final String M_FC_SOURCE_PATH = "FC_SourcePath";
+  public static final String M_FC_NS_URI = "FC_NsUri";
+  public static final String M_FC_PREFIX = "FC_NsPrefix";
+  public static final String M_FC_KEEP_IN_CONTENT = "FC_KeepInContent";
+  public static final String M_FC_CONTENT_KIND = "FC_ContentKind";
+  public static final String EDM_ASSOCIATION_PRINCIPAL = "Principal";
+  public static final String EDM_ASSOCIATION_DEPENDENT = "Dependent";
+
+  public static final String EDM_ROLE = "Role";
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmxProvider.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmxProvider.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmxProvider.java
new file mode 100644
index 0000000..2cb7ce8
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmxProvider.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * 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.odata2.core.edm.parser;
+
+import java.io.InputStream;
+import java.util.List;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.DataServices;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainer;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+
+public class EdmxProvider extends EdmProvider {
+  private DataServices dataServices;
+
+  public EdmxProvider parse(final InputStream in, final boolean validate) throws EntityProviderException {
+    EdmParser parser = new EdmParser();
+    XMLStreamReader streamReader = createStreamReader(in);
+    dataServices = parser.readMetadata(streamReader, validate);
+    return this;
+  }
+
+  @Override
+  public EntityContainerInfo getEntityContainerInfo(final String name) throws ODataException {
+    if (name != null) {
+      for (Schema schema : dataServices.getSchemas()) {
+        for (EntityContainer container : schema.getEntityContainers()) {
+          if (container.getName().equals(name)) {
+            return container;
+          }
+        }
+      }
+    } else {
+      for (Schema schema : dataServices.getSchemas()) {
+        for (EntityContainer container : schema.getEntityContainers()) {
+          if (container.isDefaultEntityContainer()) {
+            return container;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public EntityType getEntityType(final FullQualifiedName edmFQName) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      if (schema.getNamespace().equals(edmFQName.getNamespace())) {
+        for (EntityType entityType : schema.getEntityTypes()) {
+          if (entityType.getName().equals(edmFQName.getName())) {
+            return entityType;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public ComplexType getComplexType(final FullQualifiedName edmFQName) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      if (schema.getNamespace().equals(edmFQName.getNamespace())) {
+        for (ComplexType complexType : schema.getComplexTypes()) {
+          if (complexType.getName().equals(edmFQName.getName())) {
+            return complexType;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public Association getAssociation(final FullQualifiedName edmFQName) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      if (schema.getNamespace().equals(edmFQName.getNamespace())) {
+        for (Association association : schema.getAssociations()) {
+          if (association.getName().equals(edmFQName.getName())) {
+            return association;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public EntitySet getEntitySet(final String entityContainer, final String name) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      for (EntityContainer container : schema.getEntityContainers()) {
+        if (container.getName().equals(entityContainer)) {
+          for (EntitySet entitySet : container.getEntitySets()) {
+            if (entitySet.getName().equals(name)) {
+              return entitySet;
+            }
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public AssociationSet getAssociationSet(final String entityContainer, final FullQualifiedName association, final String sourceEntitySetName, final String sourceEntitySetRole) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      for (EntityContainer container : schema.getEntityContainers()) {
+        if (container.getName().equals(entityContainer)) {
+          for (AssociationSet associationSet : container.getAssociationSets()) {
+            if (associationSet.getAssociation().equals(association)
+                && ((associationSet.getEnd1().getEntitySet().equals(sourceEntitySetName) && associationSet.getEnd1().getRole().equals(sourceEntitySetRole))
+                || (associationSet.getEnd2().getEntitySet().equals(sourceEntitySetName) && associationSet.getEnd2().getRole().equals(sourceEntitySetRole)))) {
+              return associationSet;
+            }
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public FunctionImport getFunctionImport(final String entityContainer, final String name) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      for (EntityContainer container : schema.getEntityContainers()) {
+        if (container.getName().equals(entityContainer)) {
+          for (FunctionImport function : container.getFunctionImports()) {
+            if (function.getName().equals(name)) {
+              return function;
+            }
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public List<Schema> getSchemas() throws ODataException {
+    return dataServices.getSchemas();
+  }
+
+  private XMLStreamReader createStreamReader(final InputStream in) throws EntityProviderException {
+    XMLInputFactory factory = XMLInputFactory.newInstance();
+    factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+    factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+
+    XMLStreamReader streamReader;
+    try {
+      streamReader = factory.createXMLStreamReader(in);
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+
+    return streamReader;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProv.java
new file mode 100644
index 0000000..9c22cfd
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProv.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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.odata2.core.edm.provider;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationElement;
+
+public class EdmAnnotationsImplProv implements EdmAnnotations {
+
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<? extends EdmAnnotationElement> annotationElements;
+
+  public EdmAnnotationsImplProv(final List<AnnotationAttribute> annotationAttributes, final List<AnnotationElement> annotationElements) {
+    this.annotationAttributes = annotationAttributes;
+    this.annotationElements = annotationElements;
+  }
+
+  @Override
+  public List<? extends EdmAnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  @Override
+  public EdmAnnotationElement getAnnotationElement(final String name, final String namespace) {
+    if (annotationElements != null) {
+      Iterator<? extends EdmAnnotationElement> annotationElementIterator = annotationElements.iterator();
+
+      while (annotationElementIterator.hasNext()) {
+        EdmAnnotationElement annotationElement = annotationElementIterator.next();
+        if (annotationElement.getName().equals(name) && annotationElement.getNamespace().equals(namespace)) {
+          return annotationElement;
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public List<? extends EdmAnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  @Override
+  public EdmAnnotationAttribute getAnnotationAttribute(final String name, final String namespace) {
+    if (annotationElements != null) {
+      Iterator<? extends EdmAnnotationAttribute> annotationAttributesIterator = annotationAttributes.iterator();
+
+      while (annotationAttributesIterator.hasNext()) {
+        EdmAnnotationAttribute annotationAttribute = annotationAttributesIterator.next();
+        if (annotationAttribute.getName().equals(name) && annotationAttribute.getNamespace().equals(namespace)) {
+          return annotationAttribute;
+        }
+      }
+    }
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProv.java
new file mode 100644
index 0000000..6030fa1
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProv.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.odata2.core.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+
+public class EdmAssociationEndImplProv implements EdmAssociationEnd, EdmAnnotatable {
+
+  private EdmImplProv edm;
+  private AssociationEnd associationEnd;
+
+  public EdmAssociationEndImplProv(final EdmImplProv edm, final AssociationEnd associationEnd) throws EdmException {
+    this.edm = edm;
+    this.associationEnd = associationEnd;
+  }
+
+  @Override
+  public String getRole() {
+    return associationEnd.getRole();
+  }
+
+  @Override
+  public EdmEntityType getEntityType() throws EdmException {
+    final FullQualifiedName type = associationEnd.getType();
+    EdmEntityType entityType = edm.getEntityType(type.getNamespace(), type.getName());
+    if (entityType == null) {
+      throw new EdmException(EdmException.COMMON);
+    }
+    return entityType;
+  }
+
+  @Override
+  public EdmMultiplicity getMultiplicity() {
+    return associationEnd.getMultiplicity();
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(associationEnd.getAnnotationAttributes(), associationEnd.getAnnotationElements());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProv.java
new file mode 100644
index 0000000..3c102ca
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProv.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.odata2.core.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+
+public class EdmAssociationImplProv extends EdmNamedImplProv implements EdmAssociation, EdmAnnotatable {
+
+  private Association association;
+  private String namespace;
+
+  public EdmAssociationImplProv(final EdmImplProv edm, final Association association, final String namespace) throws EdmException {
+    super(edm, association.getName());
+    this.association = association;
+    this.namespace = namespace;
+  }
+
+  @Override
+  public String getNamespace() throws EdmException {
+    return namespace;
+  }
+
+  @Override
+  public EdmTypeKind getKind() {
+    return EdmTypeKind.ASSOCIATION;
+  }
+
+  @Override
+  public EdmAssociationEnd getEnd(final String role) throws EdmException {
+    AssociationEnd end = association.getEnd1();
+    if (end.getRole().equals(role)) {
+      return new EdmAssociationEndImplProv(edm, end);
+    }
+    end = association.getEnd2();
+    if (end.getRole().equals(role)) {
+      return new EdmAssociationEndImplProv(edm, end);
+    }
+
+    return null;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(association.getAnnotationAttributes(), association.getAnnotationElements());
+  }
+
+  public EdmMultiplicity getEndMultiplicity(final String role) {
+    if (association.getEnd1().getRole().equals(role)) {
+      return association.getEnd1().getMultiplicity();
+    }
+
+    if (association.getEnd2().getRole().equals(role)) {
+      return association.getEnd2().getMultiplicity();
+    }
+
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProv.java
new file mode 100644
index 0000000..4bbc1f7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProv.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.odata2.core.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+
+public class EdmAssociationSetEndImplProv implements EdmAssociationSetEnd, EdmAnnotatable {
+
+  private EdmEntitySet entitySet;
+  private String role;
+  private AssociationSetEnd end;
+
+  public EdmAssociationSetEndImplProv(final AssociationSetEnd end, final EdmEntitySet entitySet) throws EdmException {
+    this.end = end;
+    this.entitySet = entitySet;
+    role = end.getRole();
+  }
+
+  @Override
+  public EdmEntitySet getEntitySet() throws EdmException {
+    return entitySet;
+  }
+
+  @Override
+  public String getRole() {
+    return role;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(end.getAnnotationAttributes(), end.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProv.java
new file mode 100644
index 0000000..a831615
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProv.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * 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.odata2.core.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+
+public class EdmAssociationSetImplProv extends EdmNamedImplProv implements EdmAssociationSet, EdmAnnotatable {
+
+  private AssociationSet associationSet;
+  private EdmEntityContainer edmEntityContainer;
+
+  public EdmAssociationSetImplProv(final EdmImplProv edm, final AssociationSet associationSet, final EdmEntityContainer edmEntityContainer) throws EdmException {
+    super(edm, associationSet.getName());
+    this.associationSet = associationSet;
+    this.edmEntityContainer = edmEntityContainer;
+  }
+
+  @Override
+  public EdmAssociation getAssociation() throws EdmException {
+    EdmAssociation association = edm.getAssociation(associationSet.getAssociation().getNamespace(), associationSet.getAssociation().getName());
+    if (association == null) {
+      throw new EdmException(EdmException.COMMON);
+    }
+    return association;
+  }
+
+  @Override
+  public EdmAssociationSetEnd getEnd(final String role) throws EdmException {
+    AssociationSetEnd end;
+
+    if (associationSet.getEnd1().getRole().equals(role)) {
+      end = associationSet.getEnd1();
+    } else if (associationSet.getEnd2().getRole().equals(role)) {
+      end = associationSet.getEnd2();
+    } else {
+      return null;
+    }
+
+    EdmEntitySet entitySet = edmEntityContainer.getEntitySet(end.getEntitySet());
+    if (entitySet == null) {
+      throw new EdmException(EdmException.COMMON);
+    }
+
+    return new EdmAssociationSetEndImplProv(end, entitySet);
+  }
+
+  @Override
+  public EdmEntityContainer getEntityContainer() throws EdmException {
+    return edmEntityContainer;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(associationSet.getAnnotationAttributes(), associationSet.getAnnotationElements());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexPropertyImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexPropertyImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexPropertyImplProv.java
new file mode 100644
index 0000000..70b48c6
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexPropertyImplProv.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.odata2.core.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+
+/**
+ * @author SAP AG
+ */
+public class EdmComplexPropertyImplProv extends EdmPropertyImplProv {
+
+  private ComplexProperty property;
+
+  public EdmComplexPropertyImplProv(final EdmImplProv edm, final ComplexProperty property) throws EdmException {
+    super(edm, property.getType(), property);
+    this.property = property;
+  }
+
+  @Override
+  public EdmType getType() throws EdmException {
+    if (edmType == null) {
+      edmType = edm.getComplexType(property.getType().getNamespace(), property.getType().getName());
+    }
+    if (edmType == null) {
+      throw new EdmException(EdmException.PROVIDERPROBLEM);
+    }
+    return edmType;
+  }
+
+  @Override
+  public boolean isSimple() {
+    return false;
+  }
+}