You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2013/12/05 13:31:34 UTC
[41/52] Removed not to merge PoC parts
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/8764e11a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/processor/json/JsonWriter.java
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/processor/json/JsonWriter.java b/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/processor/json/JsonWriter.java
deleted file mode 100644
index a277b41..0000000
--- a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/processor/json/JsonWriter.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/**
- * *****************************************************************************
- * 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.annotation.processor.json;
-
-import java.io.IOException;
-import java.io.Writer;
-
-import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
-
-public class JsonWriter {
-
- private final Writer writer;
- private boolean firstProperty = true;
-
- public JsonWriter(Writer writer) {
- this.writer = writer;
- }
-
- public void startCallback(String functionName) {
- try {
- writer.write(encode(functionName) + "(");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void endCallback() {
- try {
- writer.write(");");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void startObject() {
- try {
- firstProperty = true;
- writer.write("{\n");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void endObject() {
- try {
- firstProperty = false;
- writer.write("\n}");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void writeName(String name) {
- try {
- writer.write("\"" + encode(name) + "\" : ");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void startArray() {
- try {
- writer.write("[\n");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void endArray() {
- try {
- writer.write("\n]");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void writeSeparator() {
- try {
- writer.write(", ");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void writeRawString(String value) {
- try {
- writer.write("\"" + value + "\"");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void writeString(String value) {
- try {
- writer.write("\"" + encode(value) + "\"");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void writeNull() {
- try {
- writer.write("null");
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- public void writeStringProperty(String name, String value) {
- if (value == null) {
- writeProperty(name, value, false);
- } else {
- writeProperty(name, encode(value), false);
- }
- }
-
- public void writeRawStringProperty(String name, String value) {
- writeProperty(name, value, false);
- }
-
- public void writeRawProperty(String name, String value) {
- writeProperty(name, value, true);
- }
-
- private void writeProperty(String name, String value, boolean raw) {
- if (firstProperty) {
- firstProperty = false;
- } else {
- writeSeparator();
- }
-
- // write content
- this.writeName(name);
- if (value == null) {
- writeNull();
- } else {
- try {
- if (raw) {
- writeRaw(value);
- } else {
- writeString(value);
- }
- } catch (Exception e) {
- writeString("exception for property with name '" + name
- + "' with message '" + e.getMessage()
- + "' and toString '" + value.toString() + "'.");
- }
- }
-
- }
-
- private void writeRaw(String value) {
- try {
- writer.write(value);
- } catch (IOException e) {
- throw new ODataRuntimeException(e.getMessage(), e);
- }
- }
-
- private String encode(String unencoded) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < unencoded.length(); i++) {
- char c = unencoded.charAt(i);
- if (c == '\\') {
- sb.append("\\\\");
- } else if (c == '"') {
- sb.append("\\\"");
- } else if (c == '\n') {
- sb.append("\\n");
- } else if (c == '\r') {
- sb.append("\\r");
- } else if (c == '\f') {
- sb.append("\\f");
- } else if (c == '\b') {
- sb.append("\\b");
- } else if (c == '\t') {
- sb.append("\\t");
- } else {
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
- public void start() {
- writeRaw("{\n\"d\":");
- }
-
- public void finish() {
- writeRaw("\n}");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/8764e11a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/util/AnnotationHelper.java
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/util/AnnotationHelper.java b/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/util/AnnotationHelper.java
new file mode 100644
index 0000000..0c81fb1
--- /dev/null
+++ b/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/util/AnnotationHelper.java
@@ -0,0 +1,726 @@
+/**
+ * *****************************************************************************
+ * 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.annotation.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.annotation.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.annotation.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.annotation.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.annotation.edm.EdmKey;
+import org.apache.olingo.odata2.api.annotation.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.annotation.edm.EdmNavigationProperty.Multiplicity;
+import org.apache.olingo.odata2.api.annotation.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ *
+ */
+public class AnnotationHelper {
+
+ public static final String DEFAULT_CONTAINER_NAME = "DefaultContainer";
+
+ /**
+ * Compare keys of both instances.
+ *
+ * @param firstInstance
+ * @param secondInstance
+ * @return
+ */
+ public boolean keyMatch(Object firstInstance, Object secondInstance) {
+ if (firstInstance == null || secondInstance == null) {
+ return false;
+ } else if (firstInstance.getClass() != secondInstance.getClass()) {
+ return false;
+ }
+
+ Map<String, Object> firstKeyFields = getValueForAnnotatedFields(firstInstance, EdmKey.class);
+ Map<String, Object> secondKeyFields = getValueForAnnotatedFields(secondInstance, EdmKey.class);
+
+ return keyValuesMatch(firstKeyFields, secondKeyFields);
+ }
+
+ /**
+ * Compare keys of instance with key values in map.
+ *
+ * @param instance
+ * @param keyName2Value
+ * @return
+ */
+ public boolean keyMatch(Object instance, Map<String, Object> keyName2Value) {
+ Map<String, Object> instanceKeyFields = getValueForAnnotatedFields(instance, EdmKey.class);
+ return keyValuesMatch(instanceKeyFields, keyName2Value);
+ }
+
+ private boolean keyValuesMatch(Map<String, Object> firstKeyValues, Map<String, Object> secondKeyValues) {
+ if (firstKeyValues.size() != secondKeyValues.size()) {
+ return false;
+ } else {
+ Set<Map.Entry<String, Object>> entries = firstKeyValues.entrySet();
+ for (Map.Entry<String, Object> entry : entries) {
+ Object firstKey = entry.getValue();
+ Object secondKey = secondKeyValues.get(entry.getKey());
+ if (!isEqual(firstKey, secondKey)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ private boolean isEqual(Object firstKey, Object secondKey) {
+ if (firstKey == null) {
+ if (secondKey == null) {
+ return true;
+ } else {
+ return secondKey.equals(firstKey);
+ }
+ } else {
+ return firstKey.equals(secondKey);
+ }
+ }
+
+ public String extractEntitTypeName(EdmNavigationProperty enp, Class<?> fallbackClass) {
+ Class<?> entityTypeClass = enp.toType();
+ return extractEntityTypeName(entityTypeClass == Object.class ? fallbackClass : entityTypeClass);
+ }
+
+ public String extractEntitTypeName(EdmNavigationProperty enp, Field field) {
+ Class<?> entityTypeClass = enp.toType();
+ if (entityTypeClass == Object.class) {
+ Class<?> toClass = field.getType();
+ return extractEntityTypeName((toClass.isArray() || Collection.class.isAssignableFrom(toClass) ?
+ (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0] : toClass));
+ } else {
+ return extractEntityTypeName(entityTypeClass);
+ }
+ }
+
+ /**
+ * Returns <code>NULL</code> if given class is not annotated. If annotated the set entity type name is returned and if
+ * no name is set the default name is generated from the simple class name.
+ *
+ * @param annotatedClass
+ * @return
+ */
+ public String extractEntityTypeName(Class<?> annotatedClass) {
+ return extractTypeName(annotatedClass, EdmEntityType.class);
+ }
+
+ public FullQualifiedName extractEntityTypeFqn(EdmEntityType type, Class<?> annotatedClass) {
+ if(type.namespace().isEmpty()) {
+ return new FullQualifiedName(generateNamespace(annotatedClass), extractEntityTypeName(annotatedClass));
+ }
+ return new FullQualifiedName(type.namespace(), extractEntityTypeName(annotatedClass));
+ }
+
+ public FullQualifiedName extractEntityTypeFqn(Class<?> annotatedClass) {
+ EdmEntityType type = annotatedClass.getAnnotation(EdmEntityType.class);
+ if(type == null) {
+ return null;
+ }
+ return extractEntityTypeFqn(type, annotatedClass);
+ }
+
+ public FullQualifiedName extractComplexTypeFqn(Class<?> annotatedClass) {
+ EdmComplexType type = annotatedClass.getAnnotation(EdmComplexType.class);
+ if(type == null) {
+ return null;
+ }
+ return extractComplexTypeFqn(type, annotatedClass);
+ }
+
+ public FullQualifiedName extractComplexTypeFqn(EdmComplexType type, Class<?> annotatedClass) {
+ if(type.namespace().isEmpty()) {
+ return new FullQualifiedName(generateNamespace(annotatedClass), extractComplexTypeName(annotatedClass));
+ }
+ return new FullQualifiedName(type.namespace(), extractComplexTypeName(annotatedClass));
+ }
+
+ public String extractComplexTypeName(Class<?> annotatedClass) {
+ return extractTypeName(annotatedClass, EdmComplexType.class);
+ }
+
+ public String generateNamespace(Class<?> annotatedClass) {
+ String packageName = annotatedClass.getPackage().getName();
+ return packageName;
+ }
+
+ /**
+ *
+ *
+ * @param <T> must be EdmEntityType or EdmComplexType annotation
+ * @param annotatedClass
+ * @param typeAnnotation
+ * @return null if annotatedClass is not annotated or name set via annotation or generated via
+ * {@link #getCanonicalName(java.lang.Class)}
+ */
+ private <T extends Annotation> String extractTypeName(Class<?> annotatedClass, Class<T> typeAnnotation) {
+ if (annotatedClass == Object.class) {
+ return null;
+ }
+ T type = annotatedClass.getAnnotation(typeAnnotation);
+ if (type == null) {
+ return null;
+ }
+
+ String name;
+ if (typeAnnotation == EdmEntityType.class) {
+ name = ((EdmEntityType) type).name();
+ } else if (typeAnnotation == EdmComplexType.class) {
+ name = ((EdmComplexType) type).name();
+ } else {
+ return null;
+ }
+
+ if (name.isEmpty()) {
+ return getCanonicalName(annotatedClass);
+ }
+ return name;
+ }
+
+ /**
+ * Get the set property name from an EdmProperty or EdmNavigationProperty annotation.
+ *
+ * @param field
+ * @return
+ */
+ public String getPropertyNameFromAnnotation(Field field) {
+ EdmProperty property = field.getAnnotation(EdmProperty.class);
+ if (property == null) {
+ EdmNavigationProperty navProperty = field.getAnnotation(EdmNavigationProperty.class);
+ if (navProperty == null) {
+ throw new EdmAnnotationException("Given field '" + field
+ + "' has no EdmProperty or EdmNavigationProperty annotation.");
+ }
+ return navProperty.name();
+ }
+ return property.name();
+ }
+
+ public String getPropertyName(Field field) {
+ String propertyName = getPropertyNameFromAnnotation(field);
+ if (propertyName.isEmpty()) {
+ propertyName = getCanonicalName(field);
+ }
+ return propertyName;
+ }
+
+ public String extractFromRoleName(EdmNavigationProperty enp, Field field) {
+ return getCanonicalRole(field.getDeclaringClass());
+ }
+
+ public String extractToRoleName(EdmNavigationProperty enp, Field field) {
+ String role = enp.toRole();
+ if (role.isEmpty()) {
+ role = getCanonicalRole(
+ field.getType().isArray() || Collection.class.isAssignableFrom(field.getType()) ?
+ (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0] : field.getType());
+ }
+ return role;
+ }
+
+ public String getCanonicalRole(Class<?> fallbackClass) {
+ String toRole = extractEntityTypeName(fallbackClass);
+ return "r_" + toRole;
+ }
+
+ public String extractRelationshipName(EdmNavigationProperty enp, Field field) {
+ String relationshipName = enp.association();
+ if (relationshipName.isEmpty()) {
+ final String fromRole = extractFromRoleName(enp, field);
+ final String toRole = extractToRoleName(enp, field);
+ if (fromRole.compareTo(toRole) > 0) {
+ relationshipName = toRole + "-" + fromRole;
+ } else {
+ relationshipName = fromRole + "-" + toRole;
+ }
+ }
+ return relationshipName;
+ }
+
+ public EdmMultiplicity getMultiplicity(EdmNavigationProperty enp, Field field) {
+ EdmMultiplicity multiplicity = mapMultiplicity(enp.toMultiplicity());
+ final boolean isCollectionType = field.getType().isArray() || Collection.class.isAssignableFrom(field.getType());
+
+ if (multiplicity == EdmMultiplicity.ONE && isCollectionType) {
+ return EdmMultiplicity.MANY;
+ }
+ return multiplicity;
+ }
+
+
+ /**
+ * Set key fields based on values in map.
+ * If an key field is not available or <code>NULL</code> in the map
+ * it will be not set as <code>NULL</code> at the instance object.
+ *
+ * @param instance
+ * @param keys
+ * @return
+ */
+ public <T> T setKeyFields(T instance, Map<String, Object> keys) {
+ List<Field> fields = getAnnotatedFields(instance, EdmKey.class);
+
+ for (Field field : fields) {
+ String propertyName = getPropertyName(field);
+ Object keyValue = keys.get(propertyName);
+ setValueForProperty(instance, propertyName, keyValue);
+ }
+
+ return instance;
+ }
+
+ public static final class ODataAnnotationException extends ODataException {
+ private static final long serialVersionUID = 1L;
+
+ public ODataAnnotationException(String message) {
+ super(message);
+ }
+ }
+
+
+ public class AnnotatedNavInfo {
+ private final Field fromField;
+ private final Field toField;
+ private final EdmNavigationProperty fromNavigation;
+ private final EdmNavigationProperty toNavigation;
+
+ public AnnotatedNavInfo(Field fromField, Field toField, EdmNavigationProperty fromNavigation,
+ EdmNavigationProperty toNavigation) {
+ this.fromField = fromField;
+ this.toField = toField;
+ this.fromNavigation = fromNavigation;
+ this.toNavigation = toNavigation;
+ }
+
+ public Field getFromField() {
+ return fromField;
+ }
+
+ public Field getToField() {
+ return toField;
+ }
+
+ public EdmMultiplicity getFromMultiplicity() {
+ return getMultiplicity(toNavigation, toField);
+ }
+
+ public EdmMultiplicity getToMultiplicity() {
+ return getMultiplicity(fromNavigation, fromField);
+ }
+
+ public boolean isBiDirectional() {
+ return toNavigation != null;
+ }
+ }
+
+ public AnnotatedNavInfo getCommonNavigationInfo(Class<?> sourceClass, Class<?> targetClass) {
+ List<Field> sourceFields = getAnnotatedFields(sourceClass, EdmNavigationProperty.class);
+ List<Field> targetFields = getAnnotatedFields(targetClass, EdmNavigationProperty.class);
+
+ // first try via association name to get full navigation information
+ for (Field sourceField : sourceFields) {
+ final EdmNavigationProperty sourceNav = sourceField.getAnnotation(EdmNavigationProperty.class);
+ final String sourceAssociation = extractRelationshipName(sourceNav, sourceField);
+ for (Field targetField : targetFields) {
+ final EdmNavigationProperty targetNav = targetField.getAnnotation(EdmNavigationProperty.class);
+ final String targetAssociation = extractRelationshipName(targetNav, targetField);
+ if (sourceAssociation.equals(targetAssociation)) {
+ return new AnnotatedNavInfo(sourceField, targetField, sourceNav, targetNav);
+ }
+ }
+ }
+
+ // if nothing was found assume none bi-directinal navigation
+ String targetEntityTypeName = extractEntityTypeName(targetClass);
+ for (Field sourceField : sourceFields) {
+ final EdmNavigationProperty sourceNav = sourceField.getAnnotation(EdmNavigationProperty.class);
+ final String navTargetEntityName = extractEntitTypeName(sourceNav, sourceField);
+
+ if (navTargetEntityName.equals(targetEntityTypeName)) {
+ return new AnnotatedNavInfo(sourceField, null, sourceNav, null);
+ }
+ }
+
+ return null;
+ }
+
+ public Class<?> getFieldTypeForProperty(Object instance, String propertyName) throws ODataAnnotationException {
+ if (instance == null) {
+ return null;
+ }
+
+ Field field = getFieldForPropertyName(instance, propertyName, instance.getClass(), true);
+ if (field == null) {
+ throw new ODataAnnotationException("No field for property '" + propertyName
+ + "' found at class '" + instance.getClass() + "'.");
+ }
+ return field.getType();
+ }
+
+ public Object getValueForProperty(Object instance, String propertyName) throws ODataAnnotationException {
+ if (instance == null) {
+ return null;
+ }
+
+ Field field = getFieldForPropertyName(instance, propertyName, instance.getClass(), true);
+ if (field == null) {
+ throw new ODataAnnotationException("No field for property '" + propertyName
+ + "' found at class '" + instance.getClass() + "'.");
+ }
+ return getFieldValue(instance, field);
+ }
+
+ public void setValueForProperty(Object instance, String propertyName, Object propertyValue) {
+ if (instance != null) {
+ Field field = getFieldForPropertyName(instance, propertyName, instance.getClass(), true);
+ if (field != null) {
+ setFieldValue(instance, field, propertyValue);
+ }
+ }
+ }
+
+ private Field getFieldForPropertyName(Object instance, String propertyName,
+ Class<?> resultClass, boolean inherited) {
+ if (instance == null) {
+ return null;
+ }
+
+ Field[] fields = resultClass.getDeclaredFields();
+ for (Field field : fields) {
+ EdmProperty property = field.getAnnotation(EdmProperty.class);
+ if (property != null) {
+ if (property.name().isEmpty() && getCanonicalName(field).equals(propertyName)) {
+ return field;
+ } else if (property.name().equals(propertyName)) {
+ return field;
+ }
+ }
+ }
+
+ Class<?> superClass = resultClass.getSuperclass();
+ if (inherited && superClass != Object.class) {
+ return getFieldForPropertyName(instance, propertyName, superClass, true);
+ }
+
+ return null;
+ }
+
+ public Object getValueForField(Object instance, String fieldName, Class<? extends Annotation> annotation) {
+ if (instance == null) {
+ return null;
+ }
+ return getValueForField(instance, fieldName, instance.getClass(), annotation, true);
+ }
+
+ public Object getValueForField(Object instance, Class<? extends Annotation> annotation) {
+ if (instance == null) {
+ return null;
+ }
+ return getValueForField(instance, instance.getClass(), annotation, true);
+ }
+
+ private Object getValueForField(Object instance, Class<?> resultClass,
+ Class<? extends Annotation> annotation, boolean inherited) {
+ return getValueForField(instance, null, resultClass, annotation, inherited);
+ }
+
+ public Map<String, Object> getValueForAnnotatedFields(Object instance,
+ Class<? extends Annotation> annotation) {
+ return getValueForAnnotatedFields(instance, instance.getClass(), annotation, true);
+ }
+
+ private Map<String, Object> getValueForAnnotatedFields(Object instance, Class<?> resultClass,
+ Class<? extends Annotation> annotation, boolean inherited) {
+ if (instance == null) {
+ return null;
+ }
+
+ Field[] fields = resultClass.getDeclaredFields();
+ Map<String, Object> fieldName2Value = new HashMap<String, Object>();
+
+ for (Field field : fields) {
+ if (field.getAnnotation(annotation) != null) {
+ Object value = getFieldValue(instance, field);
+ final EdmProperty property = field.getAnnotation(EdmProperty.class);
+ final String name = property == null || property.name().isEmpty() ? field.getName() : property.name();
+ fieldName2Value.put(name, value);
+ }
+ }
+
+ Class<?> superClass = resultClass.getSuperclass();
+ if (inherited && superClass != Object.class) {
+ Map<String, Object> tmp = getValueForAnnotatedFields(instance, superClass, annotation, true);
+ fieldName2Value.putAll(tmp);
+ }
+
+ return fieldName2Value;
+ }
+
+ public void setValueForAnnotatedField(Object instance, Class<? extends Annotation> annotation, Object value)
+ throws ODataAnnotationException {
+ List<Field> fields = getAnnotatedFields(instance, annotation);
+
+ if(fields.isEmpty()) {
+ throw new ODataAnnotationException("No field found for annotation '" + annotation
+ + "' on instance '" + instance + "'.");
+ } else if(fields.size() > 1) {
+ throw new ODataAnnotationException("More then one field found for annotation '" + annotation
+ + "' on instance '" + instance + "'.");
+ }
+
+ setFieldValue(instance, fields.get(0), value);
+ }
+
+ public void setValuesToAnnotatedFields(Object instance,
+ Class<? extends Annotation> annotation, Map<String, Object> fieldName2Value) {
+ List<Field> fields = getAnnotatedFields(instance, annotation);
+
+ // XXX: refactore
+ for (Field field : fields) {
+ final String canonicalName = getCanonicalName(field);
+ if (fieldName2Value.containsKey(canonicalName)) {
+ Object value = fieldName2Value.get(canonicalName);
+ setFieldValue(instance, field, value);
+ }
+ }
+ }
+
+ public List<Field> getAnnotatedFields(Object instance, Class<? extends Annotation> annotation) {
+ if (instance == null) {
+ return null;
+ }
+ return getAnnotatedFields(instance.getClass(), annotation, true);
+ }
+
+ public List<Field> getAnnotatedFields(Class<?> fieldClass, Class<? extends Annotation> annotation) {
+ return getAnnotatedFields(fieldClass, annotation, true);
+ }
+
+ /**
+ *
+ * @param instance
+ * @param resultClass
+ * @param annotation
+ * @param inherited
+ * @return
+ */
+ private List<Field> getAnnotatedFields(Class<?> resultClass,
+ Class<? extends Annotation> annotation, boolean inherited) {
+ if (resultClass == null) {
+ return null;
+ }
+
+ Field[] fields = resultClass.getDeclaredFields();
+ List<Field> annotatedFields = new ArrayList<Field>();
+
+ for (Field field : fields) {
+ if (field.getAnnotation(annotation) != null) {
+ annotatedFields.add(field);
+ }
+ }
+
+ Class<?> superClass = resultClass.getSuperclass();
+ if (inherited && superClass != Object.class) {
+ List<Field> tmp = getAnnotatedFields(superClass, annotation, true);
+ annotatedFields.addAll(tmp);
+ }
+
+ return annotatedFields;
+ }
+
+ private Object getValueForField(Object instance, String fieldName, Class<?> resultClass,
+ Class<? extends Annotation> annotation, boolean inherited) {
+ if (instance == null) {
+ return null;
+ }
+
+ Field[] fields = resultClass.getDeclaredFields();
+ for (Field field : fields) {
+ if (field.getAnnotation(annotation) != null
+ && (fieldName == null || field.getName().equals(fieldName))) {
+ return getFieldValue(instance, field);
+ }
+ }
+
+ Class<?> superClass = resultClass.getSuperclass();
+ if (inherited && superClass != Object.class) {
+ return getValueForField(instance, fieldName, superClass, annotation, true);
+ }
+
+ return null;
+ }
+
+ private Object getFieldValue(Object instance, Field field) {
+ try {
+ boolean access = field.isAccessible();
+ field.setAccessible(true);
+ Object value = field.get(instance);
+ field.setAccessible(access);
+ return value;
+ } catch (IllegalArgumentException ex) { // should never happen
+ throw new ODataRuntimeException(ex);
+ } catch (IllegalAccessException ex) { // should never happen
+ throw new ODataRuntimeException(ex);
+ }
+ }
+
+ private void setFieldValue(Object instance, Field field, Object value) {
+ try {
+ Object usedValue = value;
+ if (value != null
+ && field.getType() != value.getClass()
+ && value.getClass() == String.class) {
+ usedValue = convert(field, (String) value);
+ }
+ boolean access = field.isAccessible();
+ field.setAccessible(true);
+ field.set(instance, usedValue);
+ field.setAccessible(access);
+ } catch (IllegalArgumentException ex) { // should never happen
+ throw new ODataRuntimeException(ex);
+ } catch (IllegalAccessException ex) { // should never happen
+ throw new ODataRuntimeException(ex);
+ }
+ }
+
+ public Object convert(Field field, String propertyValue) {
+ Class<?> fieldClass = field.getType();
+ try {
+ EdmProperty property = field.getAnnotation(EdmProperty.class);
+ EdmSimpleTypeKind type = mapTypeKind(property.type());
+ return type.getEdmSimpleTypeInstance().valueOfString(propertyValue,
+ EdmLiteralKind.DEFAULT, null, fieldClass);
+ } catch (EdmSimpleTypeException ex) {
+ throw new ODataRuntimeException("Conversion failed for string property with error: "
+ + ex.getMessage(), ex);
+ }
+ }
+
+ public boolean isEdmAnnotated(Object object) {
+ if (object == null) {
+ return false;
+ }
+ return isEdmAnnotated(object.getClass());
+ }
+
+ public boolean isEdmTypeAnnotated(Class<?> clazz) {
+ boolean isComplexEntity = clazz.getAnnotation(EdmComplexType.class) != null;
+ boolean isEntity = clazz.getAnnotation(EdmEntityType.class) != null;
+ return isComplexEntity || isEntity;
+ }
+
+ public boolean isEdmAnnotated(Class<?> clazz) {
+ if (clazz == null) {
+ return false;
+ } else {
+ final boolean isEntity = null != clazz.getAnnotation(EdmEntityType.class);
+ final boolean isEntitySet = null != clazz.getAnnotation(EdmEntitySet.class);
+ final boolean isComplexEntity = null != clazz.getAnnotation(EdmComplexType.class);
+ return isEntity || isComplexEntity || isEntitySet;
+ }
+ }
+
+ public String getCanonicalName(Field field) {
+ return firstCharToUpperCase(field.getName());
+ }
+
+ public String getCanonicalName(Class<?> clazz) {
+ return firstCharToUpperCase(clazz.getSimpleName());
+ }
+
+ private String firstCharToUpperCase(String content) {
+ if (content == null || content.isEmpty()) {
+ return content;
+ }
+ return content.substring(0, 1).toUpperCase(Locale.ENGLISH) + content.substring(1);
+ }
+
+ public EdmSimpleTypeKind mapTypeKind(org.apache.olingo.odata2.api.annotation.edm.EdmType type) {
+ switch (type) {
+ case BINARY: return EdmSimpleTypeKind.Binary;
+ case BOOLEAN: return EdmSimpleTypeKind.Boolean;
+ case BYTE: return EdmSimpleTypeKind.Byte;
+ case COMPLEX: return EdmSimpleTypeKind.Null;
+ case DATE_TIME: return EdmSimpleTypeKind.DateTime;
+ case DATE_TIME_OFFSET: return EdmSimpleTypeKind.DateTimeOffset;
+ case DECIMAL: return EdmSimpleTypeKind.Decimal;
+ case DOUBLE: return EdmSimpleTypeKind.Double;
+ case GUID: return EdmSimpleTypeKind.Guid;
+ case INT16: return EdmSimpleTypeKind.Int16;
+ case INT32: return EdmSimpleTypeKind.Int32;
+ case INT64: return EdmSimpleTypeKind.Int64;
+ case NULL: return EdmSimpleTypeKind.Null;
+ case SBYTE: return EdmSimpleTypeKind.SByte;
+ case SINGLE: return EdmSimpleTypeKind.Single;
+ case STRING: return EdmSimpleTypeKind.String;
+ case TIME: return EdmSimpleTypeKind.Time;
+ default: throw new ODataRuntimeException("Unknown type '" + type
+ + "' for mapping to EdmSimpleTypeKind.");
+ }
+ }
+
+ public EdmMultiplicity mapMultiplicity(Multiplicity multiplicity) {
+ switch (multiplicity) {
+ case ZERO_OR_ONE: return EdmMultiplicity.ZERO_TO_ONE;
+ case ONE: return EdmMultiplicity.ONE;
+ case MANY: return EdmMultiplicity.MANY;
+ default: throw new ODataRuntimeException("Unknown type '" + multiplicity + "' for mapping to EdmMultiplicity.");
+ }
+ }
+
+ /**
+ *
+ */
+ private static class EdmAnnotationException extends RuntimeException {
+
+ private static final long serialVersionUID = 42L;
+
+ public EdmAnnotationException(String message) {
+ super(message);
+ }
+ }
+
+ public String getCanonicalNamespace(Class<?> aClass) {
+ return generateNamespace(aClass);
+ }
+
+ public String extractContainerName(Class<?> aClass) {
+ EdmEntitySet entitySet = aClass.getAnnotation(EdmEntitySet.class);
+ if(entitySet != null) {
+ String containerName = entitySet.container();
+ if(!containerName.isEmpty()) {
+ return containerName;
+ }
+ }
+ return DEFAULT_CONTAINER_NAME;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/8764e11a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/util/ClassHelper.java
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/util/ClassHelper.java b/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/util/ClassHelper.java
new file mode 100644
index 0000000..5e9fcdb
--- /dev/null
+++ b/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/util/ClassHelper.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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.annotation.util;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FilenameFilter;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ */
+public class ClassHelper {
+
+ private static final File[] EMPTY_FILE_ARRAY = new File[0];
+
+ private static final FilenameFilter CLASSFILE_FILTER = new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith(CLASSFILE_ENDING);
+ }
+ public static final String CLASSFILE_ENDING = ".class";
+ };
+
+ private static final FileFilter FOLDER_FILTER = new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ return pathname.isDirectory();
+ }
+ };
+
+ public static final List<Class<?>> loadClasses(String packageToScan, ClassValidator cv) {
+ return loadClasses(packageToScan, CLASSFILE_FILTER, cv);
+ }
+
+
+ public static final List<Class<?>> loadClasses(String packageToScan, FilenameFilter ff, ClassValidator cv) {
+ final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ String folderToScan = packageToScan.replace(".", "/");
+ URL url = classLoader.getResource(folderToScan);
+ if(url == null) {
+ throw new IllegalArgumentException("No folder to scan found for package '" + packageToScan + "'.");
+ }
+ File folder = new File(url.getFile());
+ File[] classFiles = folder.listFiles(ff);
+ if(classFiles == null) {
+ classFiles = EMPTY_FILE_ARRAY;
+ }
+
+ List<Class<?>> annotatedClasses = new ArrayList<Class<?>>(classFiles.length);
+ for (File file : classFiles) {
+ String name = file.getName();
+ String fqn = packageToScan + "." + name.substring(0, name.length() - 6);
+ try {
+ Class<?> c = classLoader.loadClass(fqn);
+ if (cv.isClassValid(c)) {
+ annotatedClasses.add(c);
+ }
+ } catch (ClassNotFoundException ex) {
+ throw new IllegalArgumentException("Exception during class loading of class '" + fqn +
+ "' with message '" + ex.getMessage() + "'.");
+ }
+ }
+
+ // recursive search
+ File[] subfolders = listSubFolder(folder);
+ for (File file : subfolders) {
+ List<Class<?>> subFolderClazzes = loadClasses(packageToScan + "." + file.getName(), ff, cv);
+ annotatedClasses.addAll(subFolderClazzes);
+ }
+ //
+
+ return annotatedClasses;
+ }
+
+ private static File[] listSubFolder(File folder) {
+ File[] subfolders = folder.listFiles(FOLDER_FILTER);
+ if(subfolders == null) {
+ return EMPTY_FILE_ARRAY;
+ }
+ return subfolders;
+ }
+
+ public interface ClassValidator {
+ boolean isClassValid(Class<?> c);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/8764e11a/odata2-edm-annotation/edm-annotation-core/src/main/resources/log4j.xml
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-core/src/main/resources/log4j.xml b/odata2-edm-annotation/edm-annotation-core/src/main/resources/log4j.xml
deleted file mode 100644
index 90a4706..0000000
--- a/odata2-edm-annotation/edm-annotation-core/src/main/resources/log4j.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
- 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.
--->
-<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
- <appender name="console" class="org.apache.log4j.ConsoleAppender">
- <param name="Target" value="System.out" />
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="%-5p %c{1} - %m%n" />
- </layout>
- </appender>
-
- <logger name="org.apache.olingo.odata2.ref" additivity="false">
- <level value="trace" />
- <appender-ref ref="console" />
- </logger>
-
- <root>
- <priority value="error" />
- <appender-ref ref="console" />
- </root>
-</log4j:configuration>
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/8764e11a/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/data/AnnotationsInMemoryDsTest.java
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/data/AnnotationsInMemoryDsTest.java b/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/data/AnnotationsInMemoryDsTest.java
index b132a0b..04dbefc 100644
--- a/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/data/AnnotationsInMemoryDsTest.java
+++ b/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/data/AnnotationsInMemoryDsTest.java
@@ -24,10 +24,10 @@ import org.apache.olingo.odata2.api.edm.FullQualifiedName;
import org.apache.olingo.odata2.api.edm.provider.EntitySet;
import org.apache.olingo.odata2.api.exception.ODataException;
import org.apache.olingo.odata2.core.annotation.edm.AnnotationEdmProvider;
-import org.apache.olingo.odata2.core.annotation.edm.AnnotationHelper;
import org.apache.olingo.odata2.core.annotation.model.Building;
import org.apache.olingo.odata2.core.annotation.model.ModelSharedConstants;
import org.apache.olingo.odata2.core.annotation.model.Photo;
+import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/8764e11a/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/processor/json/JsonConsumerTest.java
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/processor/json/JsonConsumerTest.java b/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/processor/json/JsonConsumerTest.java
deleted file mode 100644
index 3d7b89d..0000000
--- a/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/processor/json/JsonConsumerTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2013 The Apache Software Foundation.
- *
- * Licensed 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.annotation.processor.json;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.Map;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- *
- */
-public class JsonConsumerTest {
-
- public static final String SIMPLE_TEAM = "{\"d\":{"
- + "\"__metadata\":{\"id\":\"https://localhost/Test.svc/Teams('1')\","
- + "\"uri\":\"https://localhost/Test.svc/Teams('1')\","
- + "\"type\":\"Test.Team\""
- + "},"
- + "\"Id\":\"1\","
- + "\"Name\":\"Team 1\","
- + "\"isScrumTeam\":false}}";
-
- public static final String SIMPLER_TEAM = "{"
- + "\"d\":{"
- + "\"Id\":\"1\",\"Name\":\"Team 1\",\"isScrumTeam\":false"
- + "}}";
-
- @Test
- public void simplerRead() throws Exception {
- InputStream content = encapsulate(SIMPLER_TEAM);
- JsonConsumer jc = new JsonConsumer(content);
- Map<String, String> name2Values = jc.read();
-
-// System.out.println("" + name2Values);
- Assert.assertEquals(3, name2Values.size());
-
- Assert.assertEquals("1", name2Values.get("Id"));
- Assert.assertEquals("Team 1", name2Values.get("Name"));
- Assert.assertEquals("false", name2Values.get("isScrumTeam"));
- }
-
- @Test
- public void simpleRead() throws Exception {
- InputStream content = encapsulate(SIMPLE_TEAM);
- JsonConsumer jc = new JsonConsumer(content);
- Map<String, String> name2Values = jc.read();
-
-// System.out.println("" + name2Values);
- Assert.assertEquals(6, name2Values.size());
-
- Assert.assertEquals("1", name2Values.get("Id"));
- Assert.assertEquals("Team 1", name2Values.get("Name"));
- Assert.assertEquals("false", name2Values.get("isScrumTeam"));
-
- Assert.assertEquals("https://localhost/Test.svc/Teams('1')", name2Values.get("md_id"));
- Assert.assertEquals("https://localhost/Test.svc/Teams('1')", name2Values.get("md_uri"));
- Assert.assertEquals("Test.Team", name2Values.get("md_type"));
- }
-
- public static InputStream encapsulate(final String content) {
- try {
- return new ByteArrayInputStream(content.getBytes("UTF-8"));
- } catch (UnsupportedEncodingException e) {
- // we know that UTF-8 is supported
- throw new RuntimeException("UTF-8 MUST be supported.", e);
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/8764e11a/odata2-edm-annotation/edm-annotation-webref/pom.xml
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-webref/pom.xml b/odata2-edm-annotation/edm-annotation-webref/pom.xml
index 9f4e99f..18ff957 100644
--- a/odata2-edm-annotation/edm-annotation-webref/pom.xml
+++ b/odata2-edm-annotation/edm-annotation-webref/pom.xml
@@ -21,6 +21,10 @@ the License. -->
<relativePath>..</relativePath>
</parent>
+ <properties>
+ <version.slf4j>1.7.1</version.slf4j>
+ </properties>
+
<build>
<finalName>${project.artifactId}</finalName>
<resources>
@@ -88,17 +92,11 @@ the License. -->
<artifactId>olingo-odata2-edm-annotation-core-incubating</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.olingo</groupId>
- <artifactId>olingo-odata2-ref-incubating</artifactId>
- <version>${project.version}</version>
- </dependency>
-
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
- <version>1.7.1</version>
+ <version>${version.slf4j}</version>
</dependency>
</dependencies>