You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by sk...@apache.org on 2013/08/28 15:34:30 UTC

[26/43] source distribution

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/c5b266a6/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeImpl.java
----------------------------------------------------------------------
diff --git a/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeImpl.java b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeImpl.java
new file mode 100644
index 0000000..e078097
--- /dev/null
+++ b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeImpl.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * 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;
+
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmLiteralException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeFacade;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ *  
+ */
+public class EdmSimpleTypeFacadeImpl implements EdmSimpleTypeFacade {
+
+  @Override
+  public EdmLiteral parseUriLiteral(final String uriLiteral) throws EdmLiteralException {
+    if (uriLiteral == null || "null".equals(uriLiteral)) {
+      return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Null), uriLiteral);
+    }
+
+    if ("true".equals(uriLiteral) || "false".equals(uriLiteral)) {
+      return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Boolean), uriLiteral);
+    }
+
+    if (uriLiteral.length() >= 2
+        && uriLiteral.startsWith("'") && uriLiteral.endsWith("'")) {
+      try {
+        final EdmSimpleType type = getEdmSimpleType(EdmSimpleTypeKind.String);
+        return new EdmLiteral(type, type.valueOfString(uriLiteral, EdmLiteralKind.URI, null, String.class));
+      } catch (EdmSimpleTypeException e) {
+        throw new EdmLiteralException(EdmLiteralException.LITERALFORMAT.addContent(uriLiteral), e);
+      }
+    }
+
+    if (uriLiteral.matches("-?\\p{Digit}+")) {
+      try {
+        final int i = getEdmSimpleType(EdmSimpleTypeKind.Int32).valueOfString(uriLiteral, EdmLiteralKind.URI, null, Integer.class);
+        if (i == 0 || i == 1) {
+          return new EdmLiteral(getInternalEdmSimpleTypeByString("Bit"), uriLiteral);
+        }
+        if (i >= 0 && i <= Byte.MAX_VALUE) {
+          return new EdmLiteral(getInternalEdmSimpleTypeByString("Uint7"), uriLiteral);
+        }
+        if (i >= Byte.MIN_VALUE && i < 0) {
+          return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.SByte), uriLiteral);
+        } else if (i > Byte.MAX_VALUE && i <= 255) {
+          return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Byte), uriLiteral);
+        } else if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) {
+          return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Int16), uriLiteral);
+        } else {
+          return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Int32), uriLiteral);
+        }
+      } catch (EdmSimpleTypeException e) {
+        throw new EdmLiteralException(EdmLiteralException.LITERALFORMAT.addContent(uriLiteral), e);
+      }
+    }
+
+    if (uriLiteral.endsWith("L") || uriLiteral.endsWith("l")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Int64, uriLiteral, 0, 1);
+    }
+    if (uriLiteral.endsWith("M") || uriLiteral.endsWith("m")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Decimal, uriLiteral, 0, 1);
+    }
+    if (uriLiteral.endsWith("D") || uriLiteral.endsWith("d")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Double, uriLiteral, 0, 1);
+    }
+    if (uriLiteral.equals("-INF") || uriLiteral.equals("INF") || uriLiteral.equals("NaN")) {
+      return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Single), uriLiteral);
+    }
+    if (uriLiteral.endsWith("F") || uriLiteral.endsWith("f")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Single, uriLiteral, 0, 1);
+    }
+
+    if (uriLiteral.startsWith("datetime'")) {
+      return createEdmLiteral(EdmSimpleTypeKind.DateTime, uriLiteral, 9, 1);
+    }
+    if (uriLiteral.startsWith("datetimeoffset'")) {
+      return createEdmLiteral(EdmSimpleTypeKind.DateTimeOffset, uriLiteral, 15, 1);
+    }
+    if (uriLiteral.startsWith("guid'")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Guid, uriLiteral, 5, 1);
+    }
+    if (uriLiteral.startsWith("time'")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Time, uriLiteral, 5, 1);
+    }
+
+    if (uriLiteral.startsWith("X'") || uriLiteral.startsWith("binary'")) {
+      try {
+        final EdmSimpleType type = getEdmSimpleType(EdmSimpleTypeKind.Binary);
+        final byte[] value = type.valueOfString(uriLiteral, EdmLiteralKind.URI, null, byte[].class);
+        return new EdmLiteral(type, type.valueToString(value, EdmLiteralKind.DEFAULT, null));
+      } catch (EdmSimpleTypeException e) {
+        throw new EdmLiteralException(EdmLiteralException.LITERALFORMAT.addContent(uriLiteral), e);
+      }
+    }
+
+    throw new EdmLiteralException(EdmLiteralException.UNKNOWNLITERAL.addContent(uriLiteral));
+  }
+
+  private static EdmLiteral createEdmLiteral(final EdmSimpleTypeKind typeKind, final String literal, final int prefixLength, final int suffixLength) throws EdmLiteralException {
+    final EdmSimpleType type = getEdmSimpleType(typeKind);
+    if (type.validate(literal, EdmLiteralKind.URI, null)) {
+      return new EdmLiteral(type, literal.substring(prefixLength, literal.length() - suffixLength));
+    } else {
+      throw new EdmLiteralException(EdmLiteralException.LITERALFORMAT.addContent(literal));
+    }
+  }
+
+  @Override
+  public EdmSimpleType getEdmSimpleTypeInstance(final EdmSimpleTypeKind typeKind) {
+    return getEdmSimpleType(typeKind);
+  }
+
+  public static EdmSimpleType getEdmSimpleType(final EdmSimpleTypeKind typeKind) {
+
+    switch (typeKind) {
+    case Binary:
+      return EdmBinary.getInstance();
+    case Boolean:
+      return EdmBoolean.getInstance();
+    case Byte:
+      return EdmByte.getInstance();
+    case DateTime:
+      return EdmDateTime.getInstance();
+    case DateTimeOffset:
+      return EdmDateTimeOffset.getInstance();
+    case Decimal:
+      return EdmDecimal.getInstance();
+    case Double:
+      return EdmDouble.getInstance();
+    case Guid:
+      return EdmGuid.getInstance();
+    case Int16:
+      return EdmInt16.getInstance();
+    case Int32:
+      return EdmInt32.getInstance();
+    case Int64:
+      return EdmInt64.getInstance();
+    case SByte:
+      return EdmSByte.getInstance();
+    case Single:
+      return EdmSingle.getInstance();
+    case String:
+      return EdmString.getInstance();
+    case Time:
+      return EdmTime.getInstance();
+    case Null:
+      return EdmNull.getInstance();
+    default:
+      throw new ODataRuntimeException("Invalid Type " + typeKind);
+    }
+  }
+
+  public static EdmSimpleType getInternalEdmSimpleTypeByString(final String edmSimpleType) {
+    if ("Bit".equals(edmSimpleType)) {
+      return Bit.getInstance();
+    } else if ("Uint7".equals(edmSimpleType)) {
+      return Uint7.getInstance();
+    } else {
+      throw new ODataRuntimeException("Invalid internal Type " + edmSimpleType);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/c5b266a6/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmSingle.java
----------------------------------------------------------------------
diff --git a/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmSingle.java b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmSingle.java
new file mode 100644
index 0000000..257e7f8
--- /dev/null
+++ b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmSingle.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * 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;
+
+import java.math.BigDecimal;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type Single.
+ *  
+ */
+public class EdmSingle extends AbstractSimpleType {
+
+  // value-range limitations according to the CSDL document
+  private static final int MAX_PRECISION = 7;
+  private static final int MAX_SCALE = 38;
+
+  private static final Pattern PATTERN = Pattern.compile(
+      "(?:\\+|-)?\\p{Digit}{1,7}(?:\\.\\p{Digit}{1,7})?(?:(?:E|e)(?:\\+|-)?\\p{Digit}{1,2})?(F|f)?");
+  private static final EdmSingle instance = new EdmSingle();
+
+  public static EdmSingle getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit
+        || simpleType instanceof Uint7
+        || simpleType instanceof EdmByte
+        || simpleType instanceof EdmSByte
+        || simpleType instanceof EdmInt16
+        || simpleType instanceof EdmInt32
+        || simpleType instanceof EdmInt64
+        || simpleType instanceof EdmSingle;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Float.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    String valueString = value;
+    Float result = null;
+    // Handle special values first.
+    if (value.equals("-INF")) {
+      result = Float.NEGATIVE_INFINITY;
+    } else if (value.equals("INF")) {
+      result = Float.POSITIVE_INFINITY;
+    } else if (value.equals("NaN")) {
+      result = Float.NaN;
+    } else {
+      // Now only "normal" numbers remain.
+      final Matcher matcher = PATTERN.matcher(value);
+      if (!matcher.matches()
+          || (literalKind == EdmLiteralKind.URI) == (matcher.group(1) == null)) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+
+      if (literalKind == EdmLiteralKind.URI) {
+        valueString = value.substring(0, value.length() - 1);
+      }
+
+      // The number format is checked above, so we don't have to catch NumberFormatException.
+      result = Float.valueOf(valueString);
+      // "Real" infinite values have been treated already above, so we can throw an exception
+      // if the conversion to a float results in an infinite value.
+      if (result.isInfinite()) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+    }
+
+    if (returnType.isAssignableFrom(Float.class)) {
+      return returnType.cast(result);
+    } else if (returnType.isAssignableFrom(Double.class)) {
+      if (result.isInfinite() || result.isNaN()) {
+        return returnType.cast(result.doubleValue());
+      } else {
+        return returnType.cast(Double.valueOf(valueString));
+      }
+    } else if (result.isInfinite() || result.isNaN()) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+    } else {
+      try {
+        final BigDecimal valueBigDecimal = new BigDecimal(valueString);
+        if (returnType.isAssignableFrom(BigDecimal.class)) {
+          return returnType.cast(valueBigDecimal);
+        } else if (returnType.isAssignableFrom(Long.class)) {
+          return returnType.cast(valueBigDecimal.longValueExact());
+        } else if (returnType.isAssignableFrom(Integer.class)) {
+          return returnType.cast(valueBigDecimal.intValueExact());
+        } else if (returnType.isAssignableFrom(Short.class)) {
+          return returnType.cast(valueBigDecimal.shortValueExact());
+        } else if (returnType.isAssignableFrom(Byte.class)) {
+          return returnType.cast(valueBigDecimal.byteValueExact());
+        } else {
+          throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+        }
+
+      } catch (final ArithmeticException e) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType), e);
+      }
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value instanceof Long || value instanceof Integer) {
+      if (Math.abs(((Number) value).longValue()) < Math.pow(10, MAX_PRECISION)) {
+        return value.toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else if (value instanceof Short || value instanceof Byte) {
+      return value.toString();
+    } else if (value instanceof Double) {
+      if (((Double) value).isInfinite()) {
+        return value.toString().toUpperCase(Locale.ROOT).substring(0, value.toString().length() - 5);
+      } else if (Float.isInfinite(((Double) value).floatValue())) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      } else {
+        return Float.toString(((Double) value).floatValue());
+      }
+    } else if (value instanceof Float) {
+      final String result = value.toString();
+      return ((Float) value).isInfinite() ? result.toUpperCase(Locale.ROOT).substring(0, value.toString().length() - 5) : result;
+    } else if (value instanceof BigDecimal) {
+      if (((BigDecimal) value).precision() <= MAX_PRECISION && Math.abs(((BigDecimal) value).scale()) <= MAX_SCALE) {
+        return ((BigDecimal) value).toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) {
+    return literal.equals("-INF") || literal.equals("INF") || literal.equals("NaN") ?
+        literal : literal + "F";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/c5b266a6/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmString.java
----------------------------------------------------------------------
diff --git a/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmString.java b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmString.java
new file mode 100644
index 0000000..ac43aac
--- /dev/null
+++ b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmString.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type String.
+ *  
+ */
+public class EdmString extends AbstractSimpleType {
+
+  private static final Pattern PATTERN_ASCII = Pattern.compile("\\p{ASCII}*");
+  private static final EdmString instance = new EdmString();
+
+  public static EdmString getInstance() {
+    return instance;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return String.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    String result;
+    if (literalKind == EdmLiteralKind.URI) {
+      if (value.length() >= 2 && value.startsWith("'") && value.endsWith("'")) {
+        result = (value.substring(1, value.length() - 1)).replace("''", "'");
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      result = value;
+    }
+
+    if (facets != null
+        && (facets.isUnicode() != null && !facets.isUnicode() && !PATTERN_ASCII.matcher(result).matches()
+        || facets.getMaxLength() != null && facets.getMaxLength() < result.length())) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(value, facets));
+    }
+
+    if (returnType.isAssignableFrom(String.class)) {
+      return returnType.cast(result);
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    final String result = value instanceof String ? (String) value : String.valueOf(value);
+
+    if (facets != null
+        && (facets.isUnicode() != null && !facets.isUnicode() && !PATTERN_ASCII.matcher(result).matches()
+        || facets.getMaxLength() != null && facets.getMaxLength() < result.length())) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets));
+    }
+
+    return result;
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) throws EdmSimpleTypeException {
+    final int length = literal.length();
+
+    StringBuilder uriLiteral = new StringBuilder(length + 2);
+    uriLiteral.append('\'');
+    for (int i = 0; i < length; i++) {
+      final char c = literal.charAt(i);
+      if (c == '\'') {
+        uriLiteral.append(c);
+      }
+      uriLiteral.append(c);
+    }
+    uriLiteral.append('\'');
+    return uriLiteral.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/c5b266a6/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmTime.java
----------------------------------------------------------------------
diff --git a/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmTime.java b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmTime.java
new file mode 100644
index 0000000..217e772
--- /dev/null
+++ b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/EdmTime.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * <p>Implementation of the EDM simple type Time.</p>
+ * <p>Arguably, this type is intended to represent a time of day, not an instance in time.
+ * The time value is interpreted and formatted as local time.</p>
+ * <p>Formatting simply ignores the year, month, and day parts of time instances.
+ * Parsing returns a Calendar object where all unused fields have been cleared.</p>
+ *  
+ */
+public class EdmTime extends AbstractSimpleType {
+
+  private static final Pattern PATTERN = Pattern.compile(
+      "PT(?:(\\p{Digit}{1,2})H)?(?:(\\p{Digit}{1,4})M)?(?:(\\p{Digit}{1,5})(?:\\.(\\p{Digit}+?)0*)?S)?");
+  private static final EdmTime instance = new EdmTime();
+
+  public static EdmTime getInstance() {
+    return instance;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Calendar.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    Calendar valueCalendar;
+    if (literalKind == EdmLiteralKind.URI) {
+      if (value.length() > 6 && value.startsWith("time'") && value.endsWith("'")) {
+        valueCalendar = parseLiteral(value.substring(5, value.length() - 1), facets);
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      valueCalendar = parseLiteral(value, facets);
+    }
+
+    if (returnType.isAssignableFrom(Calendar.class)) {
+      return returnType.cast(valueCalendar);
+    } else if (returnType.isAssignableFrom(Long.class)) {
+      return returnType.cast(valueCalendar.getTimeInMillis());
+    } else if (returnType.isAssignableFrom(Date.class)) {
+      return returnType.cast(valueCalendar.getTime());
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  private Calendar parseLiteral(final String literal, final EdmFacets facets) throws EdmSimpleTypeException {
+    final Matcher matcher = PATTERN.matcher(literal);
+    if (!matcher.matches()
+        || (matcher.group(1) == null && matcher.group(2) == null && matcher.group(3) == null)) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(literal));
+    }
+
+    Calendar dateTimeValue = Calendar.getInstance();
+    dateTimeValue.clear();
+
+    dateTimeValue.set(Calendar.HOUR_OF_DAY,
+        matcher.group(1) == null ? 0 : Integer.parseInt(matcher.group(1)));
+    dateTimeValue.set(Calendar.MINUTE,
+        matcher.group(2) == null ? 0 : Integer.parseInt(matcher.group(2)));
+    dateTimeValue.set(Calendar.SECOND,
+        matcher.group(3) == null ? 0 : Integer.parseInt(matcher.group(3)));
+
+    if (matcher.group(4) != null) {
+      if (facets == null || facets.getPrecision() == null || facets.getPrecision() >= matcher.group(4).length()) {
+        if (matcher.group(4).length() <= 3) {
+          dateTimeValue.set(Calendar.MILLISECOND,
+              Short.parseShort(matcher.group(4) + "000".substring(0, 3 - matcher.group(4).length())));
+        } else {
+          throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(literal));
+        }
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(literal, facets));
+      }
+    }
+
+    if (dateTimeValue.get(Calendar.DAY_OF_YEAR) == 1) {
+      return dateTimeValue;
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(literal));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    Calendar dateTimeValue;
+    if (value instanceof Date) {
+      dateTimeValue = Calendar.getInstance();
+      dateTimeValue.clear();
+      dateTimeValue.setTime((Date) value);
+    } else if (value instanceof Calendar) {
+      dateTimeValue = (Calendar) ((Calendar) value).clone();
+    } else if (value instanceof Long) {
+      dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+      dateTimeValue.clear();
+      dateTimeValue.setTimeInMillis((Long) value);
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+
+    StringBuilder result = new StringBuilder(15); // 15 characters are enough for millisecond precision.
+    result.append('P');
+    result.append('T');
+    result.append(dateTimeValue.get(Calendar.HOUR_OF_DAY));
+    result.append('H');
+    result.append(dateTimeValue.get(Calendar.MINUTE));
+    result.append('M');
+    result.append(dateTimeValue.get(Calendar.SECOND));
+
+    try {
+      EdmDateTime.appendMilliseconds(result, dateTimeValue.get(Calendar.MILLISECOND), facets);
+    } catch (final IllegalArgumentException e) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets), e);
+    }
+
+    result.append('S');
+
+    return result.toString();
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) {
+    return "time'" + literal + "'";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/c5b266a6/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/Uint7.java
----------------------------------------------------------------------
diff --git a/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/Uint7.java b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/Uint7.java
new file mode 100644
index 0000000..9c3f801
--- /dev/null
+++ b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/Uint7.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the internal simple type "unsigned 7-bit integer".
+ *  
+ */
+public class Uint7 extends AbstractSimpleType {
+
+  private static final Uint7 instance = new Uint7();
+
+  public static Uint7 getInstance() {
+    return instance;
+  }
+
+  @Override
+  public String getNamespace() throws EdmException {
+    return SYSTEM_NAMESPACE;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit || simpleType instanceof Uint7;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Byte.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    return EdmSByte.getInstance().internalValueOfString(value, literalKind, facets, returnType);
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    return EdmSByte.getInstance().internalValueToString(value, literalKind, facets);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/c5b266a6/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/parser/EdmParser.java
----------------------------------------------------------------------
diff --git a/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/parser/EdmParser.java b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/parser/EdmParser.java
new file mode 100644
index 0000000..8a3d66b
--- /dev/null
+++ b/aggregated-sources/org.apache.olingo.odata2-parent-sources/org/apache/olingo/odata2/core/edm/parser/EdmParser.java
@@ -0,0 +1,984 @@
+/*******************************************************************************
+ * 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.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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;
+
+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 String edmNamespace = Edm.NAMESPACE_EDM_2008_09;
+  private Set<String> edmNamespaces;
+
+  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())) {
+            edmNamespace = reader.getNamespaceURI();
+            checkEdmNamespace();
+            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, edmNamespace, 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));
+    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() && edmNamespace.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, edmNamespace, EdmParserConstants.EDM_USING);
+
+    Using using = new Using();
+    using.setNamespace(reader.getAttributeValue(null, EdmParserConstants.EDM_SCHEMA_NAMESPACE));
+    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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, EdmParserConstants.EDM_ASSOCIATION_CONSTRAINT);
+    ReferentialConstraint refConstraint = new ReferentialConstraint();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    refConstraint.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && edmNamespace.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, edmNamespace, EdmParserConstants.EDM_ASSOCIATION_PRINCIPAL);
+          refConstraint.setPrincipal(readReferentialConstraintRole(reader));
+        } else if (EdmParserConstants.EDM_ASSOCIATION_DEPENDENT.equals(currentHandledStartTagName)) {
+          reader.require(XMLStreamConstants.START_ELEMENT, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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, edmNamespace, 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() && edmNamespace.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 (!edmNamespaces.contains(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 (namespace != null && !isDefaultNamespace(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++) {
+      String attributeNamespace = reader.getAttributeNamespace(i);
+      if (attributeNamespace != null && !isDefaultNamespace(attributeNamespace)
+          && !mandatoryNamespaces.containsValue(attributeNamespace)
+          && !edmNamespaces.contains(attributeNamespace)) {
+        annotationAttributes.add(new AnnotationAttribute().setName(reader.getAttributeLocalName(i)).
+            setPrefix(reader.getAttributePrefix(i)).setNamespace(attributeNamespace).setText(reader.getAttributeValue(i)));
+      }
+    }
+    if (annotationAttributes.isEmpty()) {
+      return null;
+    }
+    return annotationAttributes;
+  }
+
+  private boolean isDefaultNamespace(final String namespace) {
+    return namespace.isEmpty();
+  }
+
+  private void checkMandatoryNamespacesAvailable() 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));
+    }
+  }
+
+  private void checkEdmNamespace() throws EntityProviderException {
+    if (!edmNamespaces.contains(edmNamespace)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(EdmParserConstants.EDM_SCHEMA));
+    }
+  }
+
+  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 || isDefaultNamespace(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 {
+    checkMandatoryNamespacesAvailable();
+    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_M, Edm.NAMESPACE_M_2007_08);
+    edmNamespaces = new HashSet<String>();
+    edmNamespaces.add(Edm.NAMESPACE_EDM_2006_04);
+    edmNamespaces.add(Edm.NAMESPACE_EDM_2007_05);
+    edmNamespaces.add(Edm.NAMESPACE_EDM_2008_01);
+    edmNamespaces.add(Edm.NAMESPACE_EDM_2008_09);
+
+  }
+}