/** * Return a map with name as the key and index of position as the value for all parameters of the * full constructor in the RMObject * * @param rmClass * @return */ private Map<String, Attribute> attributeMap(Class rmClass) { Map<String, Attribute> map = new HashMap<String, Attribute>(); Constructor constructor = fullConstructor(rmClass); Annotation[][] annotations = constructor.getParameterAnnotations(); for (int i = 0; i < annotations.length; i++) { if (annotations[i].length == 0) { throw new IllegalArgumentException("missing annotation at position " + i); } Attribute attribute = (Attribute) annotations[i][0]; map.put(attribute.name(), attribute); } return map; }
/* * Return a map with name as the key and index of position as the value for * required parameters of the full constructor in the RMObject * * @param rmClass @return */ private Map<String, Class> attributeType(Class rmClass) { Map<String, Class> map = new HashMap<String, Class>(); Constructor constructor = fullConstructor(rmClass); if (constructor == null) { throw new IllegalArgumentException("no annotated constructor of " + rmClass + ">"); } Annotation[][] annotations = constructor.getParameterAnnotations(); Class[] types = constructor.getParameterTypes(); if (annotations.length != types.length) { throw new IllegalArgumentException("less annotations"); } for (int i = 0; i < types.length; i++) { if (annotations[i].length == 0) { throw new IllegalArgumentException("missing annotations of attribute " + i); } Attribute attribute = (Attribute) annotations[i][0]; map.put(attribute.name(), types[i]); } return map; }
/** * Finds the matching RM class that can be used to create RM object for given value map * * @param valueMap * @return null if no match RM class is found */ public String findMatchingRMClass(Map<String, Object> valueMap) { List simpleTypes = Arrays.asList(SKIPPED_TYPES_IN_MATCHING); for (Class rmClass : typeMap.values()) { log.debug("matching rmClass: " + rmClass.getName()); if (simpleTypes.contains(rmClass.getSimpleName())) { continue; // skip simple value types } // replace underscore separated names with camel case Map<String, Object> filteredMap = new HashMap<String, Object>(); for (String name : valueMap.keySet()) { filteredMap.put(toCamelCase(name), valueMap.get(name)); } Constructor constructor = fullConstructor(rmClass); if (constructor == null) { throw new RuntimeException("annotated constructor missing for " + rmClass); } Annotation[][] annotations = constructor.getParameterAnnotations(); if (annotations == null || annotations.length == 0) { throw new RuntimeException("attribute annotations missing for " + rmClass); } Class[] types = constructor.getParameterTypes(); boolean matched = true; Set<String> attributes = new HashSet<String>(); for (int i = 0; i < types.length; i++) { if (annotations[i].length == 0) { throw new RuntimeException("attribute annotation missing for" + rmClass); } Attribute attribute = (Attribute) annotations[i][0]; attributes.add(attribute.name()); log.debug("checking attribute: " + attribute.name()); String attrName = attribute.name(); Object attrValue = filteredMap.get(attrName); if (attribute.required() && attrValue == null) { log.debug("missing required attribute.."); matched = false; break; } else if (attrValue != null) { if (((attrValue instanceof Boolean) && types[i] != boolean.class) || ((attrValue instanceof Integer) && types[i] != Integer.class) || ((attrValue instanceof Double) && types[i] != double.class)) { log.debug("wrong primitive value type for attribute.."); matched = false; break; } else if (!types[i].isPrimitive() && !types[i].isInstance(attrValue)) { log.debug("wrong value type for attribute.."); matched = false; break; } } } for (String attr : filteredMap.keySet()) { if (!attributes.contains(attr)) { log.debug("unknown attribute: " + attr); matched = false; } } // matching found if (matched) { String className = rmClass.getSimpleName(); log.debug(">>> MATCHING FOUND: " + className); return className; } } return null; }