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);
+
+ }
+}