📄 collectionelement.java
字号:
} // 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()); } } } } } /** * 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. The * result is used for recursive checking to detect conditions where an * inner structure defines a type but an outer one does not (which causes * errors in the current code generation). * * @param vctx validation context * @param type collection item type * @param children list of child components to be checked * @return <code>true</code> if only child is a <value> element with * type, <code>false</code> if not */ private boolean checkCollectionChildren(ValidationContext vctx, IClass type, ArrayList children) { boolean valonly = children.size() == 1; for (int i = 0; i < children.size(); i++) { ElementBase child = (ElementBase)children.get(i); if (!vctx.isSkipped(child)) { // track whether children of this child must be type-checked boolean expand = true; valonly = valonly && (child instanceof ValueElement); if (child instanceof IComponent) { // first make sure a name is present IComponent comp = (IComponent)child; if (vctx.isInBinding() && !comp.hasName() && comp instanceof ValueElement) { vctx.addFatal("<value> elements within a collection " + "must define element name for unmarshalling", comp); } // find the type associated with this component (if any) IClass ctype = comp.getType(); expand = false; if (comp instanceof ContainerElementBase) { ContainerElementBase contain = (ContainerElementBase)comp; if (contain.hasObject()) { ctype = contain.getObjectType(); } else { expand = true; } } // see if a type was found (no need to look at children) if (!expand) { // verify that type is compatible with collection if (!ctype.isAssignable(type)) { vctx.addFatal("References to collection items must " + "use compatible types: " + ctype.getName() + " cannot be used as " + type.getName(), child); } } } // recurse on children if necessary for type-checking if (expand && child instanceof NestingElementBase) { NestingElementBase nest = (NestingElementBase)child; if (nest.children().size() > 0) { // type check child definitions boolean valchild = checkCollectionChildren(vctx, type, ((NestingElementBase)child).children()); // now check for structure element with no type if (!valchild && child instanceof StructureElement) { vctx.addError("Type must be specified on outermost <structure> element within collection", child); } } } } } return valonly; } /** * Check children of unordered collection for consistency. In an input * binding each child element must define a unique qualified name. In an * output binding each child element must define a unique type or supply * a test method to allow checking when that element should be generated for * an object. * * @param vctx validation context * @param children list of child components */ private void checkUnorderedChildren(ValidationContext vctx, ArrayList children) { HashMap typemap = new HashMap(); HashMap namemap = new HashMap(); for (int i = 0; i < children.size(); i++) { ElementBase child = (ElementBase)children.get(i); if (child instanceof IComponent && !vctx.isSkipped(child)) { IComponent comp = (IComponent)child; if (vctx.isInBinding()) { // names must be distinct in input binding String name = comp.getName(); String uri = comp.getUri(); if (uri == null) { uri = ""; } Object value = namemap.get(name); if (value == null) { // first instance of name, store directly namemap.put(name, comp); } else if (value instanceof HashMap) { // multiple instances already found, match on URI HashMap urimap = (HashMap)value; if (urimap.get(uri) != null) { vctx.addError("Duplicate names are not " + "allowed in unordered collection", comp); } else { urimap.put(uri, comp); } } else { // duplicate name, check URI IComponent match = (IComponent)value; if ((uri == null && match.getUri() == null) || (uri != null && uri.equals(match.getUri()))) { vctx.addError("Duplicate names are not " + "allowed in unordered collection", comp); } else { // multiple namespaces for same name, use map HashMap urimap = new HashMap(); urimap.put(uri, comp); String muri = match.getUri(); if (muri == null) { muri = ""; } urimap.put(muri, match); namemap.put(name, urimap); } } } if (vctx.isOutBinding()) { // just accumulate lists of each type in this loop String type = comp.getType().getName(); Object value = typemap.get(type); if (value == null) { typemap.put(type, comp); } else if (value instanceof ArrayList) { ArrayList types = (ArrayList)value; types.add(comp); } else { ArrayList types = new ArrayList(); types.add(value); types.add(comp); typemap.put(type, types); } } } } // check for duplicate type usage in output binding for (Iterator iter = typemap.values().iterator(); iter.hasNext();) { Object value = iter.next(); if (value instanceof ArrayList) { // multiple instances of type, make sure we can distinguish ArrayList types = (ArrayList)value; for (int i = 0; i < types.size(); i++) { Object child = types.get(i); if (child instanceof ValueElement) { ValueElement vel = (ValueElement)child; if (vel.getTest() == null) { vctx.addError("test-method needed for " + "multiple instances of same type in " + "unordered collection", vel); } } else if (child instanceof StructureElementBase) { StructureElementBase sel = (StructureElementBase)child; if (sel.getTest() == null) { vctx.addError("test-method needed for " + "multiple instances of same type in " + "unordered collection", sel); } } } } } } /** * Check children of ordered collection for consistency. In an input binding * each child element must use a different qualified name from the preceding * child element. In an output binding each child element must define a * different type from the preceding child element, or the preceding child * element must supply a test method to allow checking when that element * should be generated for an object. * * @param vctx validation context * @param children list of child components */ private void checkOrderedChildren(ValidationContext vctx, ArrayList children) { IComponent prior = null; for (int i = 0; i < children.size(); i++) { ElementBase child = (ElementBase)children.get(i); if (child instanceof IComponent && !vctx.isSkipped(child)) { IComponent comp = (IComponent)child; if (prior == null) { prior = comp; } else { if (vctx.isInBinding()) { // make sure names are different String uri = comp.getUri(); String cname = comp.getName(); String pname = prior.getName(); if (cname != null && pname != null && cname.equals(pname) && ((uri == null && prior.getUri() == null) || (uri != null && uri.equals(prior.getUri())))) { vctx.addError("Successive elements of collection " + "cannot use duplicate names for unmarshalling", comp); } } if (vctx.isOutBinding()) { // make sure types differ or test method supplied IClass type = comp.getType(); if (type.isAssignable(prior.getType())) { IClassItem test = null; if (prior instanceof ValueElement) { test = ((ValueElement)prior).getTest(); } else if (prior instanceof StructureElementBase) { test = ((StructureElementBase)prior).getTest(); } if (test == null) { vctx.addError("Collection component must " + "specify a test-method to distinguish " + "from next component of compatible type " + "for marshalling", prior); } } } } } } } /* (non-Javadoc) * @see org.jibx.binding.model.ElementBase#validate(org.jibx.binding.model.ValidationContext) */ public void validate(ValidationContext vctx) { // call base class method first super.validate(vctx); // check for way to determine if named collection present on output if (vctx.isOutBinding() && hasName() && !hasProperty() && isOptional() && getTest() == null && !(vctx.getParentContainer() instanceof CollectionElement)) { vctx.addError ("Need test method for optional collection output element"); } // make sure only element components are present ArrayList children = children(); for (int i = 0; i < children.size(); i++) { IComponent child = (IComponent)children.get(i); if (child.hasAttribute()) { vctx.addFatal ("Attributes not allowed as child components of collection", child); } } // check each child component checkCollectionChildren(vctx, m_itemTypeClass, children); // make sure child components can be distinguished if (children.size() > 1) { if (isOrdered()) { checkOrderedChildren(vctx, children); } else { checkUnorderedChildren(vctx, children); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -