package com.sap.hana.cloud.samples.benefits.odata.cfg; import java.beans.IntrospectionException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind; import org.apache.olingo.odata2.api.edm.provider.ComplexType; import org.apache.olingo.odata2.api.edm.provider.Property; import org.apache.olingo.odata2.api.edm.provider.SimpleProperty; import com.sap.hana.cloud.samples.benefits.bean.BeanDescriber; import com.sap.hana.cloud.samples.benefits.odata.beans.BenefitsAmount; import com.sap.hana.cloud.samples.benefits.odata.beans.StartCampaignDetails; import com.sap.hana.cloud.samples.benefits.odata.beans.UIConfig; import com.sap.hana.cloud.samples.benefits.odata.beans.UserInfo; public final class ComplexTypesDescriber { private static ComplexTypesDescriber INTANCE; private static final Map<Class<?>, String> CLASS_TYPES = new HashMap<>(); static { CLASS_TYPES.put(StartCampaignDetails.class, "StartCampaignDetails"); //$NON-NLS-1$ CLASS_TYPES.put(UIConfig.class, "UIConfig"); //$NON-NLS-1$ CLASS_TYPES.put(UserInfo.class, FunctionImportEntitySets.USER_INFO); CLASS_TYPES.put(BenefitsAmount.class, FunctionImportEntitySets.BENEFITS_AMOUNT); } private final List<ComplexType> edmComplexTypes; private ComplexTypesDescriber() { this.edmComplexTypes = describeTypes(); } public static ComplexTypesDescriber getInstance() { if (INTANCE == null) { INTANCE = new ComplexTypesDescriber(); } return INTANCE; } private List<ComplexType> describeTypes() { List<ComplexType> types = new ArrayList<>(); for (Entry<Class<?>, String> odataType : CLASS_TYPES.entrySet()) { try { types.add(describeType(odataType.getKey(), odataType.getValue())); } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException | NoSuchFieldException | IntrospectionException ex) { throw new IllegalStateException("Invalid OData configuration!", ex); //$NON-NLS-1$ } } return types; } private ComplexType describeType(Class<?> odataType, String name) throws SecurityException, IllegalArgumentException, InstantiationException, IllegalAccessException, IntrospectionException, NoSuchFieldException { List<Field> fields = getTypeFields(odataType); List<Property> properties = new ArrayList<>(); for (Field field : fields) { properties.add(createProperty(field)); } ComplexType complexType = new ComplexType(); complexType.setName(name); complexType.setProperties(properties); return complexType; } private List<Field> getTypeFields(Class<?> odataType) throws InstantiationException, IllegalAccessException, IntrospectionException, NoSuchFieldException { BeanDescriber beanDescriber = new BeanDescriber(odataType.newInstance()); List<String> propertyNames = beanDescriber.getPropertyNames(); List<Field> fields = new ArrayList<>(); for (String propName : propertyNames) { fields.add(odataType.getDeclaredField(propName)); } return fields; } @SuppressWarnings("nls") private Property createProperty(Field field) { switch (field.getType().getCanonicalName()) { case "java.lang.String": return createProperty(field.getName(), EdmSimpleTypeKind.String); case "java.lang.Short": case "short": return createProperty(field.getName(), EdmSimpleTypeKind.Int16); case "java.lang.Integer": case "int": return createProperty(field.getName(), EdmSimpleTypeKind.Int32); case "java.lang.Long": case "long": return createProperty(field.getName(), EdmSimpleTypeKind.Int64); case "java.lang.Boolean": case "boolean": return createProperty(field.getName(), EdmSimpleTypeKind.Boolean); case "java.lang.Double": case "double": return createProperty(field.getName(), EdmSimpleTypeKind.Double); default: String errMsg = String.format("Unsupported type [%s} for property [%s]!", field.getType().getCanonicalName(), field.getName()); throw new IllegalArgumentException(errMsg); } } private SimpleProperty createProperty(String propertyName, EdmSimpleTypeKind propertyType) { SimpleProperty property = new SimpleProperty(); property.setName(propertyName); property.setType(propertyType); return property; } public List<ComplexType> getEdmComplexTypes() { return edmComplexTypes; } }