0001: /*
0002: * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
0003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
0004: */
0005: package com.sun.portal.desktop.dp.xml;
0006:
0007: import org.w3c.dom.Element;
0008: import org.w3c.dom.Document;
0009: import org.w3c.dom.Text;
0010: import org.w3c.dom.Comment;
0011: import org.w3c.dom.Node;
0012: import org.w3c.dom.NodeList;
0013: import org.w3c.dom.NamedNodeMap;
0014: import org.w3c.dom.Attr;
0015:
0016: import org.xml.sax.InputSource;
0017: import org.xml.sax.SAXException;
0018: import org.xml.sax.SAXParseException;
0019:
0020: import javax.xml.parsers.DocumentBuilder;
0021: import javax.xml.parsers.DocumentBuilderFactory;
0022: import javax.xml.parsers.ParserConfigurationException;
0023:
0024: import java.io.ByteArrayInputStream;
0025: import java.io.IOException;
0026:
0027: import java.util.List;
0028: import java.util.ArrayList;
0029: import java.util.Map;
0030: import java.util.HashMap;
0031: import java.util.Collections;
0032: import java.util.StringTokenizer;
0033:
0034: import com.sun.portal.desktop.context.DPContext;
0035: import com.sun.portal.desktop.util.OrderedMap;
0036: import com.sun.portal.desktop.encode.Encoder;
0037:
0038: import com.sun.portal.desktop.dp.DPError;
0039: import com.sun.portal.desktop.dp.DPObject;
0040: import com.sun.portal.desktop.dp.DPTypes;
0041: import com.sun.portal.desktop.dp.DPRoot;
0042:
0043: public abstract class XMLDPObject implements DPObject, DPTypes,
0044: XMLDPTags, XMLDPAttrs, Comparable {
0045:
0046: static final int INDENT_SPACES = 4;
0047: static Map mergeTypeTable = null;
0048: static String[] MERGETYPE_VALUES = null;
0049: static {
0050: mergeTypeTable = new HashMap();
0051:
0052: mergeTypeTable.put("fuse", new Short(MERGE_FUSE));
0053: mergeTypeTable.put("replace", new Short(MERGE_REPLACE));
0054: mergeTypeTable.put("remove", new Short(MERGE_REMOVE));
0055:
0056: MERGETYPE_VALUES = new String[max(MERGE_FUSE, MERGE_REPLACE,
0057: MERGE_REMOVE) + 1];
0058: MERGETYPE_VALUES[MERGE_FUSE] = "fuse";
0059: MERGETYPE_VALUES[MERGE_REPLACE] = "replace";
0060: MERGETYPE_VALUES[MERGE_REMOVE] = "remove";
0061: }
0062:
0063: private DPContext dpContext = null;
0064: private DPRoot dpRoot = null;
0065:
0066: private Element element = null;
0067: private DocumentBuilder docBuilder = null;
0068:
0069: private List mergers = null;
0070: private List unmodifiableMergers = Collections.EMPTY_LIST;
0071:
0072: private boolean mergeLocked = false;
0073: private boolean mergeRemoved = false;
0074: private boolean mergeAdvanced = false;
0075:
0076: static long ccount = 0;
0077:
0078: private static Map localeNames = null;
0079:
0080: private static XMLDPEntityResolver entityResolver = null;
0081: private static XMLDPErrorHandler errorHandler = null;
0082:
0083: //
0084: // these values cache the results of:
0085: // isLocked()
0086: // isRemoved();
0087: // isReplace();
0088: // isAdvanced();
0089: //
0090: private Boolean locked = null;
0091: private Boolean removed = null;
0092: private Boolean replaced = null;
0093: private Boolean dummy = null;
0094: private Short mergeType = null;
0095: private Boolean advanced = null;
0096:
0097: private String name = null;
0098:
0099: private XMLDPObject() {
0100: // nothing
0101: }
0102:
0103: static Map createElementTable(Element e) {
0104: Map elementTable = new OrderedMap();
0105:
0106: NodeList childNodes = e.getChildNodes();
0107: int numChildren = childNodes.getLength();
0108:
0109: for (int i = 0; i < numChildren; i++) {
0110: Node childNode = childNodes.item(i);
0111: if (childNode.getNodeType() != Node.ELEMENT_NODE) {
0112: continue;
0113: }
0114: Element childElement = (Element) childNode;
0115: String name = getNameElement(childElement);
0116: elementTable.put(name, childElement);
0117: }
0118:
0119: return elementTable;
0120: }
0121:
0122: XMLDPObject(DPContext dpc, DPRoot r, Element e) {
0123: dpContext = dpc;
0124: dpRoot = r;
0125: element = e;
0126:
0127: checkType();
0128: }
0129:
0130: public DocumentBuilder getDocBuilder() {
0131: if (docBuilder == null) {
0132: synchronized (this ) {
0133: if (docBuilder == null) {
0134: docBuilder = getDocBuilder(getContext());
0135: }
0136: }
0137: }
0138:
0139: return docBuilder;
0140: }
0141:
0142: public DPObject getObject(Element e) {
0143: return ((XMLDPRoot) getRoot()).getObject(e);
0144: }
0145:
0146: public void putObject(DPObject dpo) {
0147: ((XMLDPRoot) getRoot()).putObject(dpo);
0148: }
0149:
0150: public void removeObject(DPObject dpo) {
0151: ((XMLDPRoot) getRoot()).removeObject(dpo);
0152: }
0153:
0154: public void removeObject(Element e) {
0155: ((XMLDPRoot) getRoot()).removeObject(e);
0156: }
0157:
0158: public DPRoot getRoot() {
0159: return dpRoot;
0160: }
0161:
0162: Element getRootElement() {
0163: return getRootElement(getElement());
0164: }
0165:
0166: static Element getRootElement(Element e) {
0167: Element rootElement = e.getOwnerDocument().getDocumentElement();
0168: return rootElement;
0169: }
0170:
0171: public boolean isRemove() {
0172: if (removed == null) {
0173: if (isDummy()) {
0174: if (isMergeRemove()) {
0175: removed = Boolean.TRUE;
0176: } else {
0177: removed = Boolean.FALSE;
0178: }
0179: } else {
0180: if (isThisRemove(getElement())) {
0181: removed = Boolean.TRUE;
0182: } else {
0183: removed = Boolean.FALSE;
0184: }
0185: }
0186: }
0187:
0188: return removed.booleanValue();
0189: }
0190:
0191: public boolean isThisRemove(Element e) {
0192: if (!isDummyElement(e) && isRemoveElement(e)) {
0193: return true;
0194: }
0195: Node parentNode = e.getParentNode();
0196:
0197: if (parentNode == null
0198: || parentNode.getNodeType() == Node.DOCUMENT_NODE) {
0199: return false;
0200: }
0201:
0202: if (parentNode.getNodeType() != Node.ELEMENT_NODE) {
0203: throw new DPError(
0204: "XMLDPProperty.isThisRemove(): parent node was not an element");
0205: }
0206: Element parentElement = (Element) parentNode;
0207:
0208: return isThisRemove(parentElement);
0209: }
0210:
0211: public static boolean isRemoveElement(Element e) {
0212: if (e.hasAttribute(MERGE_KEY)
0213: && (e.getAttribute(MERGE_KEY).equals(REMOVE_ATTR))) {
0214: return true;
0215: }
0216:
0217: return false;
0218: }
0219:
0220: public boolean isReplace() {
0221: if (replaced == null) {
0222: if (isThisReplace(getElement())) {
0223: replaced = Boolean.TRUE;
0224: } else {
0225: replaced = Boolean.FALSE;
0226: }
0227: }
0228:
0229: return replaced.booleanValue();
0230: }
0231:
0232: public boolean isThisReplace(Element e) {
0233: if (!isDummyElement(e) && isReplaceElement(e)) {
0234: return true;
0235: }
0236: Node parentNode = e.getParentNode();
0237:
0238: if (parentNode == null
0239: || parentNode.getNodeType() == Node.DOCUMENT_NODE) {
0240: return false;
0241: }
0242:
0243: if (parentNode.getNodeType() != Node.ELEMENT_NODE) {
0244: throw new DPError(
0245: "XMLDPProperty.isThisReplace(): parent node was not an element");
0246: }
0247: Element parentElement = (Element) parentNode;
0248:
0249: return isThisReplace(parentElement);
0250: }
0251:
0252: public static boolean isReplaceElement(Element e) {
0253: if (e.hasAttribute(MERGE_KEY)
0254: && (e.getAttribute(MERGE_KEY).equals(REPLACE_ATTR))) {
0255: return true;
0256: }
0257:
0258: return false;
0259: }
0260:
0261: public boolean isMergeReplace() {
0262: DPObject dpo = getLastMerger();
0263: if (dpo == null) {
0264: return false;
0265: }
0266: if (dpo.getMergeType() == MERGE_REPLACE) {
0267: return true;
0268: }
0269:
0270: return false;
0271: }
0272:
0273: public boolean isMergeRemove() {
0274: return mergeRemoved;
0275: }
0276:
0277: public boolean isMergeLocked() {
0278: return mergeLocked;
0279: }
0280:
0281: public boolean isMergeAdvanced() {
0282: return mergeAdvanced;
0283: }
0284:
0285: public DPObject getLastMerger() {
0286: if (mergers == null) {
0287: return null;
0288: }
0289:
0290: int size = mergers.size();
0291: if (size == 0) {
0292: return null;
0293: }
0294:
0295: return (DPObject) mergers.get(size - 1);
0296: }
0297:
0298: public List getMergers() {
0299: return unmodifiableMergers;
0300: }
0301:
0302: private List getModifiableMergers() {
0303: if (mergers == null) {
0304: mergers = new ArrayList();
0305: unmodifiableMergers = Collections.unmodifiableList(mergers);
0306: }
0307:
0308: return mergers;
0309: }
0310:
0311: public void addMergers(List m) {
0312: Collections.sort(m);
0313: for (int i = 0; i < m.size(); i++) {
0314: addMerger((DPObject) m.get(i));
0315: }
0316: }
0317:
0318: public void addMerger(DPObject dpo) {
0319: if (getType() != dpo.getType()) {
0320: throw new DPError(
0321: "XMLDPObject.addMerger(): merger type mismatch");
0322: }
0323:
0324: List m = getModifiableMergers();
0325:
0326: //
0327: // this check could perhaps be removed to improve perf.
0328: // this should never happen
0329: // but it helps in debugging if it does.
0330: //
0331: if (m.contains(dpo)) {
0332: throw new DPError(
0333: "XMLDPObject.addMerger(): merger already added");
0334: }
0335:
0336: m.add(dpo);
0337:
0338: if (dpo.isRemove()) {
0339: mergeRemoved = true;
0340: } else {
0341: mergeRemoved = false;
0342: }
0343: if (dpo.isLocked()) {
0344: mergeLocked = true;
0345: }
0346: if (dpo.isAdvanced()) {
0347: mergeAdvanced = true;
0348: }
0349: }
0350:
0351: public static boolean isLockedElement(Element e) {
0352: String l = e.getAttribute(LOCK_KEY);
0353: if ((l == null) || (l.length() == 0)) {
0354: return staticGetDefaultLockValue();
0355: }
0356:
0357: boolean lock = toBoolean(l);
0358:
0359: return lock;
0360: }
0361:
0362: public boolean isThisLocked(Element e) {
0363: if (!isDummyElement(e) && isLockedElement(e)) {
0364: return true;
0365: }
0366: Node parentNode = e.getParentNode();
0367:
0368: if (parentNode == null
0369: || parentNode.getNodeType() == Node.DOCUMENT_NODE) {
0370: return false;
0371: }
0372:
0373: if (parentNode.getNodeType() != Node.ELEMENT_NODE) {
0374: throw new DPError(
0375: "XMLDPProperty.isThisLocked(): parent node was not an element");
0376: }
0377: Element parentElement = (Element) parentNode;
0378:
0379: return isThisLocked(parentElement);
0380: }
0381:
0382: public boolean isLocked() {
0383: if (locked == null) {
0384: if (isDummy()) {
0385: if (isMergeLocked()) {
0386: locked = Boolean.TRUE;
0387: } else {
0388: locked = Boolean.FALSE;
0389: }
0390: } else {
0391: if (isThisLocked(getElement())) {
0392: locked = Boolean.TRUE;
0393: } else {
0394: locked = Boolean.FALSE;
0395: }
0396: }
0397: }
0398:
0399: return locked.booleanValue();
0400: }
0401:
0402: public void setLock(boolean lock) {
0403: if (lock) {
0404: getElement().setAttribute(LOCK_KEY, TRUE_ATTR);
0405: locked = Boolean.TRUE;
0406: } else {
0407: getElement().setAttribute(LOCK_KEY, FALSE_ATTR);
0408: locked = Boolean.FALSE;
0409: }
0410: }
0411:
0412: public int getPriority() {
0413: return getRoot().getPriority();
0414: }
0415:
0416: public void setPriority(int priority) {
0417: getRoot().setPriority(priority);
0418: }
0419:
0420: public String getVersion() {
0421: return getRoot().getVersion();
0422: }
0423:
0424: public void setVersion(String version) {
0425: getRoot().setVersion(version);
0426: }
0427:
0428: public void setMergeType(short type) {
0429: removed = null;
0430: replaced = null;
0431: advanced = null;
0432: mergeType = new Short(type);
0433:
0434: setMergeTypeElement(getElement(), type);
0435: setDummy(false);
0436: }
0437:
0438: static void setMergeTypeElement(Element e, int type) {
0439: switch (type) {
0440: case MERGE_FUSE:
0441: e.setAttribute(MERGE_KEY, FUSE_ATTR);
0442: break;
0443:
0444: case MERGE_REPLACE:
0445: e.setAttribute(MERGE_KEY, REPLACE_ATTR);
0446: break;
0447:
0448: case MERGE_REMOVE:
0449: e.setAttribute(MERGE_KEY, REMOVE_ATTR);
0450: break;
0451:
0452: default:
0453: throw new DPError(
0454: "XMLDPObject.setMergeType(): unknown type=" + type);
0455: }
0456:
0457: }
0458:
0459: public short getMergeType() {
0460: if (mergeType == null) {
0461: mergeType = new Short(getMergeTypeElement(getElement(),
0462: getDefaultMergeType()));
0463: }
0464:
0465: return (short) mergeType.shortValue();
0466: }
0467:
0468: public short getThisMergeType() {
0469: return getMergeTypeElement(getElement(), getDefaultMergeType());
0470: }
0471:
0472: private static short getMergeTypeElement(Element e, int defaultType) {
0473: String t = e.getAttribute(MERGE_KEY);
0474: if ((t == null) || (t.length() == 0)) {
0475: return (short) defaultType;
0476: }
0477:
0478: Short type = (Short) mergeTypeTable.get(t);
0479: if (type == null) {
0480: throw new DPError(
0481: "XMLDPObject.getMergeType(): unknown merge type="
0482: + t + " for element=" + e.toString());
0483: }
0484:
0485: return type.shortValue();
0486: }
0487:
0488: public boolean isAdvanced() {
0489: if (advanced == null) {
0490: if (isDummy()) {
0491: if (isMergeAdvanced()) {
0492: advanced = Boolean.TRUE;
0493: } else {
0494: advanced = Boolean.FALSE;
0495: }
0496: } else {
0497: if (isThisAdvanced(getElement())) {
0498: advanced = Boolean.TRUE;
0499: } else {
0500: advanced = Boolean.FALSE;
0501: }
0502: }
0503: }
0504:
0505: return advanced.booleanValue();
0506: }
0507:
0508: public void setAdvanced(boolean adv) {
0509: if (adv) {
0510: getElement().setAttribute(ADVANCED_KEY, TRUE_ATTR);
0511: advanced = Boolean.TRUE;
0512: } else {
0513: getElement().setAttribute(ADVANCED_KEY, FALSE_ATTR);
0514: advanced = Boolean.FALSE;
0515: }
0516: }
0517:
0518: public static boolean isAdvancedElement(Element e) {
0519: String a = e.getAttribute(ADVANCED_KEY);
0520: if ((a == null) || (a.length() == 0)) {
0521: return staticGetDefaultAdvancedValue();
0522: }
0523:
0524: return toBoolean(a);
0525: }
0526:
0527: public boolean isThisAdvanced(Element e) {
0528: return isAdvancedElement(e);
0529: }
0530:
0531: public DPContext getContext() {
0532: return dpContext;
0533: }
0534:
0535: public Element getElement() {
0536: return element;
0537: }
0538:
0539: public Element getParentElement() {
0540: Node pn = getElement().getParentNode();
0541: Element pe = (Element) pn;
0542:
0543: return pe;
0544: }
0545:
0546: public Document getDocument() {
0547: return element.getOwnerDocument();
0548: }
0549:
0550: public void setElement(Element e) {
0551: Node parentNode = element.getParentNode();
0552: parentNode.removeChild(element);
0553: parentNode.appendChild(e);
0554:
0555: element = e;
0556:
0557: checkType();
0558: }
0559:
0560: public abstract short getType();
0561:
0562: public abstract String getTag();
0563:
0564: public void setDummy(boolean state) {
0565: if (!state) {
0566: getRoot().setDirty(true);
0567: setDummyElement(getElement(), false);
0568:
0569: //
0570: // when we're a dummy, we defer our locked status
0571: // to that of the mergers. so we if we change
0572: // dummy status, we clear out the cached locked
0573: // value to make sure and re-calc the next time
0574: // someone calls isLocked()
0575: //
0576: locked = null;
0577:
0578: dummy = Boolean.FALSE;
0579: } else if (state) {
0580: setDummyElement(getElement(), true);
0581: dummy = Boolean.TRUE;
0582: }
0583: }
0584:
0585: private void setDummyElement(Element e, boolean state) {
0586: if (state) {
0587: //trace();
0588: e.setAttribute(DUMMY_KEY, TRUE_ATTR);
0589: } else {
0590: if (e.hasAttribute(DUMMY_KEY)) {
0591: e.removeAttribute(DUMMY_KEY);
0592: }
0593:
0594: Node n = e.getParentNode();
0595:
0596: if (n == null) {
0597: return;
0598: }
0599:
0600: if (n.getNodeType() != Node.ELEMENT_NODE) {
0601: return;
0602: }
0603:
0604: Element parentElement = (Element) n;
0605:
0606: //
0607: // what's this?
0608: // if the element we're recursing to is wrapped by
0609: // a dp object, then we want to make sure and
0610: // update it's "dummy" (cached isDummy result).
0611: // therefore, we try to get the matching dp object
0612: // from the cache. if it's there, then we call the
0613: // instance method setDummy() so we make sure and
0614: // update the cached isDummy value. if it's not
0615: // a cached dp object, then we don't have to worry
0616: // about that so we just set the dummy attr on
0617: // the element.
0618: //
0619:
0620: DPObject dpo = getObject(parentElement);
0621: if (dpo != null) {
0622: dpo.setDummy(false);
0623: } else {
0624: setDummyElement(parentElement, false);
0625: }
0626: }
0627: }
0628:
0629: public void setDirty(boolean state) {
0630: getRoot().setDirty(state);
0631: }
0632:
0633: public boolean isDirty() {
0634: return getRoot().isDirty();
0635: }
0636:
0637: public boolean isMerged() {
0638: return (mergers != null && mergers.size() > 0);
0639: }
0640:
0641: private static boolean isDummyElement(Element e) {
0642: String dummy = e.getAttribute(DUMMY_KEY);
0643:
0644: if (dummy == null || dummy.length() == 0
0645: || !dummy.equals(TRUE_ATTR)) {
0646: return false;
0647: }
0648:
0649: return true;
0650: }
0651:
0652: public boolean isDummy() {
0653: if (dummy == null) {
0654: if (isDummyElement(getElement())) {
0655: dummy = Boolean.TRUE;
0656: } else {
0657: dummy = Boolean.FALSE;
0658: }
0659: }
0660:
0661: return dummy.booleanValue();
0662: }
0663:
0664: static boolean isAtomicElement(Element e) {
0665: if ((e.getTagName().equals(STRING_TAG))
0666: || (e.getTagName().equals(BOOLEAN_TAG))
0667: || (e.getTagName().equals(INTEGER_TAG))
0668: || (e.getTagName().equals(REFERENCE_TAG))) {
0669: return true;
0670: }
0671:
0672: return false;
0673: }
0674:
0675: static void setName(Element e, String name) {
0676: e.setAttribute(NAME_KEY, name);
0677: }
0678:
0679: static String getCachedLocaleName(String l, String c, String v) {
0680: if (localeNames == null) {
0681: return null;
0682: }
0683:
0684: Map countries = (Map) localeNames.get(l);
0685: if (countries == null) {
0686: return null;
0687: }
0688:
0689: Map variants = (Map) countries.get(c);
0690: if (variants == null) {
0691: return null;
0692: }
0693:
0694: String name = (String) variants.get(v);
0695:
0696: return name;
0697: }
0698:
0699: static void putCachedLocaleName(String l, String c, String v,
0700: String name) {
0701: if (localeNames == null) {
0702: localeNames = new HashMap();
0703: }
0704:
0705: Map countries = (Map) localeNames.get(l);
0706: if (countries == null) {
0707: countries = new HashMap();
0708: localeNames.put(l, countries);
0709: }
0710:
0711: Map variants = (Map) countries.get(c);
0712: if (variants == null) {
0713: variants = new HashMap();
0714: countries.put(c, variants);
0715: }
0716:
0717: variants.put(v, name);
0718: }
0719:
0720: static String getLocaleName(String l, String c, String v) {
0721: String name = getCachedLocaleName(l, c, v);
0722:
0723: if (name == null) {
0724: StringBuffer b = new StringBuffer();
0725: b.append("_locale");
0726:
0727: if ((l != null) && (l.length() > 0)) {
0728: b.append("_");
0729: b.append(l);
0730: }
0731:
0732: if ((c != null) && (c.length() > 0)) {
0733: b.append("_");
0734: b.append(c);
0735: }
0736:
0737: if ((v != null) && (v.length() > 0)) {
0738: b.append("_");
0739: b.append(v);
0740: }
0741:
0742: name = b.toString();
0743: putCachedLocaleName(l, c, v, name);
0744: }
0745:
0746: return name;
0747: }
0748:
0749: static boolean isLocaleName(String name) {
0750: return name.startsWith("_locale");
0751: }
0752:
0753: static List parseLocaleName(String name) {
0754: List attrs = new ArrayList();
0755: StringTokenizer tk = new StringTokenizer(name, "_");
0756:
0757: String lang = null;
0758: String country = null;
0759: String variant = null;
0760: tk.nextToken();
0761: if (tk.hasMoreTokens()) {
0762: lang = tk.nextToken();
0763: }
0764: if (tk.hasMoreTokens()) {
0765: country = tk.nextToken();
0766: }
0767: if (tk.hasMoreTokens()) {
0768: variant = tk.nextToken();
0769: }
0770: attrs.add(lang);
0771: attrs.add(country);
0772: attrs.add(variant);
0773:
0774: return attrs;
0775: }
0776:
0777: static String getConditionalPropertiesName(String type, String value) {
0778: StringBuffer b = new StringBuffer();
0779: b.append("_conditional").append("_").append(type).append("_")
0780: .append(value);
0781:
0782: return b.toString();
0783: }
0784:
0785: static boolean isConditionalPropertiesName(String name) {
0786: return name.startsWith("_conditional");
0787: }
0788:
0789: static List parseConditionalPropertiesName(String name) {
0790: List attrs = new ArrayList();
0791: StringTokenizer tk = new StringTokenizer(name, "_");
0792:
0793: String type = "";
0794: String value = "";
0795: tk.nextToken();
0796: if (tk.hasMoreTokens()) {
0797: type = tk.nextToken();
0798: }
0799: if (tk.hasMoreTokens()) {
0800: value = tk.nextToken();
0801: }
0802: attrs.add(type);
0803: attrs.add(value);
0804:
0805: return attrs;
0806: }
0807:
0808: private static String getNameElement(Element e) {
0809: String name = e.getAttribute(NAME_KEY);
0810:
0811: if ((name == null) || (name.length() == 0)) {
0812: //
0813: // if it's a <ConditionalProperties> object
0814: // determine "name" from the condition and value
0815: //
0816: if (e.getTagName().equals(CONDITIONALPROPERTIES_TAG)) {
0817: String condition = e.getAttribute(CONDITION_KEY);
0818: String conditionValue = e.getAttribute(VALUE_KEY);
0819:
0820: name = getConditionalPropertiesName(condition,
0821: conditionValue);
0822: } else if (e.getTagName().equals(LOCALE_TAG)) {
0823: //
0824: // this is a <local> object. determine "name"
0825: // from the lang, country, and variant settings
0826: //
0827: String l = e.getAttribute("language");
0828: String c = e.getAttribute("country");
0829: String v = e.getAttribute("variant");
0830:
0831: name = getLocaleName(l, c, v);
0832: } else if (isAtomicElement(e)) {
0833: //
0834: // no name, string value becomes the key
0835: //
0836: Text textNode = null;
0837:
0838: if ((textNode = getTextNode(e)) == null) {
0839: //
0840: // no child (text) node, so value is in "value" attr
0841: //
0842: String value = e.getAttribute("value");
0843: if ((value != null) && (value.length() != 0)) {
0844: name = value;
0845: }
0846: } else {
0847: //
0848: // has child (text) node, so value is in body content
0849: //
0850: String text = textNode.getData();
0851: if ((text != null) && (text.length() != 0)) {
0852: name = text;
0853: }
0854: }
0855: }
0856: }
0857:
0858: return name;
0859: }
0860:
0861: protected static Text getTextNode(Element e) {
0862: NodeList childNodes = e.getChildNodes();
0863: int numChildren = childNodes.getLength();
0864:
0865: for (int i = 0; i < numChildren; i++) {
0866: Node childNode = childNodes.item(i);
0867: if (childNode.getNodeType() != Node.TEXT_NODE) {
0868: continue;
0869: }
0870: return (Text) childNode;
0871: }
0872:
0873: return null;
0874: }
0875:
0876: public String getName() {
0877: if (name == null) {
0878: name = getNameElement(getElement());
0879: }
0880:
0881: return name;
0882: }
0883:
0884: public void checkType() {
0885: checkType(getElement().getTagName());
0886: }
0887:
0888: void checkType(String actual) {
0889: if (actual.equals(getTag())) {
0890: return;
0891: }
0892: throw new DPError(
0893: "XMLDPObject.checkType(): wrong type tagName="
0894: + getElement().getTagName());
0895:
0896: }
0897:
0898: public String toDebugString() {
0899: StringBuffer b = new StringBuffer(256);
0900:
0901: b.append("\n\n\n\nthis=\n");
0902: b.append(toString(false));
0903:
0904: for (int i = 0; i < getMergers().size(); i++) {
0905: DPObject dpo = (DPObject) getMergers().get(i);
0906: b.append("\n\n\n\nmerger(");
0907: b.append(i);
0908: b.append(")=");
0909: b.append(dpo.toString(false));
0910: b.append("\n\n\n\n");
0911: }
0912:
0913: return b.toString();
0914: }
0915:
0916: public String toString() {
0917: StringBuffer b = new StringBuffer(256);
0918:
0919: toStringBuffer(getElement(), b, false, 0);
0920: return b.toString();
0921: }
0922:
0923: public String toString(boolean prune) {
0924: StringBuffer b = new StringBuffer(256);
0925:
0926: toStringBuffer(getElement(), b, prune, 0);
0927: return b.toString();
0928: }
0929:
0930: public String toMergedXML() {
0931: StringBuffer b = new StringBuffer(256);
0932: toStringBuffer(getMergedElement(), b, true, 0);
0933: return b.toString();
0934: }
0935:
0936: protected abstract Element getMergedElement();
0937:
0938: private static XMLDPEntityResolver getEntityResolver() {
0939: if (entityResolver == null) {
0940: entityResolver = new XMLDPEntityResolver();
0941: }
0942:
0943: return entityResolver;
0944: }
0945:
0946: private static XMLDPErrorHandler getErrorHandler(DPContext dpc) {
0947: if (errorHandler == null) {
0948: errorHandler = new XMLDPErrorHandler(dpc);
0949: }
0950:
0951: return errorHandler;
0952: }
0953:
0954: static DocumentBuilder getDocBuilder(DPContext dpc) {
0955: DocumentBuilderFactory dbf = DocumentBuilderFactory
0956: .newInstance();
0957:
0958: DocumentBuilder db = null;
0959:
0960: dbf.setValidating(dpc.isValidating());
0961:
0962: try {
0963: db = dbf.newDocumentBuilder();
0964: } catch (ParserConfigurationException pce) {
0965: throw new DPError("XMLDPObject.getDocBuilder(): ", pce);
0966: }
0967:
0968: db.setErrorHandler(getErrorHandler(dpc));
0969: db.setEntityResolver(getEntityResolver());
0970:
0971: return db;
0972: }
0973:
0974: Element createElement(String xml) {
0975: Document d = null;
0976:
0977: try {
0978: byte[] bytes = xml.getBytes("UTF-8");
0979: ByteArrayInputStream byteIS = new ByteArrayInputStream(
0980: bytes);
0981: InputSource is = new InputSource(byteIS);
0982: d = getDocBuilder().parse(is);
0983: } catch (SAXParseException spe) {
0984: throw new DPError("XMLDPRoot.createElement(): line="
0985: + spe.getLineNumber() + ". ", spe);
0986: } catch (SAXException se) {
0987: throw new DPError("XMLDPRoot.createElement(): ", se);
0988: } catch (IOException ioe) {
0989: throw new DPError("XMLDPRoot.createElement(): ", ioe);
0990: }
0991:
0992: Element docElement = d.getDocumentElement();
0993: Element importedElement = (Element) (getDocument().importNode(
0994: docElement, true));
0995:
0996: return importedElement;
0997: }
0998:
0999: static short getType(Element e) {
1000: if (e.getTagName().equals(STRING_TAG)) {
1001: return STRING_DP;
1002: } else if (e.getTagName().equals(REFERENCE_TAG)) {
1003: return REFERENCE_DP;
1004: } else if (e.getTagName().equals(COLLECTION_TAG)) {
1005: return COLLECTION_DP;
1006: } else if (e.getTagName().equals(INTEGER_TAG)) {
1007: return INTEGER_DP;
1008: } else if (e.getTagName().equals(BOOLEAN_TAG)) {
1009: return BOOLEAN_DP;
1010: } else if (e.getTagName().equals(CHANNEL_TAG)) {
1011: return CHANNEL_DP;
1012: } else if (e.getTagName().equals(CONTAINER_TAG)) {
1013: return CONTAINER_DP;
1014: } else if (e.getTagName().equals(PROPERTIES_TAG)) {
1015: return CONTAINER_DP;
1016: } else if (e.getTagName().equals(PROVIDER_TAG)) {
1017: return PROVIDER_DP;
1018: } else {
1019: return UNKNOWN_DP;
1020: }
1021: }
1022:
1023: static List getChildElements(Element e, String tagName) {
1024: NodeList childNodes = e.getChildNodes();
1025: int numChildren = childNodes.getLength();
1026:
1027: List childElements = new ArrayList();
1028:
1029: for (int i = 0; i < numChildren; i++) {
1030: Node childNode = childNodes.item(i);
1031: if (childNode.getNodeType() != Node.ELEMENT_NODE) {
1032: continue;
1033: }
1034: Element childElement = (Element) childNode;
1035:
1036: if (tagName != null) {
1037: String childTagName = childElement.getTagName();
1038: if (!childTagName.equals(tagName)) {
1039: continue;
1040: }
1041: }
1042:
1043: childElements.add(childElement);
1044: }
1045:
1046: return childElements;
1047: }
1048:
1049: static Element getChildElement(Element e, String tagName) {
1050: return getChildElement(e, tagName, null);
1051: }
1052:
1053: static Element getChildElement(Element e, String tagName,
1054: String name) {
1055: NodeList childNodes = e.getChildNodes();
1056: int numChildren = childNodes.getLength();
1057:
1058: for (int i = 0; i < numChildren; i++) {
1059: Node childNode = childNodes.item(i);
1060: if (childNode.getNodeType() != Node.ELEMENT_NODE) {
1061: continue;
1062: }
1063: Element childElement = (Element) childNode;
1064:
1065: if (tagName != null) {
1066: String childTagName = childElement.getTagName();
1067: if (!childTagName.equals(tagName)) {
1068: continue;
1069: }
1070: }
1071:
1072: if (name != null) {
1073: String childName = getNameElement(childElement);
1074: if (!childName.equals(name)) {
1075: continue;
1076: }
1077: }
1078:
1079: return childElement;
1080: }
1081:
1082: return null;
1083: }
1084:
1085: static void appendBuffer(String a, StringBuffer b, int indent) {
1086: if (b.length() != 0) {
1087: if (b.charAt(b.length() - 1) == '\n') {
1088: for (int i = 0; i < indent * INDENT_SPACES; i++) {
1089: b.append(" ");
1090: }
1091: }
1092: }
1093:
1094: b.append(a);
1095: }
1096:
1097: static void toStringBuffer(Node n, StringBuffer b, boolean prune,
1098: int indent) {
1099:
1100: //
1101: // note: we only handle ELEMENT and TEXT node types
1102: //
1103:
1104: switch (n.getNodeType()) {
1105: case Node.ELEMENT_NODE:
1106: Element e = (Element) n;
1107: if (prune) {
1108: if (e.hasAttribute(DUMMY_KEY)) {
1109: return;
1110: }
1111: }
1112:
1113: appendBuffer("<", b, indent);
1114: appendBuffer(e.getTagName(), b, indent);
1115:
1116: NamedNodeMap attrs = e.getAttributes();
1117: if (attrs != null) {
1118: int numAttrs = attrs.getLength();
1119: for (int i = 0; i < numAttrs; i++) {
1120: Node na = attrs.item(i);
1121: if (na.getNodeType() != Node.ATTRIBUTE_NODE) {
1122: continue;
1123: }
1124: Attr a = (Attr) na;
1125: appendBuffer(" ", b, indent);
1126: appendBuffer(Encoder.XML_ENCODER
1127: .encode(a.getName()), b, indent);
1128: appendBuffer("=\"", b, indent);
1129: appendBuffer(Encoder.XML_ENCODER.encode(a
1130: .getValue()), b, indent);
1131: appendBuffer("\"", b, indent);
1132: }
1133: }
1134:
1135: Node s = e.getNextSibling();
1136: boolean appendNewline = !(s != null && s.getNodeType() == Node.TEXT_NODE);
1137:
1138: NodeList nodes = e.getChildNodes();
1139:
1140: if (nodes.getLength() == 0) {
1141: if (appendNewline) {
1142: appendBuffer("/>\n", b, indent);
1143: } else {
1144: appendBuffer("/>", b, indent);
1145: }
1146: } else {
1147:
1148: if (nodes.item(0).getNodeType() == Node.TEXT_NODE) {
1149: appendBuffer(">", b, indent);
1150: } else {
1151: appendBuffer(">\n", b, indent);
1152: }
1153:
1154: for (int j = 0; j < nodes.getLength(); j++) {
1155: toStringBuffer(nodes.item(j), b, prune, indent + 1);
1156: }
1157:
1158: appendBuffer("</", b, indent);
1159: appendBuffer(e.getTagName(), b, indent);
1160: if (appendNewline) {
1161: appendBuffer(">\n", b, indent);
1162: } else {
1163: appendBuffer(">", b, indent);
1164: }
1165: }
1166:
1167: break;
1168:
1169: case Node.COMMENT_NODE:
1170: Comment c = (Comment) n;
1171: appendBuffer("<!--", b, indent);
1172: appendBuffer(c.getData(), b, indent);
1173: appendBuffer("-->\n", b, indent);
1174:
1175: break;
1176:
1177: case Node.TEXT_NODE:
1178: Text t = (Text) n;
1179: String text = t.getData();
1180: if (text.length() > 0) {
1181: appendBuffer(Encoder.XML_ENCODER.encode(text), b, 0);
1182: }
1183:
1184: break;
1185:
1186: default:
1187: throw new DPError(
1188: "XMLDPObject.toStringBuffer(): unknown node type encountered");
1189: }
1190: }
1191:
1192: /*
1193: Element setValuesByDP(
1194: DPContext dpc, Element parentElement, List l
1195: ) {
1196: Document d = parentElement.getOwnerDocument();
1197: String parentTagName = parentElement.getTagName();
1198: String name = getName(parentElement);
1199:
1200: Element newElement = d.createElement(
1201: parentTagName
1202: );
1203: if (name != null) {
1204: setName(newElement, name);
1205: }
1206:
1207: for (Iterator i = l.iterator(); i.hasNext(); ){
1208: Object value = i.next();
1209: XMLDPObject dpo = (XMLDPObject)value;
1210: Element e = dpo.getElement();
1211: newElement.appendChild(e);
1212: }
1213: parentElement.getParentNode().replaceChild(newElement, parentElement);
1214:
1215: return newElement;
1216: }
1217: */
1218:
1219: /*
1220: Element setValuesByObject(
1221: DPContext dpc, Element parentElement, Map m
1222: ) {
1223: Document d = parentElement.getOwnerDocument();
1224: String parentTagName = parentElement.getTagName();
1225: String elemName = getName(parentElement);
1226:
1227: Element newElement = d.createElement(
1228: parentTagName
1229: );
1230: if (elemName != null) {
1231: setName(newElement, elemName);
1232: }
1233: message("XMLDPObject.getValuesByObject(): elemName=" + elemName);
1234:
1235: for (Iterator i = m.keySet().iterator(); i.hasNext(); ){
1236: String name = (String)i.next();
1237: Object value = m.get(name);
1238: XMLDPProperty dpp = (XMLDPProperty)XMLDPFactory.
1239: getInstance().
1240: createProperty(dpc, getRoot(), d, name, value);
1241: Element e = dpp.getElement();
1242: newElement.appendChild(e);
1243: debug("XMLDObject.setValuesByObject(): appended child " +
1244: "value=" + value);
1245: }
1246: parentElement.getParentNode().replaceChild(newElement, parentElement);
1247:
1248: return newElement;
1249: }
1250: */
1251:
1252: /*
1253: Element setValuesByObject(
1254: DPContext dpc, Element parentElement, List l
1255: ) {
1256: Document d = parentElement.getOwnerDocument();
1257: String parentTagName = parentElement.getTagName();
1258: String elemName = getName(parentElement);
1259:
1260: Element newElement = d.createElement(
1261: parentTagName
1262: );
1263: if (elemName != null) {
1264: setName(newElement, elemName);
1265: }
1266: message("XMLDPObject.getValuesByObject(): elemName=" + elemName);
1267:
1268: for (Iterator i = l.iterator(); i.hasNext(); ) {
1269: Object value = i.next();
1270: XMLDPProperty dpp =
1271: (XMLDPProperty)XMLDPFactory.
1272: getInstance().
1273: createProperty(dpc, getRoot(), d, null, value);
1274: Element e = dpp.getElement();
1275: newElement.appendChild(e);
1276: debug("XMLDObject.setValuesByObject(): appended child " +
1277: "value=" + value);
1278: }
1279: parentElement.getParentNode().replaceChild(newElement, parentElement);
1280:
1281: return newElement;
1282: }
1283: */
1284:
1285: /*
1286: Element setReferenceValuesByObject(
1287: DPContext dpc, DPRoot r, Element parentElement, List l
1288: ) {
1289: Document d = parentElement.getOwnerDocument();
1290: String parentTagName = parentElement.getTagName();
1291: String elemName = getName(parentElement);
1292:
1293: Element newElement = d.createElement(
1294: parentTagName
1295: );
1296: if (elemName != null) {
1297: setName(newElement, elemName);
1298: }
1299: message("XMLDPObject.getValuesByObject(): elemName=" + elemName);
1300:
1301: for (Iterator i = l.iterator(); i.hasNext(); ) {
1302: String value = (String)i.next();
1303: XMLDPReference dpr =
1304: (XMLDPReference)XMLDPFactory.
1305: getInstance().
1306: createReference(dpc, r, d, value);
1307: Element e = dpr.getElement();
1308: newElement.appendChild(e);
1309: debug("XMLDObject.setValuesByObject(): appended child " +
1310: "value=" + value);
1311: }
1312: parentElement.getParentNode().replaceChild(newElement, parentElement);
1313:
1314: return newElement;
1315: }
1316: */
1317:
1318: static Element createElement(DPContext dpc, Document d,
1319: String tagName) {
1320: Element e = d.createElement(tagName);
1321: return e;
1322: }
1323:
1324: static Element createElement(DPContext dpc, Document d,
1325: String tagName, String name) {
1326: Element e = createElement(dpc, d, tagName);
1327: if (name != null) {
1328: setName(e, name);
1329: }
1330: return e;
1331: }
1332:
1333: public int compareTo(Object o) {
1334: DPObject dpo = (DPObject) o;
1335:
1336: if (getPriority() < dpo.getPriority()) {
1337: return -1;
1338: } else if (getPriority() > dpo.getPriority()) {
1339: return 1;
1340: } else {
1341: return 0;
1342: }
1343: }
1344:
1345: /**
1346: * Tests equality for this XML DP object. Two XML DP objects are equal
1347: * if there underlying DOM elements are equal
1348: */
1349: public boolean equals(Object o) {
1350: if (!(o instanceof XMLDPObject)) {
1351: return false;
1352: }
1353: XMLDPObject xmldpo = (XMLDPObject) o;
1354:
1355: Element e = getElement();
1356: Element f = xmldpo.getElement();
1357:
1358: boolean eq = e.equals(f);
1359: return eq;
1360: }
1361:
1362: static boolean toBoolean(String name) {
1363: return ((name != null) && name.toLowerCase().equals("true"));
1364: }
1365:
1366: public static boolean staticGetDefaultLockValue() {
1367: return false;
1368: }
1369:
1370: public boolean getDefaultLockValue() {
1371: return staticGetDefaultLockValue();
1372: }
1373:
1374: public static boolean staticGetDefaultAdvancedValue() {
1375: return false;
1376: }
1377:
1378: public boolean getDefaultAdvancedValue() {
1379: return staticGetDefaultAdvancedValue();
1380: }
1381:
1382: public static boolean staticGetDefaultPropagateValue() {
1383: return true;
1384: }
1385:
1386: public boolean getDefaultPropagateValue() {
1387: return staticGetDefaultPropagateValue();
1388: }
1389:
1390: public void appendMergeAttr(StringBuffer b) {
1391: if (getMergeType() != getDefaultMergeType()) {
1392: b.append(" " + MERGE_KEY + "=\"").append(
1393: MERGETYPE_VALUES[getMergeType()]).append("\"");
1394: }
1395: }
1396:
1397: public void appendLockAttr(StringBuffer b) {
1398: if (isLockedElement(getElement()) != getDefaultLockValue()) {
1399: b.append(" " + LOCK_KEY + "=\"").append(isLocked()).append(
1400: "\"");
1401: }
1402: }
1403:
1404: public void appendAdvancedAttr(StringBuffer b) {
1405: if (isAdvancedElement(getElement()) != getDefaultAdvancedValue()) {
1406: b.append(" " + ADVANCED_KEY + "=\"").append(isAdvanced())
1407: .append("\"");
1408: }
1409:
1410: }
1411:
1412: public void appendStartTag(StringBuffer b) {
1413: b.append("<").append(getTag());
1414: }
1415:
1416: public void appendEndTag(StringBuffer b) {
1417: b.append("</").append(getTag()).append(">\n");
1418: }
1419:
1420: public void indentBuffer(StringBuffer b, int indent) {
1421: if (b.length() != 0) {
1422: if (b.charAt(b.length() - 1) == '\n') {
1423: for (int i = 0; i < indent * INDENT_SPACES; i++) {
1424: b.append(" ");
1425: }
1426: }
1427: }
1428: }
1429:
1430: public static int max(int a, int b, int c) {
1431: return (Math.max(a, Math.max(b, c)));
1432: }
1433:
1434: }
|