/** * 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()) { // make sure name supplied for unmarshalling if (!comp.hasName()) { vctx.addFatal( "Child components of collection must " + "define element name for unmarshalling", comp); } // 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); } } } } } }