0001: //==============================================================================
0002: //===
0003: //=== EditLib
0004: //===
0005: //=============================================================================
0006: //=== Copyright (C) 2001-2007 Food and Agriculture Organization of the
0007: //=== United Nations (FAO-UN), United Nations World Food Programme (WFP)
0008: //=== and United Nations Environment Programme (UNEP)
0009: //===
0010: //=== This program is free software; you can redistribute it and/or modify
0011: //=== it under the terms of the GNU General Public License as published by
0012: //=== the Free Software Foundation; either version 2 of the License, or (at
0013: //=== your option) any later version.
0014: //===
0015: //=== This program is distributed in the hope that it will be useful, but
0016: //=== WITHOUT ANY WARRANTY; without even the implied warranty of
0017: //=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0018: //=== General Public License for more details.
0019: //===
0020: //=== You should have received a copy of the GNU General Public License
0021: //=== along with this program; if not, write to the Free Software
0022: //=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
0023: //===
0024: //=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
0025: //=== Rome - Italy. email: geonetwork@osgeo.org
0026: //==============================================================================
0027:
0028: package org.fao.geonet.kernel;
0029:
0030: import java.util.*;
0031: import org.fao.geonet.kernel.schema.*;
0032: import org.jdom.*;
0033: import org.jdom.filter.*;
0034: import jeeves.utils.Xml;
0035:
0036: import java.io.File;
0037: import org.fao.geonet.constants.Edit;
0038:
0039: //=============================================================================
0040:
0041: public class EditLib {
0042: private DataManager dataMan;
0043: private Hashtable htVersions = new Hashtable(1000);
0044: private Hashtable htSchemas = new Hashtable();
0045: private Hashtable htSchemaDirs = new Hashtable();
0046: private Hashtable htSchemaSugg = new Hashtable();
0047:
0048: //--------------------------------------------------------------------------
0049: //---
0050: //--- Constructor
0051: //---
0052: //--------------------------------------------------------------------------
0053:
0054: /** Init structures
0055: */
0056:
0057: public EditLib(DataManager dataMan) {
0058: this .dataMan = dataMan;
0059:
0060: htVersions.clear();
0061: htSchemas.clear();
0062: }
0063:
0064: //--------------------------------------------------------------------------
0065: //---
0066: //--- API methods
0067: //---
0068: //--------------------------------------------------------------------------
0069:
0070: /** Loads the metadata schema from disk and adds it to the pool
0071: */
0072:
0073: public void addSchema(String name, String xmlSchemaFile,
0074: String xmlSuggestFile, String xmlSubstitutionsFile)
0075: throws Exception {
0076: String path = new File(xmlSchemaFile).getParent() + "/";
0077:
0078: MetadataSchema mds = new SchemaLoader().load(xmlSchemaFile,
0079: name, xmlSubstitutionsFile);
0080: mds.setName(name);
0081: htSchemas.put(name, mds);
0082: htSchemaDirs.put(name, path);
0083: htSchemaSugg.put(name, new SchemaSuggestions(xmlSuggestFile));
0084: }
0085:
0086: //--------------------------------------------------------------------------
0087:
0088: public MetadataSchema getSchema(String name) {
0089: MetadataSchema schema = (MetadataSchema) htSchemas.get(name);
0090:
0091: if (schema == null)
0092: throw new IllegalArgumentException(
0093: "Schema not registered : " + name);
0094:
0095: return schema;
0096: }
0097:
0098: //--------------------------------------------------------------------------
0099:
0100: public String getSchemaDir(String name) {
0101: String dir = (String) htSchemaDirs.get(name);
0102:
0103: if (dir == null)
0104: throw new IllegalArgumentException(
0105: "Schema not registered : " + name);
0106:
0107: return dir;
0108: }
0109:
0110: //--------------------------------------------------------------------------
0111:
0112: public Set<String> getSchemas() {
0113: return htSchemas.keySet();
0114: }
0115:
0116: //--------------------------------------------------------------------------
0117:
0118: public boolean existsSchema(String name) {
0119: return htSchemas.containsKey(name);
0120: }
0121:
0122: //--------------------------------------------------------------------------
0123: /** Expands a metadata adding all information needed for editing.
0124: */
0125:
0126: public String addEditingInfo(String schema, String id, Element md)
0127: throws Exception {
0128: String version = getVersion(id, true) + "";
0129:
0130: //System.out.println("MD before editing infomation:\n" + jeeves.utils.Xml.getString(md));
0131: enumerateTree(md, 1);
0132: expandTree(getSchema(schema), md);
0133: //System.out.println("MD after editing infomation:\n" + jeeves.utils.Xml.getString(md));
0134:
0135: return version;
0136: }
0137:
0138: //--------------------------------------------------------------------------
0139:
0140: public void enumerateTree(Element md) {
0141: enumerateTree(md, 1);
0142: }
0143:
0144: //--------------------------------------------------------------------------
0145:
0146: public String getVersion(String id) {
0147: return Integer.toString(getVersion(id, false));
0148: }
0149:
0150: //--------------------------------------------------------------------------
0151:
0152: public String getNewVersion(String id) {
0153: return Integer.toString(getVersion(id, true));
0154: }
0155:
0156: //--------------------------------------------------------------------------
0157: /** Given an element, creates all mandatory sub-elements. The given element
0158: * should be empty.
0159: */
0160:
0161: public void fillElement(String schema, Element parent, Element md)
0162: throws Exception {
0163: fillElement(getSchema(schema), getSchemaSuggestions(schema),
0164: parent, md);
0165: }
0166:
0167: //--------------------------------------------------------------------------
0168: /** Given an expanded tree, removes all info added for editing and replaces
0169: * choice_elements with their children
0170: */
0171:
0172: public void removeEditingInfo(Element md) {
0173: //--- purge children
0174:
0175: List list = md.getChildren();
0176:
0177: for (int i = 0; i < list.size(); i++) {
0178: Element child = (Element) list.get(i);
0179:
0180: if (!Edit.NS_PREFIX.equals(child.getNamespacePrefix()))
0181: removeEditingInfo(child);
0182: else {
0183: child.detach();
0184: i--;
0185: }
0186: }
0187: }
0188:
0189: //--------------------------------------------------------------------------
0190: /** Returns the element at a given reference.
0191: * @param md the metadata element expanded with editing info
0192: * @param ref the element position in a pre-order visit
0193: */
0194:
0195: public Element findElement(Element md, String ref) {
0196: Element elem = md.getChild(Edit.RootChild.ELEMENT,
0197: Edit.NAMESPACE);
0198:
0199: if (ref.equals(elem.getAttributeValue(Edit.Element.Attr.REF)))
0200: return md;
0201:
0202: //--- search on children
0203:
0204: List list = md.getChildren();
0205:
0206: for (int i = 0; i < list.size(); i++) {
0207: Element child = (Element) list.get(i);
0208:
0209: if (!Edit.NS_PREFIX.equals(child.getNamespacePrefix())) {
0210: child = findElement(child, ref);
0211:
0212: if (child != null)
0213: return child;
0214: }
0215: }
0216:
0217: return null;
0218: }
0219:
0220: //--------------------------------------------------------------------------
0221:
0222: public Element addElement(String schema, Element el, String qname)
0223: throws Exception {
0224: //System.out.println("#### in addElement()"); // DEBUG
0225:
0226: //System.out.println("#### - parent = " + el.getName()); // DEBUG
0227: //System.out.println("#### - child qname = " + qname); // DEBUG
0228:
0229: String name = getUnqualifiedName(qname);
0230: String ns = getNamespace(qname, el, getSchema(schema));
0231: String prefix = getPrefix(qname);
0232: String parentName = getParentNameFromChild(el);
0233:
0234: //System.out.println("#### - parent name for type retrieval = " + parentName); // DEBUG
0235: //System.out.println("#### - child name = " + name); // DEBUG
0236: //System.out.println("#### - child namespace = " + ns); // DEBUG
0237: //System.out.println("#### - child prefix = " + prefix); // DEBUG
0238: List childS = el.getChildren();
0239: if (childS.size() > 0) {
0240: Element elChildS = (Element) childS.get(0);
0241: //System.out.println("#### - parents first child = " + elChildS.getName()); // DEBUG
0242: }
0243:
0244: Element child = new Element(name, prefix, ns);
0245:
0246: MetadataSchema mdSchema = getSchema(schema);
0247: SchemaSuggestions mdSugg = getSchemaSuggestions(schema);
0248:
0249: String typeName = mdSchema.getElementType(
0250: el.getQualifiedName(), parentName);
0251:
0252: //System.out.println("#### - type name = " + typeName); // DEBUG
0253:
0254: MetadataType type = mdSchema.getTypeInfo(typeName);
0255:
0256: //System.out.println("#### - metadata tpe = " + type); // DEBUG
0257:
0258: //--- collect all children, adding the new one at the end of the others
0259:
0260: Vector children = new Vector();
0261:
0262: for (int i = 0; i < type.getElementCount(); i++) {
0263: List list = getChildren(el, type.getElementAt(i));
0264:
0265: String childName = type.getElementAt(i);
0266:
0267: //System.out.println("#### - child of type " + type.getElementAt(i) + " list size = " + list.size()); // DEBUG
0268: for (int j = 0; j < list.size(); j++) {
0269: Element aChild = (Element) list.get(j);
0270: children.add(aChild);
0271: //System.out.println("#### - add child "+aChild.toString());
0272: }
0273:
0274: if (qname.equals(type.getElementAt(i)))
0275: children.add(child);
0276: }
0277: //--- remove everything and then add all collected children to the element
0278: //--- to assure a correct position for the new one
0279:
0280: el.removeContent();
0281: for (int i = 0; i < children.size(); i++)
0282: el.addContent((Element) children.get(i));
0283:
0284: //--- add mandatory sub-tags
0285: fillElement(mdSchema, mdSugg, el, child);
0286:
0287: return child;
0288: }
0289:
0290: //--------------------------------------------------------------------------
0291: //---
0292: //--- Private methods
0293: //---
0294: //--------------------------------------------------------------------------
0295:
0296: private List getChildren(Element el, String qname) {
0297: Vector result = new Vector();
0298:
0299: List children = el.getChildren();
0300:
0301: for (int i = 0; i < children.size(); i++) {
0302: Element child = (Element) children.get(i);
0303:
0304: if (child.getQualifiedName().equals(qname))
0305: result.add(child);
0306: }
0307: return result;
0308: }
0309:
0310: //--------------------------------------------------------------------------
0311:
0312: /** Returns the version of a metadata, incrementing it if necessary
0313: */
0314:
0315: private synchronized int getVersion(String id, boolean increment) {
0316: Integer inVer = (Integer) htVersions.get(id);
0317:
0318: if (inVer == null)
0319: inVer = new Integer(1);
0320:
0321: if (increment)
0322: inVer = new Integer(inVer.intValue() + 1);
0323:
0324: htVersions.put(id, inVer);
0325:
0326: return inVer.intValue();
0327: }
0328:
0329: //--------------------------------------------------------------------------
0330:
0331: private void fillElement(MetadataSchema schema,
0332: SchemaSuggestions sugg, Element parent, Element md)
0333: throws Exception {
0334: //System.out.println("#### entering fillElement()"); // DEBUG
0335:
0336: String elemName = md.getQualifiedName();
0337: String parentName = parent.getQualifiedName();
0338:
0339: //System.out.println("#### - elemName = " + elemName); // DEBUG
0340: //System.out.println("#### - parentName = " + parentName); // DEBUG
0341: //System.out.println("#### - isSimpleElement(" + elemName + ") = " + schema.isSimpleElement(elemName,parentName)); // DEBUG
0342:
0343: if (schema.isSimpleElement(elemName, parentName))
0344: return;
0345:
0346: MetadataType type = schema.getTypeInfo(schema.getElementType(
0347: elemName, parentName));
0348:
0349: //System.out.println("#### - type:"); // DEBUG
0350: //System.out.println("#### - name = " + type.getName()); // DEBUG
0351: //System.out.println("#### - # attributes = " + type.getAttributeCount()); // DEBUG
0352: //System.out.println("#### - # elements = " + type.getElementCount()); // DEBUG
0353: //System.out.println("#### - # isOrType = " + type.isOrType()); // DEBUG
0354: //System.out.println("#### - type = " + type); // DEBUG
0355:
0356: //-----------------------------------------------------------------------
0357: //--- handle attributes
0358:
0359: for (int i = 0; i < type.getAttributeCount(); i++) {
0360: MetadataAttribute attr = type.getAttributeAt(i);
0361:
0362: //System.out.println("#### - " + i + " attribute = " + attr.name); // DEBUG
0363: //System.out.println("#### - required = " + attr.required); // DEBUG
0364: //System.out.println("#### - suggested = "+sugg.isSuggested(elemName, attr.name));
0365: if (attr.required || sugg.isSuggested(elemName, attr.name)) {
0366: String value = "";
0367:
0368: if (attr.defValue != null) {
0369: value = attr.defValue;
0370: //System.out.println("#### - value = " + attr.defValue); // DEBUG
0371: }
0372:
0373: String uname = getUnqualifiedName(attr.name);
0374: String ns = getNamespace(attr.name, md, schema);
0375: String prefix = getPrefix(attr.name);
0376: if (!prefix.equals(""))
0377: md.setAttribute(new Attribute(uname, value,
0378: Namespace.getNamespace(prefix, ns)));
0379: else
0380: md.setAttribute(new Attribute(uname, value));
0381: }
0382: }
0383:
0384: //-----------------------------------------------------------------------
0385: //--- add mandatory children
0386:
0387: if (!type.isOrType()) {
0388: for (int i = 0; i < type.getElementCount(); i++) {
0389: int minCard = type.getMinCardinAt(i);
0390: String childName = type.getElementAt(i);
0391:
0392: if (minCard > 0
0393: || sugg.isSuggested(elemName, childName)) {
0394: MetadataType elemType = schema.getTypeInfo(schema
0395: .getElementType(childName, elemName));
0396:
0397: //--- There can be 'or' elements with other 'or' elements inside them.
0398: //--- In this case we cannot expand the inner 'or' elements so the
0399: //--- only way to solve the problem is to avoid the creation of them
0400:
0401: if (schema.isSimpleElement(elemName, childName)
0402: || !elemType.isOrType()) {
0403: String name = getUnqualifiedName(childName);
0404: String ns = getNamespace(childName, md, schema);
0405: String prefix = getPrefix(childName);
0406:
0407: Element child = new Element(name, prefix, ns);
0408:
0409: md.addContent(child);
0410: fillElement(schema, sugg, md, child);
0411: } else {
0412: if (elemType.isOrType()) {
0413: //System.out.println("WARNING (INNER): requested expansion of an OR element : " +childName);
0414: }
0415: }
0416: }
0417: }
0418: } else
0419: System.out
0420: .println("WARNING : requested expansion of an OR element : "
0421: + md.getName());
0422: }
0423:
0424: //--------------------------------------------------------------------------
0425: //---
0426: //--- Tree expansion methods
0427: //---
0428: //--------------------------------------------------------------------------
0429:
0430: /** searches children of container elements for containers
0431: */
0432:
0433: public List searchChildren(String chName, Element md, String schema)
0434: throws Exception {
0435:
0436: // FIXME? CHOICE_ELEMENT containers can only have one element in them
0437: // if there are more then the container will need to be duplicated
0438: // and the elements distributed? Doesn't seem to hurt so we'll leave it
0439: // for now........
0440: //
0441:
0442: Vector containerSubElems = new Vector();
0443: boolean hasContent = false;
0444: Vector holder = new Vector();
0445:
0446: MetadataSchema mdSchema = getSchema(schema);
0447: String chUQname = getUnqualifiedName(chName);
0448: String chPrefix = getPrefix(chName);
0449: String chNS = getNamespace(chName, md, mdSchema);
0450: Element container = new Element(chUQname, chPrefix, chNS);
0451: MetadataType containerType = mdSchema.getTypeInfo(chName);
0452: for (int k = 0; k < containerType.getElementCount(); k++) {
0453: String elemName = containerType.getElementAt(k);
0454: //System.out.println(" -- Searching for child "+elemName);
0455: List elems;
0456: if (elemName.contains(Edit.RootChild.GROUP)
0457: || elemName.contains(Edit.RootChild.SEQUENCE)
0458: || elemName.contains(Edit.RootChild.CHOICE)) {
0459: elems = searchChildren(elemName, md, schema);
0460: } else {
0461: elems = getChildren(md, elemName);
0462: }
0463: for (int j = 0; j < elems.size(); j++) {
0464: Element elem = (Element) elems.get(j);
0465: container.addContent((Element) elem.clone());
0466: hasContent = true;
0467: }
0468: }
0469: if (hasContent) {
0470: holder.add(container);
0471: } else {
0472: if (!chName.contains(Edit.RootChild.CHOICE)) {
0473: fillElement(schema, md, container);
0474: holder.add(container);
0475: }
0476: }
0477: return holder;
0478: }
0479:
0480: /** Given an unexpanded tree, creates container elements and their children
0481: */
0482: public void expandElements(String schema, Element md)
0483: throws Exception {
0484:
0485: //--- create containers and fill them with elements using a depth first
0486: //--- search
0487:
0488: List childs = (List) md.getChildren();
0489: for (int i = 0; i < childs.size(); i++)
0490: expandElements(schema, (Element) childs.get(i));
0491:
0492: String name = md.getQualifiedName();
0493: String parentName = getParentNameFromChild(md);
0494: MetadataSchema mdSchema = getSchema(schema);
0495: String typeName = mdSchema.getElementType(name, parentName);
0496: MetadataType this Type = mdSchema.getTypeInfo(typeName);
0497:
0498: if (this Type.hasContainers) {
0499: Vector holder = new Vector();
0500:
0501: for (int i = 0; i < this Type.getElementCount(); i++) {
0502: String chName = this Type.getElementAt(i);
0503: if (chName.contains(Edit.RootChild.CHOICE)
0504: || chName.contains(Edit.RootChild.GROUP)
0505: || chName.contains(Edit.RootChild.SEQUENCE)) {
0506: List elems = searchChildren(chName, md, schema);
0507: if (elems.size() > 0) {
0508: holder.addAll(elems);
0509: }
0510: } else {
0511: List chElem = getChildren(md, chName);
0512: for (int z = 0; z < chElem.size(); z++) {
0513: Element elem = (Element) chElem.get(z);
0514: holder.add(elem.detach());
0515: }
0516: }
0517: }
0518: md.removeContent();
0519: md.addContent(holder);
0520: }
0521:
0522: }
0523:
0524: //--------------------------------------------------------------------------
0525: /** For each container element - descend and collect children
0526: */
0527:
0528: private Vector getContainerChildren(Element md) {
0529: Vector result = new Vector();
0530:
0531: List chChilds = md.getChildren();
0532: for (int k = 0; k < chChilds.size(); k++) {
0533: Element chChild = (Element) chChilds.get(k);
0534: String chName = chChild.getName();
0535: if (chName.contains(Edit.RootChild.CHOICE)
0536: || chName.contains(Edit.RootChild.GROUP)
0537: || chName.contains(Edit.RootChild.SEQUENCE)) {
0538: List moreChChilds = getContainerChildren(chChild);
0539: result.addAll(moreChChilds);
0540: } else
0541: result.add(chChild.clone());
0542: }
0543: return result;
0544: }
0545:
0546: //--------------------------------------------------------------------------
0547: /** Contract container elements
0548: */
0549: public void contractElements(Element md) {
0550: //--- contract container children at each level in the XML tree
0551:
0552: Vector children = new Vector();
0553: List childs = md.getContent();
0554: for (int i = 0; i < childs.size(); i++) {
0555: Object obj = childs.get(i);
0556: if (obj instanceof Element) {
0557: Element mdCh = (Element) obj;
0558: String mdName = mdCh.getName();
0559: if (mdName.contains(Edit.RootChild.CHOICE)
0560: || mdName.contains(Edit.RootChild.GROUP)
0561: || mdName.contains(Edit.RootChild.SEQUENCE)) {
0562: if (mdCh.getChildren().size() > 0) {
0563: Vector chChilds = getContainerChildren(mdCh);
0564: if (chChilds.size() > 0)
0565: children.addAll(chChilds);
0566: }
0567: } else {
0568: children.add(mdCh.clone());
0569: }
0570: } else {
0571: children.add(obj);
0572: }
0573: }
0574: md.removeContent();
0575: md.addContent(children);
0576:
0577: //--- now move down to the next level
0578:
0579: for (int i = 0; i < children.size(); i++) {
0580: Object obj = children.get(i);
0581: if (obj instanceof Element)
0582: contractElements((Element) obj);
0583: }
0584: }
0585:
0586: //--------------------------------------------------------------------------
0587: /** Does a pre-order visit enumerating each node
0588: */
0589:
0590: private int enumerateTree(Element md, int ref) {
0591: Element elem = new Element(Edit.RootChild.ELEMENT,
0592: Edit.NAMESPACE);
0593: elem
0594: .setAttribute(new Attribute(Edit.Element.Attr.REF, ref
0595: + ""));
0596:
0597: List list = md.getChildren();
0598:
0599: for (int i = 0; i < list.size(); i++)
0600: ref = enumerateTree((Element) list.get(i), ref + 1);
0601:
0602: md.addContent(elem);
0603:
0604: return ref;
0605: }
0606:
0607: //--------------------------------------------------------------------------
0608: /** Given a metadata, does a recursive scan adding information for editing
0609: */
0610:
0611: public void expandTree(MetadataSchema schema, Element md)
0612: throws Exception {
0613: expandElement(schema, md);
0614:
0615: List list = md.getChildren();
0616:
0617: for (int i = 0; i < list.size(); i++) {
0618: Element child = (Element) list.get(i);
0619:
0620: if (!Edit.NS_PREFIX.equals(child.getNamespacePrefix()))
0621: expandTree(schema, child);
0622: }
0623: }
0624:
0625: //--------------------------------------------------------------------------
0626:
0627: private String getParentNameFromChild(Element child) {
0628: String childName = child.getQualifiedName();
0629: String parentName = "root";
0630: Element parent = child.getParentElement();
0631: if (parent != null) {
0632: parentName = parent.getQualifiedName();
0633: }
0634: return parentName;
0635: }
0636:
0637: //--------------------------------------------------------------------------
0638: /** Adds editing information to a single element
0639: */
0640:
0641: private void expandElement(MetadataSchema schema, Element md)
0642: throws Exception {
0643: //System.out.println("entering expandElement()"); // DEBUG
0644:
0645: String elemName = md.getQualifiedName();
0646: String parentName = getParentNameFromChild(md);
0647:
0648: //System.out.println("elemName = " + elemName); // DEBUG
0649: //System.out.println("parentName = " + parentName); // DEBUG
0650:
0651: String elemType = schema.getElementType(elemName, parentName);
0652: //System.out.println("elemType = " + elemType); // DEBUG
0653:
0654: Element elem = md.getChild(Edit.RootChild.ELEMENT,
0655: Edit.NAMESPACE);
0656: addValues(schema, elem, elemName, parentName);
0657:
0658: if (schema.isSimpleElement(elemName, parentName)) {
0659: //System.out.println("is simple element"); // DEBUG
0660: return;
0661: }
0662: MetadataType type = schema.getTypeInfo(elemType);
0663: //System.out.println("Type = "+type);
0664:
0665: for (int i = 0; i < type.getElementCount(); i++) {
0666: String childQName = type.getElementAt(i);
0667:
0668: //System.out.println("- childName = " + childQName); // DEBUG
0669: if (childQName == null)
0670: continue; // schema extensions cause null types; just skip
0671:
0672: String childName = getUnqualifiedName(childQName);
0673: String childPrefix = getPrefix(childQName);
0674: String childNS = getNamespace(childQName, md, schema);
0675:
0676: // System.out.println("- name = " + childName); // DEBUG
0677: // System.out.println("- prefix = " + childPrefix); // DEBUG
0678: // System.out.println("- namespace = " + childNS); // DEBUG
0679:
0680: List list = md.getChildren(childName, Namespace
0681: .getNamespace(childNS));
0682: if (list.size() == 0 && !(type.isOrType())) {
0683: // System.out.println("- no children of this type already present"); // DEBUG
0684:
0685: Element newElem = createElement(schema, elemName,
0686: childQName, childPrefix, childNS);
0687:
0688: if (i == 0)
0689: insertFirst(md, newElem);
0690: else {
0691: String prevQName = type.getElementAt(i - 1);
0692: String prevName = getUnqualifiedName(prevQName);
0693: String prevNS = getNamespace(prevQName, md, schema);
0694: insertLast(md, prevName, prevNS, newElem);
0695: }
0696: } else {
0697: //System.out.println("- " + list.size() + " children of this type already present"); // DEBUG
0698: //System.out.println("- min cardinality = " + type.getMinCardinAt(i)); // DEBUG
0699: //System.out.println("- max cardinality = " + type.getMaxCardinAt(i)); // DEBUG
0700:
0701: for (int j = 0; j < list.size(); j++) {
0702: Element listChild = (Element) list.get(j);
0703: Element listElem = listChild.getChild(
0704: Edit.RootChild.ELEMENT, Edit.NAMESPACE);
0705:
0706: if (j > 0)
0707: listElem.setAttribute(new Attribute(
0708: Edit.Element.Attr.UP, Edit.Value.TRUE));
0709:
0710: if (j < list.size() - 1)
0711: listElem
0712: .setAttribute(new Attribute(
0713: Edit.Element.Attr.DOWN,
0714: Edit.Value.TRUE));
0715:
0716: if (list.size() > type.getMinCardinAt(i))
0717: listElem
0718: .setAttribute(new Attribute(
0719: Edit.Element.Attr.DEL,
0720: Edit.Value.TRUE));
0721: }
0722: if (list.size() < type.getMaxCardinAt(i))
0723: insertLast(md, childName, childNS, createElement(
0724: schema, elemName, childQName, childPrefix,
0725: childNS));
0726: }
0727: }
0728: addAttribs(type, md, schema);
0729: }
0730:
0731: //--------------------------------------------------------------------------
0732:
0733: public String getUnqualifiedName(String qname) {
0734: int pos = qname.indexOf(":");
0735: if (pos < 0)
0736: return qname;
0737: else
0738: return qname.substring(pos + 1);
0739: }
0740:
0741: //--------------------------------------------------------------------------
0742:
0743: public String getPrefix(String qname) {
0744: int pos = qname.indexOf(":");
0745: if (pos < 0)
0746: return "";
0747: else
0748: return qname.substring(0, pos);
0749: }
0750:
0751: //--------------------------------------------------------------------------
0752:
0753: public String getNamespace(String qname, Element md,
0754: MetadataSchema schema) {
0755: // check the element first to see whether the namespace is
0756: // declared locally
0757: String result = checkNamespaces(qname, md);
0758: if (result.equals("UNKNOWN")) {
0759:
0760: // find root element, where namespaces *must* be declared
0761: Element root = md;
0762: while (root.getParent() != null
0763: && root.getParent() instanceof Element)
0764: root = (Element) root.getParent();
0765: result = checkNamespaces(qname, root);
0766:
0767: // finally if it isn't on the root element then check the list
0768: // namespaces we collected as we parsed the schema
0769: if (result.equals("UNKNOWN")) {
0770: String prefix = getPrefix(qname);
0771: if (!prefix.equals("")) {
0772: result = schema.getNS(prefix);
0773: if (result == null)
0774: result = "UNKNOWN";
0775: } else
0776: result = "UNKNOWN";
0777: }
0778: }
0779: return result;
0780: }
0781:
0782: //--------------------------------------------------------------------------
0783:
0784: public String checkNamespaces(String qname, Element md) {
0785: // get prefix
0786: String prefix = getPrefix(qname);
0787:
0788: // loop on namespaces to fine the one corresponding to prefix
0789: Namespace rns = md.getNamespace();
0790: if (prefix.equals(rns.getPrefix()))
0791: return rns.getURI();
0792: for (Iterator i = md.getAdditionalNamespaces().iterator(); i
0793: .hasNext();) {
0794: Namespace ns = (Namespace) i.next();
0795: if (prefix.equals(ns.getPrefix()))
0796: return ns.getURI();
0797: }
0798: return "UNKNOWN";
0799: }
0800:
0801: //--------------------------------------------------------------------------
0802:
0803: private void insertFirst(Element md, Element child) {
0804: Vector v = new Vector();
0805: v.add(child);
0806:
0807: List list = md.getChildren();
0808:
0809: for (int i = 0; i < list.size(); i++)
0810: v.add((Element) list.get(i));
0811:
0812: //---
0813:
0814: md.removeContent();
0815:
0816: for (int i = 0; i < v.size(); i++)
0817: md.addContent((Element) v.get(i));
0818: }
0819:
0820: //--------------------------------------------------------------------------
0821:
0822: private void insertLast(Element md, String childName,
0823: String childNS, Element child) {
0824: boolean added = false;
0825:
0826: List list = md.getChildren();
0827:
0828: Vector v = new Vector();
0829:
0830: for (int i = 0; i < list.size(); i++) {
0831: Element el = (Element) list.get(i);
0832:
0833: v.add(el);
0834:
0835: if (equal(childName, childNS, el) && !added) {
0836: if (i == list.size() - 1) {
0837: v.add(child);
0838: added = true;
0839: } else {
0840: Element elNext = (Element) list.get(i + 1);
0841:
0842: if (!equal(el, elNext)) {
0843: v.add(child);
0844: added = true;
0845: }
0846: }
0847: }
0848: }
0849:
0850: md.removeContent();
0851:
0852: for (int i = 0; i < v.size(); i++)
0853: md.addContent((Element) v.get(i));
0854: }
0855:
0856: //--------------------------------------------------------------------------
0857:
0858: private boolean equal(String childName, String childNS, Element el) {
0859: if (Edit.NS_URI.equals(el.getNamespaceURI())) {
0860: if (Edit.RootChild.CHILD.equals(el.getName()))
0861: return childName.equals(el
0862: .getAttributeValue(Edit.ChildElem.Attr.NAME))
0863: && childNS
0864: .equals(el
0865: .getAttributeValue(Edit.ChildElem.Attr.NAMESPACE));
0866: else
0867: return false;
0868: } else
0869: return childName.equals(el.getName())
0870: && childNS.equals(el.getNamespaceURI());
0871: }
0872:
0873: //--------------------------------------------------------------------------
0874:
0875: private boolean equal(Element el1, Element el2) {
0876: String elemNS1 = el1.getNamespaceURI();
0877: String elemNS2 = el2.getNamespaceURI();
0878:
0879: if (Edit.NS_URI.equals(elemNS1)) {
0880: if (Edit.NS_URI.equals(elemNS2)) {
0881: //--- both are geonet:child elements
0882:
0883: if (!Edit.RootChild.CHILD.equals(el1.getName()))
0884: return false;
0885:
0886: if (!Edit.RootChild.CHILD.equals(el2.getName()))
0887: return false;
0888:
0889: String name1 = el1
0890: .getAttributeValue(Edit.ChildElem.Attr.NAME);
0891: String name2 = el2
0892: .getAttributeValue(Edit.ChildElem.Attr.NAME);
0893:
0894: String ns1 = el1
0895: .getAttributeValue(Edit.ChildElem.Attr.NAMESPACE);
0896: String ns2 = el2
0897: .getAttributeValue(Edit.ChildElem.Attr.NAMESPACE);
0898:
0899: return name1.equals(name2) && ns1.equals(ns2);
0900: } else {
0901: //--- el1 is a geonet:child, el2 is not
0902:
0903: if (!Edit.RootChild.CHILD.equals(el1.getName()))
0904: return false;
0905:
0906: String name1 = el1
0907: .getAttributeValue(Edit.ChildElem.Attr.NAME);
0908: String ns1 = el1
0909: .getAttributeValue(Edit.ChildElem.Attr.NAMESPACE);
0910:
0911: return el2.getName().equals(name1)
0912: && el2.getNamespaceURI().equals(ns1);
0913: }
0914: } else {
0915: if (Edit.NS_URI.equals(elemNS2)) {
0916: //--- el2 is a geonet:child, el1 is not
0917:
0918: if (!Edit.RootChild.CHILD.equals(el2.getName()))
0919: return false;
0920:
0921: String name2 = el2
0922: .getAttributeValue(Edit.ChildElem.Attr.NAME);
0923: String ns2 = el2
0924: .getAttributeValue(Edit.ChildElem.Attr.NAMESPACE);
0925:
0926: return el1.getName().equals(name2)
0927: && el1.getNamespaceURI().equals(ns2);
0928: } else {
0929: //--- both not geonet:child elements
0930:
0931: return el1.getName().equals(el2.getName())
0932: && el1.getNamespaceURI().equals(
0933: el2.getNamespaceURI());
0934: }
0935: }
0936: }
0937:
0938: //--------------------------------------------------------------------------
0939: /** Create a new element for editing, adding all mandatory subtags
0940: */
0941:
0942: private Element createElement(MetadataSchema schema, String parent,
0943: String qname, String childPrefix, String childNS)
0944: throws Exception {
0945:
0946: Element child = new Element(Edit.RootChild.CHILD,
0947: Edit.NAMESPACE);
0948:
0949: child.setAttribute(new Attribute(Edit.ChildElem.Attr.NAME,
0950: getUnqualifiedName(qname)));
0951: child.setAttribute(new Attribute(Edit.ChildElem.Attr.PREFIX,
0952: getPrefix(qname)));
0953: child.setAttribute(new Attribute(Edit.ChildElem.Attr.NAMESPACE,
0954: childNS));
0955:
0956: if (!schema.isSimpleElement(qname, parent)) {
0957: String elemType = schema.getElementType(qname, parent);
0958:
0959: MetadataType type = schema.getTypeInfo(elemType);
0960:
0961: if (type.isOrType())
0962: for (int l = 0; l < type.getElementCount(); l++) {
0963: String chElem = type.getElementAt(l);
0964: if (chElem.contains(Edit.RootChild.CHOICE)) {
0965: ArrayList chElems = recurseOnNestedChoices(
0966: schema, chElem, parent);
0967: for (int k = 0; k < chElems.size(); k++) {
0968: chElem = (String) chElems.get(k);
0969: createAndAddChoose(child, chElem);
0970: }
0971: } else {
0972: createAndAddChoose(child, chElem);
0973: }
0974: }
0975: }
0976:
0977: return child;
0978: }
0979:
0980: private ArrayList recurseOnNestedChoices(MetadataSchema schema,
0981: String chElem, String parent) throws Exception {
0982: ArrayList chElems = new ArrayList();
0983: String elemType = schema.getElementType(chElem, parent);
0984: MetadataType type = schema.getTypeInfo(elemType);
0985: for (int l = 0; l < type.getElementCount(); l++) {
0986: String subChElem = type.getElementAt(l);
0987: if (subChElem.contains(Edit.RootChild.CHOICE)) {
0988: ArrayList subChElems = recurseOnNestedChoices(schema,
0989: subChElem, chElem);
0990: chElems.addAll(subChElems);
0991: } else {
0992: chElems.add(subChElem);
0993: }
0994: }
0995: return chElems;
0996: }
0997:
0998: private void createAndAddChoose(Element child, String chType) {
0999: Element choose = new Element(Edit.ChildElem.Child.CHOOSE,
1000: Edit.NAMESPACE);
1001: choose
1002: .setAttribute(new Attribute(Edit.Choose.Attr.NAME,
1003: chType));
1004: child.addContent(choose);
1005: }
1006:
1007: //--------------------------------------------------------------------------
1008:
1009: private void addValues(MetadataSchema schema, Element elem,
1010: String name, String parent) throws Exception {
1011: List values = schema.getElementValues(name, parent);
1012: if (values != null)
1013: for (int i = 0; i < values.size(); i++) {
1014: Element text = new Element(Edit.Element.Child.TEXT,
1015: Edit.NAMESPACE);
1016: text.setAttribute(Edit.Attribute.Attr.VALUE,
1017: (String) values.get(i));
1018:
1019: elem.addContent(text);
1020: }
1021: }
1022:
1023: //--------------------------------------------------------------------------
1024:
1025: private void addAttribs(MetadataType type, Element md,
1026: MetadataSchema schema) {
1027: for (int i = 0; i < type.getAttributeCount(); i++) {
1028: MetadataAttribute attr = type.getAttributeAt(i);
1029:
1030: Element attribute = new Element(Edit.RootChild.ATTRIBUTE,
1031: Edit.NAMESPACE);
1032:
1033: attribute.setAttribute(new Attribute(
1034: Edit.Attribute.Attr.NAME, attr.name));
1035: //--- add default value (if any)
1036:
1037: if (attr.defValue != null) {
1038: Element def = new Element(Edit.Attribute.Child.DEFAULT,
1039: Edit.NAMESPACE);
1040: def.setAttribute(Edit.Attribute.Attr.VALUE,
1041: attr.defValue);
1042:
1043: attribute.addContent(def);
1044: }
1045:
1046: for (int j = 0; j < attr.values.size(); j++) {
1047: Element text = new Element(Edit.Attribute.Child.TEXT,
1048: Edit.NAMESPACE);
1049: text.setAttribute(Edit.Attribute.Attr.VALUE,
1050: (String) attr.values.get(j));
1051:
1052: attribute.addContent(text);
1053: }
1054:
1055: //--- handle 'add' and 'del' attribs
1056:
1057: boolean present;
1058: String uname = getUnqualifiedName(attr.name);
1059: String ns = getNamespace(attr.name, md, schema);
1060: String prefix = getPrefix(attr.name);
1061: if (!prefix.equals("")) {
1062: present = (md.getAttributeValue(uname, Namespace
1063: .getNamespace(prefix, ns)) != null);
1064: if (!present && attr.required
1065: && (attr.defValue != null)) { // Add it
1066: md.setAttribute(new Attribute(uname, attr.defValue,
1067: Namespace.getNamespace(prefix, ns)));
1068: }
1069: } else {
1070: present = (md.getAttributeValue(attr.name) != null);
1071: if (!present && attr.required
1072: && (attr.defValue != null)) { // Add it
1073: md.setAttribute(new Attribute(attr.name,
1074: attr.defValue));
1075: }
1076: }
1077:
1078: if (!present)
1079: attribute.setAttribute(new Attribute(
1080: Edit.Attribute.Attr.ADD, Edit.Value.TRUE));
1081:
1082: else if (!attr.required)
1083: attribute.setAttribute(new Attribute(
1084: Edit.Attribute.Attr.DEL, Edit.Value.TRUE));
1085:
1086: md.addContent(attribute);
1087: }
1088: }
1089:
1090: //--------------------------------------------------------------------------
1091:
1092: private SchemaSuggestions getSchemaSuggestions(String name) {
1093: SchemaSuggestions sugg = (SchemaSuggestions) htSchemaSugg
1094: .get(name);
1095:
1096: if (sugg == null)
1097: throw new IllegalArgumentException(
1098: "Schema suggestions not registered : " + name);
1099:
1100: return sugg;
1101: }
1102:
1103: }
1104:
1105: //=============================================================================
|