| /* |
| * 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.ext.proxy.utils; |
| |
| import java.lang.annotation.Annotation; |
| import java.lang.reflect.InvocationHandler; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.ParameterizedType; |
| import java.lang.reflect.Proxy; |
| import java.lang.reflect.Type; |
| import java.net.URI; |
| import java.sql.Timestamp; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.olingo.client.api.EdmEnabledODataClient; |
| import org.apache.olingo.client.api.uri.URIBuilder; |
| import org.apache.olingo.client.core.uri.URIUtils; |
| import org.apache.olingo.client.api.domain.ClientAnnotatable; |
| import org.apache.olingo.client.api.domain.ClientAnnotation; |
| import org.apache.olingo.client.api.domain.ClientComplexValue; |
| import org.apache.olingo.client.api.domain.ClientEntity; |
| import org.apache.olingo.client.api.domain.ClientEnumValue; |
| import org.apache.olingo.client.api.domain.ClientLink; |
| import org.apache.olingo.client.api.domain.ClientPrimitiveValue; |
| import org.apache.olingo.client.api.domain.ClientProperty; |
| import org.apache.olingo.client.api.domain.ClientValue; |
| import org.apache.olingo.commons.api.edm.EdmElement; |
| import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; |
| import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; |
| import org.apache.olingo.commons.api.edm.EdmTerm; |
| import org.apache.olingo.commons.api.edm.EdmType; |
| import org.apache.olingo.commons.api.edm.FullQualifiedName; |
| import org.apache.olingo.client.core.domain.ClientAnnotationImpl; |
| import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory; |
| import org.apache.olingo.commons.core.edm.EdmTypeInfo; |
| import org.apache.olingo.ext.proxy.AbstractService; |
| import org.apache.olingo.ext.proxy.api.AbstractTerm; |
| import org.apache.olingo.ext.proxy.api.ComplexCollection; |
| import org.apache.olingo.ext.proxy.api.EntityCollection; |
| import org.apache.olingo.ext.proxy.api.annotations.ComplexType; |
| import org.apache.olingo.ext.proxy.api.annotations.CompoundKey; |
| import org.apache.olingo.ext.proxy.api.annotations.CompoundKeyElement; |
| import org.apache.olingo.ext.proxy.api.annotations.EnumType; |
| import org.apache.olingo.ext.proxy.api.annotations.Key; |
| import org.apache.olingo.ext.proxy.api.annotations.Namespace; |
| import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty; |
| import org.apache.olingo.ext.proxy.api.annotations.Property; |
| import org.apache.olingo.ext.proxy.api.annotations.Term; |
| import org.apache.olingo.ext.proxy.commons.AbstractStructuredInvocationHandler; |
| import org.apache.olingo.ext.proxy.commons.ComplexInvocationHandler; |
| import org.apache.olingo.ext.proxy.commons.EntityInvocationHandler; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public final class CoreUtils { |
| |
| /** |
| * Logger. |
| */ |
| private static final Logger LOG = LoggerFactory.getLogger(CoreUtils.class); |
| |
| private CoreUtils() { |
| // Empty private constructor for static utility classes |
| } |
| |
| public static ClientValue getODataValue( |
| final EdmEnabledODataClient client, final EdmTypeInfo type, final Object obj) { |
| |
| final ClientValue value; |
| |
| if (type.isCollection()) { |
| value = client.getObjectFactory().newCollectionValue(type.getFullQualifiedName().toString()); |
| |
| final EdmTypeInfo intType = new EdmTypeInfo.Builder(). |
| setEdm(client.getCachedEdm()).setTypeExpression(type.getFullQualifiedName().toString()).build(); |
| |
| for (Object collectionItem : (Collection<?>) obj) { |
| if (intType.isPrimitiveType()) { |
| value.asCollection().add(getODataValue(client, intType, collectionItem).asPrimitive()); |
| } else if (intType.isEnumType()) { |
| value.asCollection().add((getODataValue(client, intType, collectionItem)).asEnum()); |
| } else if (intType.isComplexType()) { |
| value.asCollection().add(getODataValue(client, intType, collectionItem).asComplex()); |
| } else { |
| throw new UnsupportedOperationException("Unsupported object type " + intType.getFullQualifiedName()); |
| } |
| } |
| } else if (type.isComplexType()) { |
| |
| final Object objHandler = Proxy.getInvocationHandler(obj); |
| if (objHandler instanceof ComplexInvocationHandler) { |
| value = ((ComplexInvocationHandler) objHandler).getComplex(); |
| |
| final Class<?> typeRef = ((ComplexInvocationHandler) objHandler).getTypeRef(); |
| |
| for (Map.Entry<String, Object> changes : ((ComplexInvocationHandler) objHandler).getPropertyChanges() |
| .entrySet()) { |
| try { |
| value.asComplex().add(getODataComplexProperty( |
| client, type.getFullQualifiedName(), changes.getKey(), changes.getValue())); |
| } catch (Exception ignore) { |
| // ignore value |
| LOG.warn("Error attaching complex {} for field '{}.{}'", |
| type.getFullQualifiedName(), typeRef.getName(), changes.getKey(), ignore); |
| } |
| } |
| |
| } else { |
| throw new IllegalArgumentException(objHandler.getClass().getName() + "' is not a complex value"); |
| } |
| |
| } else if (type.isEnumType()) { |
| value = client.getObjectFactory().newEnumValue(type.getFullQualifiedName().toString(), ((Enum<?>) obj).name()); |
| } else { |
| value = client.getObjectFactory().newPrimitiveValueBuilder().setType(type.getPrimitiveTypeKind()).setValue(obj). |
| build(); |
| } |
| |
| return value; |
| } |
| |
| private static ClientProperty getODataEntityProperty( |
| final EdmEnabledODataClient client, |
| final FullQualifiedName entity, |
| final String property, |
| final Object obj) { |
| |
| final EdmElement edmProperty = client.getCachedEdm().getEntityType(entity).getProperty(property); |
| return getODataProperty(client, edmProperty, property, obj); |
| } |
| |
| private static ClientProperty getODataComplexProperty( |
| final EdmEnabledODataClient client, |
| final FullQualifiedName complex, |
| final String property, |
| final Object obj) { |
| |
| final EdmElement edmProperty = client.getCachedEdm().getComplexType(complex).getProperty(property); |
| return getODataProperty(client, edmProperty, property, obj); |
| } |
| |
| private static ClientProperty getODataProperty( |
| final EdmEnabledODataClient client, |
| final EdmElement edmProperty, |
| final String property, |
| final Object obj) { |
| |
| final EdmTypeInfo type; |
| if (edmProperty == null) { |
| // maybe opentype ... |
| type = null; |
| } else { |
| final EdmType edmType = edmProperty.getType(); |
| |
| type = new EdmTypeInfo.Builder().setEdm(client.getCachedEdm()).setTypeExpression( |
| edmProperty.isCollection() |
| ? "Collection(" + edmType.getFullQualifiedName().toString() + ")" |
| : edmType.getFullQualifiedName().toString()).build(); |
| } |
| |
| return getODataProperty(client, property, type, obj); |
| } |
| |
| public static ClientAnnotation getODataAnnotation( |
| final EdmEnabledODataClient client, final String term, final EdmType type, final Object obj) { |
| |
| ClientAnnotation annotation; |
| |
| if (obj == null) { |
| annotation = new ClientAnnotationImpl(term, null); |
| } else { |
| final EdmTypeInfo valueType = type == null |
| ? guessTypeFromObject(client, obj) |
| : new EdmTypeInfo.Builder().setEdm(client.getCachedEdm()). |
| setTypeExpression(type.getFullQualifiedName().toString()).build(); |
| |
| annotation = new ClientAnnotationImpl(term, getODataValue(client, valueType, obj)); |
| } |
| |
| return annotation; |
| } |
| |
| public static ClientProperty getODataProperty( |
| final EdmEnabledODataClient client, final String name, final EdmTypeInfo type, final Object obj) { |
| |
| ClientProperty property; |
| |
| try { |
| if (obj == null) { |
| property = client.getObjectFactory().newPrimitiveProperty(name, null); |
| } else { |
| final EdmTypeInfo valueType = type == null |
| ? guessTypeFromObject(client, obj) |
| : type; |
| final ClientValue value = getODataValue(client, valueType, obj); |
| |
| if (valueType.isCollection()) { |
| property = client.getObjectFactory().newCollectionProperty(name, value.asCollection()); |
| } else if (valueType.isPrimitiveType()) { |
| property = client.getObjectFactory().newPrimitiveProperty(name, value.asPrimitive()); |
| } else if (valueType.isComplexType()) { |
| property = client.getObjectFactory().newComplexProperty(name, value.asComplex()); |
| } else if (valueType.isEnumType()) { |
| property = client.getObjectFactory().newEnumProperty(name, value.asEnum()); |
| } else { |
| throw new UnsupportedOperationException("Usupported object type " + valueType.getFullQualifiedName()); |
| } |
| } |
| |
| return property; |
| } catch (Exception e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| private static EdmTypeInfo guessTypeFromObject( |
| final EdmEnabledODataClient client, final Object obj) { |
| |
| final EdmTypeInfo.Builder edmTypeInfo = new EdmTypeInfo.Builder().setEdm(client.getCachedEdm()); |
| |
| if (Collection.class.isAssignableFrom(obj.getClass())) { |
| final EdmTypeInfo type = guessPrimitiveType(client, ClassUtils.extractTypeArg(obj.getClass(), |
| EntityCollection.class, ComplexCollection.class, Collection.class)); |
| return edmTypeInfo.setTypeExpression("Collection(" + type.getFullQualifiedName() + ")").build(); |
| } else if (obj instanceof Proxy) { |
| final Class<?> typeRef = obj.getClass().getInterfaces()[0]; |
| final String ns = typeRef.getAnnotation(Namespace.class).value(); |
| final String name = typeRef.getAnnotation(ComplexType.class).name(); |
| return edmTypeInfo.setTypeExpression(new FullQualifiedName(ns, name).toString()).build(); |
| } else if (obj.getClass().getAnnotation(EnumType.class) != null) { |
| final Class<?> typeRef = obj.getClass(); |
| final String ns = typeRef.getAnnotation(Namespace.class).value(); |
| final String name = typeRef.getAnnotation(EnumType.class).name(); |
| return edmTypeInfo.setTypeExpression(new FullQualifiedName(ns, name).toString()).build(); |
| } else { |
| return guessPrimitiveType(client, obj.getClass()); |
| } |
| } |
| |
| private static EdmTypeInfo guessPrimitiveType(final EdmEnabledODataClient client, final Class<?> clazz) { |
| EdmPrimitiveTypeKind bckCandidate = null; |
| |
| for (EdmPrimitiveTypeKind kind : EdmPrimitiveTypeKind.values()) { |
| final Class<?> target = EdmPrimitiveTypeFactory.getInstance(kind).getDefaultType(); |
| |
| if (clazz.equals(target)) { |
| return new EdmTypeInfo.Builder().setEdm(client.getCachedEdm()).setTypeExpression(kind.toString()).build(); |
| } else if (target.isAssignableFrom(clazz)) { |
| bckCandidate = kind; |
| } else if (target == Timestamp.class && kind == EdmPrimitiveTypeKind.DateTimeOffset) { |
| bckCandidate = kind; |
| } |
| } |
| |
| if (bckCandidate == null) { |
| throw new IllegalArgumentException(clazz.getSimpleName() + " is not a simple type"); |
| } else { |
| return new EdmTypeInfo.Builder().setEdm(client.getCachedEdm()).setTypeExpression(bckCandidate.toString()).build(); |
| } |
| } |
| |
| public static void addProperties( |
| final EdmEnabledODataClient client, |
| final Map<String, Object> changes, |
| final ClientEntity entity) { |
| |
| for (Map.Entry<String, Object> entry : changes.entrySet()) { |
| entity.getProperties() |
| .add(getODataEntityProperty(client, entity.getTypeName(), entry.getKey(), entry.getValue())); |
| } |
| } |
| |
| public static void addProperties( |
| final EdmEnabledODataClient client, |
| final Map<String, Object> changes, |
| final ClientComplexValue entity) { |
| |
| for (Map.Entry<String, Object> entry : changes.entrySet()) { |
| entity.add(getODataComplexProperty( |
| client, |
| new FullQualifiedName(entity.getTypeName()), |
| entry.getKey(), |
| entry.getValue())); |
| } |
| } |
| |
| public static void addAnnotations( |
| final EdmEnabledODataClient client, |
| final Map<Class<? extends AbstractTerm>, Object> annotations, |
| final ClientAnnotatable annotatable) { |
| |
| for (Map.Entry<Class<? extends AbstractTerm>, Object> entry : annotations.entrySet()) { |
| final Namespace nsAnn = entry.getKey().getAnnotation(Namespace.class); |
| final Term termAnn = entry.getKey().getAnnotation(Term.class); |
| final FullQualifiedName termName = new FullQualifiedName(nsAnn.value(), termAnn.name()); |
| final EdmTerm term = client.getCachedEdm().getTerm(termName); |
| if (term == null) { |
| LOG.error("Could not find term for class {}", entry.getKey().getName()); |
| } else { |
| annotatable.getAnnotations().add(getODataAnnotation( |
| client, term.getFullQualifiedName().toString(), term.getType(), entry.getValue())); |
| } |
| } |
| } |
| |
| @SuppressWarnings({ "unchecked", "rawtypes" }) |
| private static Enum<?> enumValueToObject(final ClientEnumValue value, final Class<?> reference) { |
| final Namespace namespace = reference.getAnnotation(Namespace.class); |
| final EnumType enumType = reference.getAnnotation(EnumType.class); |
| if (value.getTypeName().equals(namespace.value() + "." + enumType.name())) { |
| return Enum.valueOf((Class<Enum>) reference, value.getValue()); |
| } |
| |
| return null; |
| } |
| |
| private static Object primitiveValueToObject(final ClientPrimitiveValue value, final Class<?> reference) { |
| Object obj; |
| |
| try { |
| obj = reference == null |
| ? value.toValue() |
| : value.toCastValue(reference); |
| } catch (EdmPrimitiveTypeException e) { |
| LOG.warn("While casting primitive value {} to {}", value, reference, e); |
| obj = value.toValue(); |
| } |
| |
| return obj; |
| } |
| |
| private static void setPropertyValue(final Object bean, final Method getter, final Object value) |
| throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { |
| |
| // Assumption: setter is always prefixed by 'set' word |
| final String setterName = getter.getName().replaceFirst("get", "set"); |
| bean.getClass().getMethod(setterName, getter.getReturnType()).invoke(bean, value); |
| } |
| |
| private static Class<?> getPropertyClass(final Class<?> entityClass, final String propertyName) { |
| Class<?> propertyClass = null; |
| try { |
| final Method getter = entityClass.getMethod("get" + StringUtils.capitalize(propertyName)); |
| if (getter != null) { |
| propertyClass = getter.getReturnType(); |
| } |
| } catch (Exception e) { |
| LOG.error("Could not determine the Java type of {}", propertyName, e); |
| } |
| return propertyClass; |
| } |
| |
| public static URIBuilder buildEditLink( |
| final EdmEnabledODataClient client, |
| final String entitySetURI, |
| final Object key) { |
| |
| if (key == null) { |
| return null; |
| } |
| |
| final URIBuilder uriBuilder = StringUtils.isNotBlank(entitySetURI) |
| ? client.newURIBuilder(entitySetURI) |
| : client.newURIBuilder(); |
| |
| if (key.getClass().getAnnotation(CompoundKey.class) == null) { |
| LOG.debug("Append key segment '{}'", key); |
| uriBuilder.appendKeySegment(key); |
| } else { |
| LOG.debug("Append compound key segment '{}'", key); |
| uriBuilder.appendKeySegment(CoreUtils.getCompoundKey(key)); |
| } |
| |
| return uriBuilder; |
| } |
| |
| public static Map<String, Object> getCompoundKey(final Object key) { |
| final Set<CompoundKeyElementWrapper> elements = new TreeSet<CompoundKeyElementWrapper>(); |
| |
| for (Method method : key.getClass().getMethods()) { |
| final Annotation annotation = method.getAnnotation(CompoundKeyElement.class); |
| if (annotation instanceof CompoundKeyElement) { |
| elements.add(new CompoundKeyElementWrapper( |
| ((CompoundKeyElement) annotation).name(), method, ((CompoundKeyElement) annotation).position())); |
| } |
| } |
| |
| final LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>(); |
| |
| for (CompoundKeyElementWrapper element : elements) { |
| try { |
| map.put(element.getName(), element.getMethod().invoke(key)); |
| } catch (Exception e) { |
| LOG.warn("Error retrieving compound key element '{}' value", element.getName(), e); |
| } |
| } |
| |
| return map; |
| } |
| |
| public static Object getKey( |
| final EdmEnabledODataClient client, |
| final EntityInvocationHandler typeHandler, |
| final Class<?> entityTypeRef, |
| final ClientEntity entity) { |
| |
| Object res = null; |
| |
| if (!entity.getProperties().isEmpty()) { |
| final Class<?> keyRef = ClassUtils.getCompoundKeyRef(entityTypeRef); |
| if (keyRef == null) { |
| final ClientProperty property = entity.getProperty(firstValidEntityKey(entityTypeRef)); |
| if (property != null && property.hasPrimitiveValue()) { |
| res = primitiveValueToObject( |
| property.getPrimitiveValue(), getPropertyClass(entityTypeRef, property.getName())); |
| } |
| } else { |
| try { |
| res = keyRef.newInstance(); |
| populate(client, typeHandler, res, CompoundKeyElement.class, entity.getProperties().iterator()); |
| } catch (Exception e) { |
| LOG.error("Error population compound key {}", keyRef.getSimpleName(), e); |
| throw new IllegalArgumentException("Cannot populate compound key"); |
| } |
| } |
| } |
| |
| return res; |
| } |
| |
| private static void populate( |
| final EdmEnabledODataClient client, |
| final EntityInvocationHandler typeHandler, |
| final Object bean, |
| final Class<? extends Annotation> getterAnn, |
| final Iterator<? extends ClientProperty> propItor) { |
| |
| if (bean != null) { |
| final Class<?> typeRef; |
| if (bean instanceof Proxy) { |
| final InvocationHandler handler = Proxy.getInvocationHandler(bean); |
| if (handler instanceof AbstractStructuredInvocationHandler) { |
| typeRef = ((ComplexInvocationHandler) handler).getTypeRef(); |
| } else { |
| throw new IllegalStateException("Invalid bean " + bean); |
| } |
| } else { |
| typeRef = bean.getClass(); |
| } |
| populate(client, typeHandler, bean, typeRef, getterAnn, propItor); |
| } |
| } |
| |
| @SuppressWarnings({ "unchecked" }) |
| private static void populate( |
| final EdmEnabledODataClient client, |
| final EntityInvocationHandler typeHandler, |
| final Object bean, |
| final Class<?> typeRef, |
| final Class<? extends Annotation> getterAnn, |
| final Iterator<? extends ClientProperty> propItor) { |
| |
| if (bean != null) { |
| while (propItor.hasNext()) { |
| final ClientProperty property = propItor.next(); |
| |
| final Method getter = ClassUtils.findGetterByAnnotatedName(typeRef, getterAnn, property.getName()); |
| |
| if (getter == null) { |
| LOG.warn("Could not find any property annotated as {} in {}", |
| property.getName(), bean.getClass().getName()); |
| } else { |
| try { |
| if (property.hasNullValue()) { |
| setPropertyValue(bean, getter, null); |
| } else if (property.hasPrimitiveValue()) { |
| setPropertyValue(bean, getter, primitiveValueToObject( |
| property.getPrimitiveValue(), getPropertyClass(typeRef, property.getName()))); |
| } else if (property.hasComplexValue()) { |
| final Object complex = Proxy.newProxyInstance( |
| Thread.currentThread().getContextClassLoader(), |
| new Class<?>[] { getter.getReturnType() }, |
| ComplexInvocationHandler.getInstance(typeHandler, getter.getReturnType())); |
| |
| populate(client, typeHandler, complex, Property.class, property.getValue().asComplex().iterator()); |
| setPropertyValue(bean, getter, complex); |
| } else if (property.hasCollectionValue()) { |
| final ParameterizedType collType = (ParameterizedType) getter.getGenericReturnType(); |
| final Class<?> collItemClass = (Class<?>) collType.getActualTypeArguments()[0]; |
| |
| Collection<Object> collection = (Collection<Object>) getter.invoke(bean); |
| if (collection == null) { |
| collection = new ArrayList<Object>(); |
| setPropertyValue(bean, getter, collection); |
| } |
| |
| final Iterator<ClientValue> collPropItor = property.getValue().asCollection().iterator(); |
| while (collPropItor.hasNext()) { |
| final ClientValue value = collPropItor.next(); |
| if (value.isPrimitive()) { |
| collection.add(primitiveValueToObject( |
| value.asPrimitive(), getPropertyClass(typeRef, property.getName()))); |
| } else if (value.isComplex()) { |
| final Object collItem = Proxy.newProxyInstance( |
| Thread.currentThread().getContextClassLoader(), |
| new Class<?>[] { collItemClass }, |
| ComplexInvocationHandler.getInstance(typeHandler, collItemClass)); |
| |
| populate(client, typeHandler, collItem, Property.class, value.asComplex().iterator()); |
| collection.add(collItem); |
| } |
| } |
| } |
| } catch (Exception e) { |
| LOG.error("Could not set property {} on {}", getter, bean, e); |
| } |
| } |
| } |
| } |
| } |
| |
| public static Object getObjectFromODataValue( |
| final ClientValue value, |
| final Type typeRef, |
| final AbstractService<?> service) |
| throws InstantiationException, IllegalAccessException { |
| |
| Class<?> internalRef; |
| if (typeRef == null) { |
| internalRef = null; |
| } else { |
| try { |
| internalRef = (Class<?>) ((ParameterizedType) typeRef).getActualTypeArguments()[0]; |
| } catch (ClassCastException e) { |
| internalRef = (Class<?>) typeRef; |
| } |
| } |
| |
| return getObjectFromODataValue(value, internalRef, service); |
| } |
| |
| public static Object getObjectFromODataValue( |
| final ClientValue value, |
| final Class<?> ref, |
| final AbstractService<?> service) |
| throws InstantiationException, IllegalAccessException { |
| |
| final Object res; |
| |
| if (value == null) { |
| res = null; |
| } else if (value.isComplex()) { |
| // complex types supports inheritance in V4, best to re-read actual type |
| Class<?> internalRef = getComplexTypeRef(service, value); |
| res = Proxy.newProxyInstance( |
| Thread.currentThread().getContextClassLoader(), |
| new Class<?>[] { internalRef }, |
| ComplexInvocationHandler.getInstance(value.asComplex(), internalRef, service)); |
| } else if (value.isCollection()) { |
| final ArrayList<Object> collection = new ArrayList<Object>(); |
| |
| final Iterator<ClientValue> collPropItor = value.asCollection().iterator(); |
| while (collPropItor.hasNext()) { |
| final ClientValue itemValue = collPropItor.next(); |
| if (itemValue.isPrimitive()) { |
| collection.add(CoreUtils.primitiveValueToObject(itemValue.asPrimitive(), ref)); |
| } else if (itemValue.isComplex()) { |
| Class<?> internalRef = getComplexTypeRef(service, value); |
| final Object collItem = Proxy.newProxyInstance( |
| Thread.currentThread().getContextClassLoader(), |
| new Class<?>[] { internalRef }, |
| ComplexInvocationHandler.getInstance(itemValue.asComplex(), internalRef, service)); |
| |
| collection.add(collItem); |
| } else if (itemValue.isEnum()) { |
| collection.add(CoreUtils.enumValueToObject(itemValue.asEnum(), ref)); |
| } else { |
| throw new RuntimeException("Unsupported collection item type " + itemValue.getTypeName()); |
| } |
| } |
| |
| res = collection; |
| } else if (value instanceof ClientEnumValue) { |
| res = enumValueToObject((ClientEnumValue) value, ref == null ? getEnumTypeRef(service, value) : ref); |
| } else { |
| res = primitiveValueToObject(value.asPrimitive(), ref); |
| } |
| |
| return res; |
| } |
| |
| public static Collection<Class<? extends AbstractTerm>> getAnnotationTerms( |
| final AbstractService<?> service, final List<ClientAnnotation> annotations) { |
| |
| final List<Class<? extends AbstractTerm>> res = new ArrayList<Class<? extends AbstractTerm>>(); |
| |
| for (ClientAnnotation annotation : annotations) { |
| final Class<? extends AbstractTerm> clazz = service.getTermClass(annotation.getTerm()); |
| if (clazz != null) { |
| res.add(clazz); |
| } |
| } |
| |
| return res; |
| } |
| |
| private static Class<?> getEnumTypeRef(final AbstractService<?> service, final ClientValue value) { |
| return service.getEnumTypeClass(value.getTypeName().replaceAll("^Collection\\(", "").replaceAll("\\)$", "")); |
| } |
| |
| public static Class<?> getComplexTypeRef(final AbstractService<?> service, final ClientValue value) { |
| return service.getComplexTypeClass(value.getTypeName().replaceAll("^Collection\\(", "").replaceAll("\\)$", "")); |
| } |
| |
| private static String firstValidEntityKey(final Class<?> entityTypeRef) { |
| for (Method method : entityTypeRef.getDeclaredMethods()) { |
| if (method.getAnnotation(Key.class) != null) { |
| final Annotation ann = method.getAnnotation(Property.class); |
| if (ann != null) { |
| return ((Property) ann).name(); |
| } |
| } |
| } |
| return null; |
| } |
| |
| public static URI getMediaEditLink(final String name, final ClientEntity entity) { |
| final ClientLink mediaEditLink = entity.getMediaEditLink(name); |
| return mediaEditLink == null ? URIUtils.getURI(entity.getEditLink(), name) : mediaEditLink.getLink(); |
| } |
| |
| public static URI getTargetEntitySetURI(final EdmEnabledODataClient client, final NavigationProperty property) { |
| final URIBuilder uriBuilder = client.newURIBuilder(client.getServiceRoot()); |
| uriBuilder.appendEntitySetSegment(property.targetEntitySet()); |
| return uriBuilder.build(); |
| } |
| } |