/** * Returns the correct implementation instance for the interface <code>type</code>. For convention * the implentation is named <code>InterfaceName + Impl</code>. * * @param type The interface type * @return The correct ModelProxy subclass (if exists), a ModelProxy instance otherwise * @throws MalformedModelException is the interface or the implementation are not well formed * (they don't respect the conventions). * @throws ModelRuntimeException is any error occurs during the instantiation */ protected ModelProxy createInstance(Class type) { Class backClass; if (implementations.containsKey(type)) backClass = implementations.get(type); else { /* type never seen */ try { Package pkg = type.getPackage(); String pkgN = pkg == null ? "" : pkg.getName(); backClass = Class.forName(pkgN + tableName(type) + CommonStatic.getImplementationSuffix()); } catch (Exception e) { backClass = ModelProxy.class; } Validator.validateModel(type, backClass); initFieldsTypes(type); implementations.put(type, backClass); } ModelProxy impl = null; try { impl = (ModelProxy) backClass.newInstance(); } catch (Exception e) { throw new ModelRuntimeException(e.getMessage()); } return impl; }
/** * Returns a list of inherited {@link Model} interfaces (directly inherited) of the given model * class. * * @param type The given {@link Model} class type. * @return A list of interfaces that <code>type</code> extends directly. */ protected List<Class> getSupers(Class type) { if (!superclasses.containsKey(type)) { List<Class> sC = CommonStatic.getSupers(type); superclasses.put(type, sC); } return superclasses.get(type); }
/** * Returns the conventional table name for a {@link Model} interface. * * @param type A valid Model interface. * @return The conventional table name for the given interface. */ protected String tableName(Class type) { if (tableNames.containsKey(type)) return tableNames.get(type); String tN = CommonStatic.tableName(type); tableNames.put(type, tN); return tN; }
/** * Returns the conventional field name for a getter method. * * @param m The field getter. * @return The field name. * @throws IllegalArgumentException if the method isn't a valid getter. */ protected String fieldName(Method m) { if (fieldNames.containsKey(m)) return fieldNames.get(m); String name = CommonStatic.fieldName(m); fieldNames.put(m, name); return name; }
protected boolean isAnArrayConnection(Class model, String field) { if (!arrayConnections.containsKey(model)) { arrayConnections.put(model, new HashMap<String, Boolean>()); } Map<String, Boolean> map = arrayConnections.get(model); if (map.containsKey(field.toLowerCase())) return map.get(field.toLowerCase()); else map.put(field.toLowerCase(), CommonStatic.isAnArrayConnection(model, field)); return map.get(field.toLowerCase()); }
protected Class getConnectionFieldType(Class model, String field) { if (!connectionType.containsKey(model)) { connectionType.put(model, new HashMap<String, Class>()); } Map<String, Class> map = connectionType.get(model); if (map.containsKey(field.toLowerCase())) return map.get(field.toLowerCase()); else map.put(field.toLowerCase(), CommonStatic.getConnectionFieldType(model, field)); return map.get(field.toLowerCase()); }
/** * If a {@link Model} is part of a composition, and is the weak part (is part of other models), * this method returns all the fields containing connection of {@link ConnectionType.BelongsTo} * type. It's useful in the <code>INSERT</code> of the record, for preventing foreign key * costraint inconsistency. * * @param model The given {@link Model}. * @return A list of fields that represent the Models that owns <code>model</code>. */ protected List<String> belongsTo(Class model) { if (belongsToFields.containsKey(model)) return belongsToFields.get(model); List<Class> sC = getSupers(model); List<String> ownerFields = new ArrayList<String>(); Method[] getters = CommonStatic.getDeclaredGetters(model); for (Method g : getters) /* has a belongs to annotation */ if (g.isAnnotationPresent(Connection.class) && g.getAnnotation(Connection.class).type().equals(ConnectionType.BelongsTo)) { ownerFields.add(fieldName(g)); } for (Class s : sC) ownerFields.addAll(belongsTo(s)); belongsToFields.put(model, ownerFields); return ownerFields; }
private void initFieldsTypes(Class type) { if (types.containsKey(type)) return; // TODO: Checks the connections - handle them differently Map<String, Class> tMap = new HashMap<String, Class>(); Method[] getters = CommonStatic.getGetters(type); for (Method m : getters) if (!m.isAnnotationPresent(Connection.class)) tMap.put(fieldName(m), m.getReturnType()); /* In inheritance case */ if (extendsModels(type)) { List<Class> supers = getSupers(type); for (Class c : supers) tMap.put(/*tableName(c)+*/ getModelId(type), c); } tMap.put("CreatedAt", java.sql.Timestamp.class); tMap.put("UpdatedAt", java.sql.Timestamp.class); types.put(type, tMap); }
protected Class getModelIdType(Class model) { if (!modelIdTypes.containsKey(model)) modelIdTypes.put(model, CommonStatic.getModelIdType(model)); return modelIdTypes.get(model); }
/** * Returns the field with the @link{Id} in the Model interface. For single intheritance, if the Id * is not specified, will be the same of his father class. In multiple inheritance, in order to * avoid multiple keys identification the Id must be defined by the user. * * @param The model interface * @return The Id field name, or "Id" (the default id) if there's not. */ protected String getModelId(Class model) { if (!modelIds.containsKey(model)) modelIds.put(model, CommonStatic.getModelId(model)); return modelIds.get(model); }
/** * Returns all the classes related to <code>type</code> by a {@link Connection} * * @param type The given {@link Model} interface. * @return A list that contains all the models in a relationship with <code>type</code> interface. */ protected List<Class> getAllReleatedClasses(Class type) { if (relatedClasses.containsKey(type)) return relatedClasses.get(type); List<Class> related = new ArrayList<Class>(); Method[] getters = CommonStatic.getDeclaredGetters(type); for (Method g : getters) if (g.isAnnotationPresent(Connection.class)) { Class t = g.getReturnType(); t = t.isArray() ? t.getComponentType() : t; if (!related.contains(t)) related.add(t); } relatedClasses.put(type, related); return related; }