public void exportXMLTemplate( StringBuffer sb_header, StringBuffer sb_body, HashSet<String> hs, String indent) { // write in opening tag, put in there the attributes (and also to sb_header), then close, then // call the children (indented), then closing tag. // 0 - ELEMENT and ATTLIST if (!hs.contains(type)) { hs.add(type); sb_header.append("\t<!ELEMENT ").append(type); if (null != al_children && 0 != al_children.size()) { sb_header.append(" ("); int c = 0; for (final TemplateThing child : al_children) { if (0 != c) sb_header.append(", "); c++; sb_header.append(child.type); } sb_header.append(")"); } else { sb_header.append(" EMPTY"); } sb_header.append(">\n"); sb_header.append("\t<!ATTLIST ").append(type).append(" id NMTOKEN #REQUIRED>\n"); } // 1 - opening tag with attributes: sb_body.append(indent).append("<").append(type).append(" id=\"").append(id).append("\""); sb_body.append(">\n"); // 2 - list of children: if (null != al_children && 0 != al_children.size()) { for (final TemplateThing child : al_children) { child.exportXMLTemplate(sb_header, sb_body, hs, indent + "\t"); } } // 3 - closing tag: sb_body.append(indent).append("</").append(type).append(">\n"); }
/** * Returns the list of parents to reach a particular child, starting at this, and including the * child. Only the first path is reported, others are ignored. */ protected ArrayList<TemplateThing> getTemplatePathTo(String type, ArrayList<TemplateThing> al) { al.add(this); if (null == al_children) return al; for (final TemplateThing tt : al_children) { if (tt.type.equals(type)) { // end. Return the list of parents to get here, plus the found type at the end as a means of // signal // Utils.log2("found " + tt); al.add(tt); return al; } else { // scan its children, if any // Utils.log2("looking at " + tt); ArrayList<TemplateThing> al2 = tt.getTemplatePathTo(type, new ArrayList<TemplateThing>(al)); /* //debug: String all = ""; for (int i=0; i<al2.size(); i++) all += " " + al2.get(i); Utils.log2("al2: " + all); */ if (al2.size() > 0 && ((TemplateThing) al2.get(al2.size() - 1)).type.equals(type)) { return al2; } } } return al; }
/** Recursive into children. */ public ArrayList<TemplateThing> collectAllChildren(final ArrayList<TemplateThing> al) { if (null == al_children) return al; al.addAll(al_children); for (final TemplateThing tt : al_children) { tt.collectAllChildren(al); } return al; }
/** Recursive into children! Will add the attributes as well and grab an id for this instance. */ public void addToDatabase(Project project) { this.project = project; this.id = project.getLoader().getNextId(); super.addToDatabase(); if (null == al_children || al_children.isEmpty()) return; for (final TemplateThing child : al_children) { child.addToDatabase(project); } }
/** * Find things of the same type, even if their parents are different, recusively into children. */ public HashSet<TemplateThing> collectThingsOfEqualType( final TemplateThing tt, final HashSet<TemplateThing> hs) { if (type.equals(tt.type)) hs.add(this); if (null == al_children || al_children.isEmpty()) return hs; for (final TemplateThing child : al_children) { child.collectThingsOfEqualType(tt, hs); } return hs; }
/** * Recursive into children. The parent of each stored TemplateThing are not meaningful for a tree; * only the children are meaningful. */ public HashMap<String, TemplateThing> getUniqueTypes(final HashMap<String, TemplateThing> ht) { if (ht.containsKey(this.type)) return ht; ht.put(this.type, this); if (null == al_children || al_children.isEmpty()) return ht; for (final TemplateThing tt : al_children) { tt.getUniqueTypes(ht); } return ht; }
/** For reconstruction purposes. */ public void setup(ArrayList<TemplateThing> al_children) { if (null == al_children || 0 == al_children.size()) { this.al_children = null; } else { this.al_children = al_children; // set parent for (final TemplateThing child : al_children) { child.parent = this; } } }
/** * Recursive into children, find those of the given type that have the same immediate parent type * as the given TemplateThing. */ public HashSet<TemplateThing> collectSimilarThings( final TemplateThing tt, final HashSet<TemplateThing> hs) { if (type.equals(tt.type) && parent.type.equals(tt.parent.type)) { hs.add(this); } if (null == al_children || al_children.isEmpty()) return hs; for (final TemplateThing child : al_children) { child.collectSimilarThings(tt, hs); } return hs; }
/** * Recursive into children, find those of the same type as the given TemplateThing and whose * number of children is the same to those of the given TemplateThing (to exclude nested types). */ public HashSet<TemplateThing> collectSimilarThings2( final TemplateThing tt, final HashSet<TemplateThing> hs) { if (type.equals(tt.type) && (al_children == tt.al_children /*if both are null*/ || (null != al_children && null != tt.al_children && al_children.size() == tt.al_children.size()))) hs.add(this); if (null == al_children || al_children.isEmpty()) return hs; for (final TemplateThing child : al_children) { child.collectSimilarThings2(tt, hs); } return hs; }
public void debug(String indent) { System.out.println(indent + this.type + " (id)"); if (null != al_children) { if (isNested()) { System.out.println(indent + "-- Nested type."); return; } if (indent.length() > 20) { System.out.println("INDENT OVER 20 !"); return; } for (final TemplateThing tt : al_children) { tt.debug(indent + "\t"); } } }
public boolean remove(boolean check) { if (check) { if (!Utils.check( "Really delete " + this.toString() + (null == al_children || 0 == al_children.size() ? "" : " and all its children?"))) return false; } // remove the children, recursively if (null != al_children) { Object[] children = new Object[al_children.size()]; al_children.toArray( children); // can't delete directly from the al_children because the child will call // removeChild on its parent for (int i = 0; i < children.length; i++) { Object ob = children[i]; if (ob instanceof DBObject) { if (!((DBObject) ob).remove(false)) { Utils.showMessage("Deletion incomplete, check database, for child: " + ob.toString()); return false; } } } } // remove the Thing itself if (null != parent && !parent.removeChild(this)) { Utils.showMessage( "Deletion incomplete, check database, for parent of TemplateThing id=" + id); return false; } return removeFromDatabase(); }
/** Only the header !ELEMENT and !ATTLIST. */ public void exportDTD( final StringBuilder sb_header, final HashSet<String> hs, final String indent) { final String tag = type.replace(' ', '_'); if (hs.contains(tag)) return; hs.add(tag); sb_header.append(indent).append("<!ELEMENT ").append(tag); if (null != al_children && 0 != al_children.size()) { sb_header.append(" ("); int c = 0; for (final TemplateThing child : al_children) { if (0 != c) sb_header.append(", "); c++; sb_header.append(child.type); } sb_header.append(")"); } else { sb_header.append(" EMPTY"); } sb_header.append(">\n"); sb_header .append(indent) .append("<!ATTLIST ") .append(tag) .append(" id NMTOKEN #REQUIRED>\n"); // 'id' exists separate from the other attributes // if it's a basic type it can contain a DBObject if (Project.isBasicType(type)) { sb_header.append(indent).append("<!ATTLIST ").append(tag).append(" oid NMTOKEN #REQUIRED>\n"); } // node expanded state sb_header .append(indent) .append("<!ATTLIST ") .append(tag) .append( " expanded NMTOKEN #REQUIRED>\n"); // TODO should not say #REQUIRED but optional, in // XMLese // recurse into children if (null != al_children && 0 != al_children.size()) { for (final TemplateThing child : al_children) { child.exportDTD(sb_header, hs, indent); } } }
// recursive private ArrayList<TemplateThing> scanChildTrees( final String type, ArrayList<TemplateThing> al, HashSet<TemplateThing> hs_done) { if (null == al) al = new ArrayList<TemplateThing>(); if (null == al_children) return al; for (final TemplateThing tt : al_children) { if (tt.type.equals(type)) { al.add(tt); // don't look any further down for this found Thing } else { if (!hs_done.contains( tt)) { // don't recurse into TemplateThing instances that have been visited already // (TODO future: this could be a limitation that may have to be addressed) hs_done.add(tt); // important! Before! al = tt.scanChildTrees(type, al, hs_done); } } } return al; }
/** Recursive into children: clones the whole tree from this node downward. */ public TemplateThing clone(final Project pr, final boolean copy_id) { final long nid = copy_id ? this.id : pr.getLoader().getNextId(); final TemplateThing copy = new TemplateThing(this.type, pr, nid); copy.project = pr; copy.addToDatabase(); // clone children if (null == al_children) return copy; for (final TemplateThing child : al_children) { copy.addChild(child.clone(pr, copy_id)); } return copy; }
/** Compares the String type, for sorting purposes. */ @Override public int compareTo(final TemplateThing o) { return this.type.compareTo(o.getType()); }