private boolean checkForAdapter(String s, Set<IRelation> filtered) { IClass adapter = findClass(s); IClass adaptee = null; IClass target = null; for (IRelation r : filtered) { if (r.getSrc().equals(s) && r.getType().equals("ASSOCIATION")) { adaptee = findClass(r.getDest()); } if (r.getSrc().equals(s) && r.getType().equals("IMPLEMENTS")) { target = findClass(r.getDest()); } } if (adaptee == null || target == null) return false; for (IField f : adapter.getFields()) { if (f.getType().equals(adaptee.getName())) { adapter.setStereotype("adapter"); adaptee.setStereotype("adaptee"); target.setStereotype("target"); adapter.setPattern("ADAPTER"); adaptee.setPattern("ADAPTER"); target.setPattern("ADAPTER"); for (IRelation r : m.getRelations()) { if (r.getSrc().equals(s) && r.getDest().equals(adaptee.getName()) && r.getType().equals("ASSOCIATION")) { r.setLabel("adapts"); } } return true; } } return false; }
/** * Check that child components are of types compatible with the collection item-type. This method * may call itself recursively to process the children of child components which do not themselves * set a type. * * @param vctx validation context * @param type collection item type * @param children list of child components to be checked */ private void checkCollectionChildren(ValidationContext vctx, IClass type, ArrayList children) { for (int i = 0; i < children.size(); i++) { ElementBase child = (ElementBase) children.get(i); if (!vctx.isSkipped(child)) { boolean expand = true; if (child instanceof IComponent) { IComponent comp = (IComponent) child; IClass ctype = comp.getType(); expand = false; if (comp instanceof ContainerElementBase) { ContainerElementBase contain = (ContainerElementBase) comp; if (contain.hasObject()) { ctype = contain.getObjectType(); } else { expand = true; } } if (!expand) { if (!ctype.isAssignable(type)) { vctx.addFatal( "References to collection items must " + "use compatible types: " + ctype.getName() + " cannot be used as " + type.getName(), child); } } } if (expand && child instanceof NestingElementBase) { checkCollectionChildren(vctx, type, ((NestingElementBase) child).children()); } } } }
/** * Get best binding component for class. Finds the component based on a fully qualified class * name. If a specific component for the actual class is not found (either in this or a containing * level) this returns the most specific superclass component. * * @param clas information for target class * @return binding component definition for class, or <code>null</code> if none found */ public ElementBase getMostSpecificComponent(IClass clas) { ElementBase comp = getSpecificComponent(clas.getName()); while (comp == null) { IClass sclas = clas.getSuperClass(); if (sclas == null) { break; } clas = sclas; comp = getSpecificComponent(clas.getName()); } return comp; }
private IClass findClass(String s) { for (IClass c : m.getClasses()) { if (c.getName().equals(s)) { return c; } } return null; }
/** * Add typed component to set defined at this level. This associated the component with the type * for class hierarchy-based lookups. * * @param type type name to be associated with component * @param comp definition component to be added * @param vctx validation context in use */ public void addTypedComponent(IClass clas, ElementBase comp, ValidationContext vctx) { String type = clas.getName(); if (m_typeToComponentMap.put(type, comp) == null) { // new type, add all interfaces and supertypes to compatible set String[] interfaces = clas.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { m_compatibleTypeSet.add(interfaces[i]); } IClass sclas = clas; do { m_compatibleTypeSet.add(sclas.getName()); } while ((sclas = sclas.getSuperClass()) != null); } else { vctx.addError("Duplicate conversion defined for type " + type, comp); } }
/** * Checks if a class is compatible with one or more components. If a specific component for the * actual class is not found (either in this or a containing level) this checks for components * that handle subclasses or implementations of the class. * * @param clas information for target class * @return <code>true</code> if compatible type, <code>false</code> if not */ public boolean isCompatibleType(IClass clas) { if (m_compatibleTypeSet.contains(clas.getName())) { return true; } else if (m_outerContext != null) { return m_outerContext.isCompatibleType(clas); } else { return false; } }
/* (non-Javadoc) * @see org.jibx.binding.model.ElementBase#prevalidate(org.jibx.binding.model.ValidationContext) */ public void prevalidate(ValidationContext vctx) { // first process attributes and check for errors super.prevalidate(vctx); if (!vctx.isSkipped(this)) { // check for ignored attributes if (isAllowRepeats()) { vctx.addWarning("'allow-repeats' attribute ignored on collection"); } if (isChoice()) { vctx.addWarning("'choice' attribute ignored on collection"); } // get the actual collection type and item type IClass clas = getType(); if (clas == null) { clas = vctx.getContextObject().getObjectType(); } String tname = m_itemTypeName; if (tname == null) { String ctype = clas.getName(); if (ctype.endsWith("[]")) { tname = ctype.substring(0, ctype.length() - 2); } else { tname = "java.lang.Object"; } } m_itemTypeClass = vctx.getClassInfo(tname); if (m_itemTypeClass == null) { vctx.addFatal("Can't find class " + tname); } // handle input and output bindings separately if (vctx.isInBinding()) { // check store techniques String sname = m_storeMethodName; String aname = m_addMethodName; if (sname != null && aname != null) { vctx.addWarning("Both store-method and add-method " + "supplied; using add-method"); sname = null; } // set defaults based on collection type if needed if (sname == null && aname == null) { if (clas.isSuperclass("java.util.ArrayList") || clas.isSuperclass("java.util.Vector") || clas.isImplements("Ljava/util/Collection;")) { aname = "add"; } else if (!clas.getName().endsWith("[]")) { vctx.addError("Need store-method or add-method for " + "input binding"); } } // find the actual method information if (sname != null) { m_storeMethodItem = clas.getBestMethod(sname, null, new String[] {"int", tname}); if (m_storeMethodItem == null) { vctx.addError("store-method " + sname + " not found in class " + clas.getName()); } } if (aname != null) { m_addMethodItem = clas.getBestMethod(aname, null, new String[] {tname}); if (m_addMethodItem == null) { vctx.addError("add-method " + aname + " not found in class " + clas.getName()); } } } if (vctx.isOutBinding()) { // precheck load techniques String lname = m_loadMethodName; String sname = m_sizeMethodName; String iname = m_iterMethodName; if (lname == null) { if (sname != null) { vctx.addWarning("size-method requires load-method; " + "ignoring supplied size-method"); sname = null; } } else { if (sname == null) { vctx.addWarning("load-method requires " + "size-method; ignoring supplied load-method"); lname = null; } else { if (iname != null) { vctx.addWarning("Both load-method and " + "iter-method supplied; using load-method"); iname = null; } } } // set defaults based on collection type if needed if (lname == null && iname == null) { if (clas.isSuperclass("java.util.ArrayList") || clas.isSuperclass("java.util.Vector")) { lname = "get"; sname = "size"; } else if (clas.isImplements("Ljava/util/Collection;")) { iname = "iterator"; } } // postcheck load techniques with defaults set if (lname == null) { if (iname == null && !clas.getName().endsWith("[]")) { vctx.addError( "Need load-method and size-method, or " + "iter-method, for output binding"); } } else { if (sname == null && iname == null) { vctx.addError( "Need load-method and size-method," + " or iter-method, for output binding"); } } // find the actual method information if (lname != null) { m_loadMethodItem = clas.getBestMethod(lname, tname, new String[] {"int"}); if (m_loadMethodItem == null) { vctx.addError("load-method " + lname + " not found in class " + clas.getName()); } } if (iname != null) { m_iterMethodItem = clas.getBestMethod(iname, "java.util.Iterator", new String[0]); if (m_iterMethodItem == null) { vctx.addError("iter-method " + iname + " not found in class " + clas.getName()); } } } } }