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.Document;
0008: import org.w3c.dom.Element;
0009: import org.w3c.dom.Node;
0010:
0011: import java.util.Locale;
0012: import java.util.List;
0013: import java.util.Iterator;
0014: import java.util.ListIterator;
0015: import java.util.Set;
0016: import java.util.HashSet;
0017: import java.util.Map;
0018: import java.util.ArrayList;
0019:
0020: import com.sun.portal.desktop.context.DPContext;
0021: import com.sun.portal.desktop.context.ContextException;
0022: import com.sun.portal.providers.context.ProviderContext;
0023: import com.sun.portal.desktop.context.ProviderContextThreadLocalizer;
0024:
0025: import com.sun.portal.desktop.dp.DPError;
0026: import com.sun.portal.desktop.dp.DPProperties;
0027: import com.sun.portal.desktop.dp.DPPropertyHolder;
0028: import com.sun.portal.desktop.dp.DPProperty;
0029: import com.sun.portal.desktop.dp.DPString;
0030: import com.sun.portal.desktop.dp.DPLocale;
0031: import com.sun.portal.desktop.dp.DPInteger;
0032: import com.sun.portal.desktop.dp.DPBoolean;
0033: import com.sun.portal.desktop.dp.DPCollection;
0034: import com.sun.portal.desktop.dp.DPRoot;
0035: import com.sun.portal.desktop.dp.DPChannel;
0036: import com.sun.portal.desktop.dp.DPProvider;
0037: import com.sun.portal.desktop.dp.DPConditionalProperties;
0038:
0039: import com.sun.portal.providers.context.PropertiesFilter;
0040: import com.sun.portal.providers.context.LocalePropertiesFilter;
0041: import com.sun.portal.providers.context.PropertiesFilterException;
0042:
0043: public class XMLDPProperties extends XMLDPCollection implements
0044: DPProperties, XMLDPTags {
0045: private Element holderElement = null;
0046:
0047: XMLDPProperties(DPContext dpc, DPRoot r, Document d) {
0048: super (dpc, r, createElement(dpc, d));
0049: }
0050:
0051: XMLDPProperties(DPContext dpc, DPRoot r, Element e) {
0052: super (dpc, r, e);
0053: }
0054:
0055: public DPProperty getParentProperty() {
0056: return null;
0057: }
0058:
0059: Element getPropertyHolderElement() {
0060: if (holderElement == null) {
0061: Element e = getElement();
0062: while (e.getTagName().equals(CONDITIONALPROPERTIES_TAG)) {
0063: e = (Element) e.getParentNode();
0064: }
0065:
0066: Node parentNode = e.getParentNode();
0067:
0068: if (parentNode == null) {
0069: throw new DPError(
0070: "XMLDPProperties.getPropertyHolderElement(): could not get parent node");
0071: }
0072: if (parentNode.getNodeType() != Node.ELEMENT_NODE) {
0073: throw new DPError(
0074: "XMLDPProperties.getPropertyHolderElement(): parent node was not an element");
0075: }
0076:
0077: holderElement = (Element) parentNode;
0078: }
0079:
0080: return holderElement;
0081: }
0082:
0083: protected DPPropertyHolder getPropertyHolderFromThis() {
0084: Element holderElement = getPropertyHolderElement();
0085: DPPropertyHolder holder = (DPPropertyHolder) getObject(holderElement);
0086: if (holder == null) {
0087: holder = XMLDPFactory.getInstance().getPropertyHolder(
0088: getContext(), getRoot(), holderElement);
0089: putObject(holder);
0090: }
0091:
0092: return holder;
0093: }
0094:
0095: public DPPropertyHolder getPropertyHolder() {
0096: DPPropertyHolder holder = getPropertyHolderFromThis();
0097:
0098: if (holder != null && holder.isMerged()) {
0099: // nothing
0100: } else {
0101: for (int i = 0; i < getMergers().size(); i++) {
0102: DPProperties dpp = (DPProperties) getMergers().get(i);
0103:
0104: DPPropertyHolder dpph = ((XMLDPProperties) dpp)
0105: .getPropertyHolderFromThis();
0106: holder.addMerger(dpph);
0107: }
0108: }
0109:
0110: return holder;
0111: }
0112:
0113: public short getType() {
0114: return PROPERTIES_DP;
0115: }
0116:
0117: public String getTag() {
0118: return PROPERTIES_TAG;
0119: }
0120:
0121: public DPProperty add(DPProperty dpp, List pflist) {
0122: return add(dpp, true, true, false, pflist);
0123: }
0124:
0125: DPProperty add(DPProperty dpp, boolean copy, boolean deep,
0126: boolean dummy, List pflist) {
0127: if (pflist == null || pflist.size() == 0) {
0128: return add(dpp, copy, deep, dummy);
0129: }
0130:
0131: PropertiesFilter pf = (PropertiesFilter) pflist.get(0);
0132: String condition = null;
0133: String conditionValue = null;
0134: try {
0135: condition = pf.getCondition();
0136: conditionValue = pf.getValue();
0137: } catch (PropertiesFilterException pfe) {
0138: throw new DPError(
0139: "XMLDPProperties.add(): cannot access pf=" + pf,
0140: pfe);
0141: }
0142: DPConditionalProperties dptp = getConditionalPropertiesFromThis(
0143: condition, conditionValue);
0144: if (dptp == null) {
0145: dptp = XMLDPFactory.getInstance()
0146: .createConditionalProperties(getContext(),
0147: getRoot(), getDocument(), condition,
0148: conditionValue);
0149: dptp = (DPConditionalProperties) add(dptp, false, false,
0150: dummy);
0151: }
0152: return ((XMLDPConditionalProperties) dptp).add(dpp, copy, deep,
0153: dummy, pflist.subList(1, pflist.size()));
0154:
0155: }
0156:
0157: public DPProperty get(String key) {
0158: return get(key, null, true, true);
0159: }
0160:
0161: public DPProperty get(String key, boolean scoped) {
0162: return get(key, null, true, scoped);
0163: }
0164:
0165: public DPProperty get(String key, List pflist, boolean exact) {
0166: return get(key, pflist, exact, true);
0167: }
0168:
0169: /**
0170: * note that when exact flag is on, it overrides all required flags
0171: * in the PropertiesFilters objects.
0172: */
0173: public DPProperty get(String key, List pflist, boolean exact,
0174: boolean scoped) {
0175: //
0176: // pseudocode is:
0177: //
0178: // get {
0179: // if key exists in my conditional properties return property
0180: // if filters consists of locale filters only and key exists in my
0181: // locale objects(s) return property
0182: // if key exists in me then return property
0183: // if key exists in my provider then return myprovider.get(key)
0184: // return myowner.parent.get(key)
0185: // }
0186: //
0187: // step #5 above is recursive
0188: //
0189:
0190: DPProperty dpp = null;
0191:
0192: boolean filtered = (pflist != null && pflist.size() > 0);
0193: if (filtered) {
0194: dpp = getConditional(key, pflist, exact);
0195: if (dpp != null) {
0196: return dpp;
0197: }
0198:
0199: //
0200: // try looking in the locale objects
0201: // when <Locale> tag is no longer supported, this section should
0202: // be removed
0203: //
0204: if (!exact) {
0205: Locale locale = null;
0206: try {
0207: locale = LocalePropertiesFilter.getLocale(pflist);
0208: } catch (PropertiesFilterException pfe) {
0209: throw new DPError(
0210: "XMLDPProperties.get(): cannot get locale. pflist="
0211: + pflist);
0212: }
0213: if (locale != null) {
0214: DPLocale dpLocale = getLocale(locale, exact);
0215: if (dpLocale != null) {
0216: dpp = dpLocale.get(key);
0217: if (dpp != null) {
0218: return dpp;
0219: }
0220: }
0221: }
0222: }
0223: }
0224:
0225: //
0226: // we either didn't look in filters or could not find
0227: // in the filters specified.
0228: // look directly under the properties bag.
0229: // note: skip this step if filter is specified and exact match
0230: // is required
0231: //
0232:
0233: if (!filtered || !exact) {
0234: dpp = super .get(key);
0235:
0236: if (dpp != null) {
0237: return dpp;
0238: }
0239: }
0240:
0241: //
0242: // if we're not scoped, return null here
0243: // if we get here, that means that we
0244: // could not yet find the property
0245: //
0246: if (!scoped) {
0247: return null;
0248: }
0249:
0250: //
0251: // can't find in our properties.
0252: // here, what we want is to look for it in the provider,
0253: // but only if our parent is a provier.
0254: //
0255: // there are 3 possibilities:
0256: //
0257: // first is that our owner is a channel, in which case we can
0258: // get the provider and look in it for the value.
0259: //
0260: // 2nd is that the owner is a root,
0261: // in which case the attempt to get the owner's parent
0262: // will return null.
0263: //
0264: // 3rd is that the owner is a provider, in which case again the
0265: // owner's parent is null, and we will return null.
0266: //
0267: DPPropertyHolder dpph = getPropertyHolder();
0268: if (!(dpph instanceof DPChannel)) {
0269: //
0270: // this check also ensures that we do not attempt to look in
0271: // our parent if we're not a channel (see below)
0272: //
0273: return null;
0274: }
0275:
0276: DPChannel dpc = (DPChannel) dpph;
0277: DPProvider dpProvider = dpc.getProvider();
0278:
0279: if (dpProvider != null) {
0280: DPProperties dpProperties = dpProvider.getProperties();
0281: dpp = dpProperties.get(key, pflist, exact);
0282:
0283: if (dpp != null) {
0284: return dpp;
0285: }
0286: }
0287:
0288: //
0289: // can't find in this properties. look in owner's parent.
0290: //
0291: // note, if our owner is a provider, then we'll never reach this point.
0292: // even if we did, we'd get null back for the owner and would not
0293: // proceed.
0294: //
0295:
0296: DPPropertyHolder parentDPPH = dpph.getParentPropertyHolder();
0297: if (parentDPPH == null) {
0298: return null;
0299: }
0300:
0301: //
0302: // this call is recursive!
0303: //
0304:
0305: dpp = parentDPPH.getProperties().get(key, pflist, exact);
0306: return dpp;
0307: }
0308:
0309: public void set(String key, Object val, List pflist) {
0310: //
0311: // make sure that the property with the key exists somewhere
0312: //
0313: DPProperty oldProperty = get(key, pflist, false);
0314:
0315: if (oldProperty == null) {
0316: //
0317: // property does not exist, throw an error
0318: //
0319: throw new DPError(
0320: "XMLDPProperties.set(): property does not exist name="
0321: + key + ", pflist=" + pflist);
0322: }
0323:
0324: DPProperty newProperty = null;
0325:
0326: if (!oldProperty.isPropagate()) {
0327: newProperty = oldProperty;
0328: newProperty.setPropagate(false);
0329: } else {
0330: if (!isPropertyFromThis(oldProperty)) {
0331: //
0332: // property is not local, add to this
0333: //
0334: DPProperties dpp = oldProperty.getProperties();
0335: List pflistMatched = ((XMLDPProperties) dpp)
0336: .getMatchedPropertiesFilters(key, pflist);
0337: newProperty = (DPProperty) add(oldProperty,
0338: pflistMatched);
0339: } else {
0340: //
0341: // propert is local, just set to new value
0342: //
0343: newProperty = oldProperty;
0344: }
0345: }
0346:
0347: newProperty.setValue(val);
0348: }
0349:
0350: /**
0351: * given the key and the pflist, it looks up the property then instead of
0352: * returning the value it returns the pflist that corresponds to
0353: * the property found.
0354: * note that merger *is* considered when it looks up the property.
0355: */
0356: List getMatchedPropertiesFilters(String key, List pflist) {
0357: //
0358: // recreate pflist based on the ranking returned by a call to
0359: // getBestRanked(). the resulting pflist will contain only the
0360: // properties filters that currently exist.
0361: //
0362: RankedDPProperty rdp = getBestRanked(key, pflist, false, 0,
0363: null);
0364:
0365: List pflistMatched = null;
0366: if (pflist != null && pflist.size() > 0) {
0367: pflistMatched = pflist.subList(0, rdp.rank);
0368: } else {
0369: pflistMatched = pflist;
0370: }
0371:
0372: return pflistMatched;
0373: }
0374:
0375: public DPProperty getConditional(String key, List pflist,
0376: boolean exact) {
0377: RankedDPProperty rdp = getBestRanked(key, pflist, exact, 0,
0378: null);
0379: //error("XMLDPProperties.getConditional(): key=" + key + ", pflist=" + pflist + ", exact=" + exact + ", property=" + rdp.dpProperty);
0380: return rdp.dpProperty;
0381: }
0382:
0383: /**
0384: * match the first PropertiesFilter then recurse on the matched
0385: * results.
0386: * update ranking everytime match succeeds.
0387: * when there are multiple matches, compare the ranking and pick the
0388: * highest one.
0389: * when there is no matches and required flag is on, return the best
0390: * match found so far. otherwise, if the required flag is off, look ahead
0391: * to the next filter and try matching again.
0392: * return the ranked dp property object which contains the property that
0393: * has the highest ranking and the rank value.
0394: */
0395: private RankedDPProperty getBestRanked(String key, List pflist,
0396: boolean exact, int rank, DPProperty defDPProperty) {
0397: //
0398: // no more matching to do, return the property
0399: //
0400: if (pflist == null || pflist.size() == 0) {
0401: DPProperty dpp = super .get(key);
0402: return new RankedDPProperty(dpp, rank);
0403: }
0404:
0405: DPProperty dpp = null;
0406: if (!exact) {
0407: dpp = defDPProperty;
0408: }
0409:
0410: //
0411: // match the first PropertiesFilter then pass on the rest of the
0412: // PropertiesFilters to the matched results
0413: //
0414: PropertiesFilter pf = (PropertiesFilter) pflist.get(0);
0415: List matches = matchConditionalProperties(pf);
0416: List newpflist = pflist.subList(1, pflist.size());
0417: int bestRank = rank;
0418:
0419: if (matches != null && matches.size() > 0) {
0420: for (int i = 0; i < matches.size(); i++) {
0421: DPProperties dpps = (DPProperties) matches.get(i);
0422: RankedDPProperty nrdp = ((XMLDPProperties) dpps)
0423: .getBestRanked(key, newpflist, exact, rank + 1,
0424: ((XMLDPProperties) dpps)
0425: .get(key, false));
0426: //
0427: // find the best match (higher rank)
0428: //
0429: if (nrdp.dpProperty != null && nrdp.rank > bestRank) {
0430: dpp = nrdp.dpProperty;
0431: bestRank = nrdp.rank;
0432: }
0433: }
0434: } else {
0435: //
0436: // try next filter if required match is off
0437: //
0438: if (!exact && !pf.isRequired() && newpflist.size() > 0) {
0439: return getBestRanked(key, newpflist, exact, rank, dpp);
0440: }
0441: }
0442:
0443: return new RankedDPProperty(dpp, bestRank);
0444: }
0445:
0446: /**
0447: * return a list of merged conditionalproperties that match given propertiesfilter
0448: */
0449: public List matchConditionalProperties(PropertiesFilter pf) {
0450: //
0451: // get matches from this
0452: //
0453: List matches = matchConditionalPropertiesFromThis(pf);
0454: //
0455: // go through mergers and gather matches
0456: //
0457: for (int i = 0; i < getMergers().size(); i++) {
0458: DPProperties mdpp = (DPProperties) getMergers().get(i);
0459: List matchesFromMerger = ((XMLDPProperties) mdpp)
0460: .matchConditionalPropertiesFromThis(pf);
0461: for (int j = 0; j < matchesFromMerger.size(); j++) {
0462: DPConditionalProperties dpp = (DPConditionalProperties) matchesFromMerger
0463: .get(j);
0464: if (dpp != null) {
0465: String condition = dpp.getCondition();
0466: String conditionValue = dpp.getConditionValue();
0467: DPConditionalProperties dpConditionalProperties = getConditionalPropertiesFromThis(
0468: condition, conditionValue);
0469: //
0470: // create dummies if the match doesn't already exists in this
0471: //
0472: if (dpConditionalProperties == null) {
0473: DPConditionalProperties dptp = (DPConditionalProperties) ((XMLDPConditionalProperties) dpp)
0474: .createDummy(getRoot());
0475: dpConditionalProperties = (DPConditionalProperties) add(
0476: dptp, false, false, true);
0477: matches.add(dpConditionalProperties);
0478: }
0479: }
0480: }
0481: }
0482:
0483: //
0484: // add mergers
0485: //
0486: for (ListIterator m = matches.listIterator(); m.hasNext();) {
0487: DPConditionalProperties dpConditionalProperties = (DPConditionalProperties) m
0488: .next();
0489: if (dpConditionalProperties.isMerged()) {
0490: continue;
0491: }
0492: for (int j = 0; j < getMergers().size(); j++) {
0493: DPProperties ndpp = (DPProperties) getMergers().get(j);
0494: if (ndpp != null) {
0495: String condition = dpConditionalProperties
0496: .getCondition();
0497: String conditionValue = dpConditionalProperties
0498: .getConditionValue();
0499: DPConditionalProperties mmdpp = ((XMLDPProperties) ndpp)
0500: .getConditionalPropertiesFromThis(
0501: condition, conditionValue);
0502: if (mmdpp != null) {
0503: if (!dpConditionalProperties.isMergeLocked()
0504: && mmdpp.isLocked() && mmdpp.isRemove()) {
0505: m.remove();
0506: } else {
0507: dpConditionalProperties.addMerger(mmdpp);
0508: }
0509: }
0510: }
0511: }
0512: }
0513:
0514: //
0515: // delete removed ones from the matches
0516: //
0517: for (ListIterator li = matches.listIterator(); li.hasNext();) {
0518: DPConditionalProperties dpConditionalProperties = (DPConditionalProperties) li
0519: .next();
0520: if (!dpConditionalProperties.isMergeLocked()
0521: && dpConditionalProperties.isRemove()) {
0522: li.remove();
0523: }
0524: }
0525:
0526: //error("XMLDPProperties.matchConditionalProperties(): returning matches=" + matches);
0527: return matches;
0528: }
0529:
0530: List matchConditionalPropertiesElements(PropertiesFilter pf) {
0531: List matches = new ArrayList();
0532: Set names = propertiesTable.keySet();
0533: //
0534: // TODO: make propertiesTable more efficient for conditional properties
0535: //
0536: for (Iterator i = names.iterator(); i.hasNext();) {
0537: String name = (String) i.next();
0538: if (isConditionalPropertiesName(name)) {
0539: Element e = (Element) propertiesTable.get(name);
0540: String condition = e.getAttribute(CONDITION_KEY);
0541: String conditionValue = e.getAttribute(VALUE_KEY);
0542: //ProviderContext pc = ProviderContextThreadLocalizer.get();
0543: boolean matched = false;
0544: try {
0545: //matched = pf.match(pc, condition, conditionValue);
0546: matched = pf.match(condition, conditionValue);
0547: } catch (PropertiesFilterException pfe) {
0548: throw new DPError(
0549: "XMLDPProperties.matchConditionalPropertiesElements(): ",
0550: pfe);
0551: }
0552: if (matched) {
0553: matches.add(e);
0554: }
0555: }
0556: }
0557: return matches;
0558: }
0559:
0560: protected List matchConditionalPropertiesFromThis(
0561: PropertiesFilter pf) {
0562: List matchElements = matchConditionalPropertiesElements(pf);
0563: List matches = new ArrayList();
0564:
0565: for (int i = 0; i < matchElements.size(); i++) {
0566: Element e = (Element) matchElements.get(i);
0567: DPConditionalProperties dpp = null;
0568: if (e != null) {
0569: dpp = (DPConditionalProperties) getObject(e);
0570: if (dpp == null) {
0571: dpp = XMLDPFactory.getInstance()
0572: .getConditionalProperties(getContext(),
0573: getRoot(), e);
0574: putObject(dpp);
0575: }
0576: matches.add(dpp);
0577: }
0578: }
0579:
0580: return matches;
0581: }
0582:
0583: Element getConditionalPropertiesElement(String condition,
0584: String conditionValue) {
0585: Element propertiesElement = (Element) propertiesTable
0586: .get(getConditionalPropertiesName(condition,
0587: conditionValue));
0588: return propertiesElement;
0589: }
0590:
0591: protected DPConditionalProperties getConditionalPropertiesFromThis(
0592: String condition, String conditionValue) {
0593: Element e = getConditionalPropertiesElement(condition,
0594: conditionValue);
0595: DPConditionalProperties dpp = null;
0596: if (e != null) {
0597: dpp = (DPConditionalProperties) getObject(e);
0598: if (dpp == null) {
0599: dpp = XMLDPFactory.getInstance()
0600: .getConditionalProperties(getContext(),
0601: getRoot(), e);
0602: putObject(dpp);
0603: }
0604: }
0605: return dpp;
0606: }
0607:
0608: public DPConditionalProperties getConditionalProperties(
0609: String condition, String value) {
0610:
0611: boolean replace = false;
0612: DPConditionalProperties dpCondProp = getConditionalPropertiesFromThis(
0613: condition, value);
0614:
0615: if (dpCondProp != null && dpCondProp.isMerged()) {
0616: // nothing
0617: } else {
0618: for (int i = 0; i < getMergers().size(); i++) {
0619: DPProperties dpp = (DPProperties) getMergers().get(i);
0620:
0621: DPConditionalProperties dpcp = ((XMLDPProperties) dpp)
0622: .getConditionalPropertiesFromThis(condition,
0623: value);
0624:
0625: if (dpcp != null) {
0626: if (dpCondProp != null) {
0627: if (dpcp.getType() != dpCondProp.getType()) {
0628: throw new DPError(
0629: "XMLDPProperties.get(): conflicting types found for condition = "
0630: + condition
0631: + " and value = " + value);
0632: }
0633: } else {
0634: DPConditionalProperties ddpcp = (DPConditionalProperties) ((XMLDPConditionalProperties) dpcp)
0635: .createDummy(getRoot());
0636: dpCondProp = (DPConditionalProperties) add(
0637: ddpcp, false, false, true);
0638: if (!dpcp.isLocked() && dpCondProp.isDummy()
0639: && dpcp.isReplace()) {
0640: replace = true;
0641: }
0642: }
0643:
0644: if (!dpCondProp.isMergeLocked()) {
0645: if (dpcp.isLocked() && dpcp.isRemove()) {
0646: dpCondProp = null;
0647: break;
0648: }
0649: }
0650:
0651: dpCondProp.addMerger(dpcp);
0652: }
0653: }
0654: }
0655:
0656: if (dpCondProp != null) {
0657: if (!dpCondProp.isMergeLocked() && dpCondProp.isRemove()) {
0658: dpCondProp = null;
0659: }
0660: }
0661:
0662: if (replace) {
0663: dpCondProp = null;
0664: }
0665:
0666: return dpCondProp;
0667: }
0668:
0669: /**
0670: * Remove once <Locale> support is no longer needed.
0671: */
0672: public DPLocale getLocale(Locale locale, boolean exact) {
0673: if (locale == null) {
0674: return null;
0675: }
0676:
0677: String language = locale.getLanguage();
0678: String country = locale.getCountry();
0679: String variant = locale.getVariant();
0680:
0681: return getLocale(language, country, variant, exact);
0682: }
0683:
0684: /**
0685: * Remove once <Locale> support is no longer needed.
0686: */
0687: public DPLocale getLocale(String language, String country,
0688: String variant, boolean exact) {
0689: boolean replace = false;
0690: DPLocale dpLocale = null;
0691:
0692: while (dpLocale == null && language != null) {
0693: dpLocale = getLocaleFromThis(language, country, variant,
0694: true);
0695:
0696: if (dpLocale != null && dpLocale.isMerged()) {
0697: // nothing
0698: } else {
0699: for (Iterator i = getMergers().iterator(); i.hasNext();) {
0700: DPProperties dpp = (DPProperties) i.next();
0701: DPLocale dplc = ((XMLDPProperties) dpp)
0702: .getLocaleFromThis(language, country,
0703: variant, true);
0704:
0705: if (dplc != null) {
0706: if (dpLocale == null) {
0707: DPLocale ddpl = (DPLocale) ((XMLDPLocale) dplc)
0708: .createDummy(getRoot());
0709: dpLocale = (DPLocale) add(ddpl, false,
0710: false, true);
0711: if (!dplc.isLocked() && dpLocale.isDummy()
0712: && this .isReplace()) {
0713: replace = true;
0714: }
0715: }
0716:
0717: if (!dpLocale.isMergeLocked()) {
0718: if (dplc.isLocked() && dplc.isRemove()) {
0719: dpLocale = null;
0720: break;
0721: }
0722: }
0723:
0724: dpLocale.addMerger(dplc);
0725: }
0726:
0727: }
0728:
0729: if (dpLocale != null) {
0730: if (!dpLocale.isMergeLocked()
0731: && dpLocale.isRemove()) {
0732: dpLocale = null;
0733: }
0734: }
0735: }
0736:
0737: if (exact) {
0738: language = null;
0739: } else if (variant != null) {
0740: variant = null;
0741: } else if (country != null) {
0742: country = null;
0743: } else if (language != null) {
0744: language = null;
0745: }
0746: }
0747:
0748: if (replace) {
0749: dpLocale = null;
0750: }
0751:
0752: return dpLocale;
0753: }
0754:
0755: /**
0756: * Remove once <Locale> support is no longer needed.
0757: */
0758: protected DPLocale getLocaleFromThis(String language,
0759: String country, String variant, boolean exact) {
0760: Element e = getLocaleElement(language, country, variant, exact);
0761: DPLocale dpl = null;
0762:
0763: if (e != null) {
0764: dpl = (DPLocale) getObject(e);
0765: if (dpl == null) {
0766: dpl = new XMLDPLocale(getContext(), getRoot(), e);
0767: putObject(dpl);
0768: }
0769: }
0770:
0771: return dpl;
0772: }
0773:
0774: /**
0775: * Remove once <Locale> support is no longer needed.
0776: */
0777: Element getLocaleElement(String language, String country,
0778: String variant, boolean exact) {
0779: Element localeElement = null;
0780:
0781: //
0782: // try <lang>_<country>_<variant>
0783: //
0784: localeElement = getLocaleElement(language, country, variant);
0785: if (localeElement != null) {
0786: return localeElement;
0787: }
0788:
0789: //
0790: // if we're exact matching, then don't search less-specific
0791: // locales
0792: //
0793: if (exact) {
0794: return localeElement;
0795: }
0796:
0797: //
0798: // try with <lang>_<country>, if variant was non-null
0799: //
0800: if ((variant != null) && (variant.length() > 0)) {
0801: localeElement = getLocaleElement(language, country, null);
0802: if (localeElement != null) {
0803: return localeElement;
0804: }
0805: }
0806:
0807: //
0808: // try with <lang>, if country was non-null
0809: //
0810: if ((country != null) && (country.length() > 0)) {
0811: localeElement = getLocaleElement(language, null, null);
0812: if (localeElement != null) {
0813: return localeElement;
0814: }
0815: }
0816:
0817: return null;
0818: }
0819:
0820: static boolean isEmptyString(String s) {
0821: if (s == null || s.length() == 0) {
0822: return true;
0823: }
0824:
0825: return false;
0826: }
0827:
0828: /**
0829: * Remove once <Locale> support is no longer needed.
0830: */
0831: Element getLocaleElement(String language, String country,
0832: String variant) {
0833: String localeName = getLocaleName(language, country, variant);
0834: Element localeElement = (Element) propertiesTable
0835: .get(localeName);
0836:
0837: return localeElement;
0838: }
0839:
0840: public Set getNames() {
0841: return getNames(true);
0842: }
0843:
0844: public Set getNames(boolean scoped) {
0845: //
0846: // TBD(jtb): get the names from the mergers as well
0847: //
0848:
0849: //
0850: // first get names from me
0851: //
0852: Set names = super .getNames();
0853:
0854: //
0855: // when not scoped, just return names from me
0856: //
0857: if (!scoped) {
0858: return names;
0859: }
0860:
0861: //
0862: // now get names provider, if my parent is a channel that is, neato!
0863: //
0864: DPPropertyHolder dpph = getPropertyHolder();
0865: if (!(dpph instanceof DPChannel)) {
0866: /*
0867: message(
0868: "XMLDPProperties.getNames():owner not a channel, returning names"
0869: );
0870: */
0871: return names;
0872: }
0873: /*
0874: message(
0875: "XMLDPProperties.getNames():owner was a channel, getting provider"
0876: );
0877: */
0878: DPChannel dpc = (DPChannel) dpph;
0879:
0880: DPProvider dpp = dpc.getProvider();
0881: if (dpp != null) {
0882: Set providerNames = dpp.getProperties().getNames();
0883:
0884: if (providerNames != null) {
0885: names.addAll(providerNames);
0886: }
0887: }
0888:
0889: //
0890: // now, get the names from my parent
0891: //
0892: DPPropertyHolder owner = getPropertyHolder();
0893: if (owner == null) {
0894: throw new DPError(
0895: "XMLDPProperties.getNames(): no owner for properties");
0896: }
0897: DPPropertyHolder ownerParent = owner.getParentPropertyHolder();
0898: if (ownerParent == null) {
0899: return names;
0900: }
0901: //
0902: // this call is recursive!
0903: //
0904: Set ownerNames = ownerParent.getProperties().getNames();
0905: if (ownerNames != null) {
0906: names.addAll(ownerNames);
0907: }
0908:
0909: return names;
0910: }
0911:
0912: public DPString getString(String key, List pflist, boolean exact) {
0913: DPProperty dpp = get(key, pflist, exact);
0914: if (dpp == null) {
0915: return null;
0916: }
0917: if (dpp.getType() != STRING_DP) {
0918: return null;
0919: }
0920:
0921: return (DPString) dpp;
0922: }
0923:
0924: public DPString getString(String key) {
0925: return getString(key, null, true);
0926: }
0927:
0928: public void setString(String key, String val) {
0929: setString(key, val, null, false);
0930: }
0931:
0932: boolean isPropertyFromThis(DPProperty dpp) {
0933: DPProperties dppp = dpp.getProperties();
0934: if (dppp == this ) {
0935: return true;
0936: }
0937: return false;
0938: }
0939:
0940: public void setString(String key, String val, List pflist) {
0941: setString(key, val, pflist, false);
0942: }
0943:
0944: public void setString(String key, String val, List pflist,
0945: boolean exact) {
0946: //check if property exists anywhere
0947: DPString oldString = getString(key, pflist, false);
0948: if (oldString == null) {
0949: // property does not exist, throw an error
0950: throw new DPError(
0951: "XMLDPProperties.setString(): property does not exist name="
0952: + key);
0953: }
0954: DPString newString = null;
0955: if (!oldString.isPropagate()) {
0956: newString = oldString;
0957: newString.setPropagate(false);
0958: newString.setStringValue(val);
0959: } else {
0960: //property set to closest match
0961: if (!exact) {
0962: if (!isPropertyFromThis(oldString)) {
0963: // property is not local, add to this
0964: DPProperties dpp = oldString.getProperties();
0965: List pflistMatched = ((XMLDPProperties) dpp)
0966: .getMatchedPropertiesFilters(key, pflist);
0967: newString = (DPString) add(oldString, pflistMatched);
0968: } else {
0969: // property is local, just set to new value
0970: newString = oldString;
0971: }
0972: newString.setStringValue(val);
0973: //property set to exact match
0974: } else {
0975: //check if this is an exact match
0976: newString = getString(key, pflist, true);
0977: if (newString != null) {
0978: if (!isPropertyFromThis(newString)) { // do we need to propagate?
0979: newString = (DPString) add(newString, pflist); // propagate
0980: }
0981: newString.setStringValue(val);
0982: } else {
0983: DPProperty property = (DPString) createProperty(
0984: key, new String(val));
0985: newString = (DPString) add(property, pflist);
0986: }
0987: }
0988: }
0989: return;
0990: }
0991:
0992: public DPInteger getInteger(String key) {
0993: return getInteger(key, null, true);
0994: }
0995:
0996: public DPInteger getInteger(String key, List pflist, boolean exact) {
0997: DPProperty dpp = get(key, pflist, exact);
0998: if (dpp == null) {
0999: return null;
1000: }
1001: if (dpp.getType() != INTEGER_DP) {
1002: return null;
1003: }
1004:
1005: return (DPInteger) dpp;
1006: }
1007:
1008: public void setInteger(String key, int val) {
1009: setInteger(key, val, null);
1010: }
1011:
1012: public void setInteger(String key, int val, List pflist) {
1013: setInteger(key, val, pflist, false);
1014: }
1015:
1016: public void setInteger(String key, int val, List pflist,
1017: boolean exact) {
1018: //check if property exists anywhere
1019: DPInteger oldInteger = getInteger(key, pflist, false);
1020: if (oldInteger == null) {
1021: // property does not exist, throw an error
1022: throw new DPError(
1023: "XMLDPProperties.setInteger(): property does not exist name="
1024: + key);
1025: }
1026: DPInteger newInteger = null;
1027: if (!oldInteger.isPropagate()) {
1028: newInteger = oldInteger;
1029: newInteger.setPropagate(false);
1030: newInteger.setIntValue(val);
1031: } else {
1032: //property set to closest match
1033: if (!exact) {
1034: if (!isPropertyFromThis(oldInteger)) {
1035: // property is not local, add to this
1036: DPProperties dpp = oldInteger.getProperties();
1037: List pflistMatched = ((XMLDPProperties) dpp)
1038: .getMatchedPropertiesFilters(key, pflist);
1039: newInteger = (DPInteger) add(oldInteger,
1040: pflistMatched);
1041: } else {
1042: // property is local, just set to new value
1043: newInteger = oldInteger;
1044: }
1045: newInteger.setIntValue(val);
1046: //property set to exact match
1047: } else {
1048: //check if this is an exact match
1049: newInteger = getInteger(key, pflist, true);
1050: if (newInteger != null) {
1051: if (!isPropertyFromThis(newInteger)) { // do we need to propagate?
1052: newInteger = (DPInteger) add(newInteger, pflist); // propagate
1053: }
1054: newInteger.setIntValue(val);
1055: } else {
1056: DPProperty property = (DPInteger) createProperty(
1057: key, new Integer(val));
1058: newInteger = (DPInteger) add(property, pflist);
1059: }
1060: }
1061: }
1062: return;
1063: }
1064:
1065: public DPBoolean getBoolean(String key) {
1066: return getBoolean(key, null, true);
1067: }
1068:
1069: public DPBoolean getBoolean(String key, List pflist, boolean exact) {
1070: DPProperty dpp = get(key, pflist, exact);
1071: if (dpp == null) {
1072: return null;
1073: }
1074: if (dpp.getType() != BOOLEAN_DP) {
1075: return null;
1076: }
1077:
1078: return (DPBoolean) dpp;
1079: }
1080:
1081: public void setBoolean(String key, boolean val) {
1082: setBoolean(key, val, null);
1083: }
1084:
1085: public void setBoolean(String key, boolean val, List pflist) {
1086: setBoolean(key, val, pflist, false);
1087: }
1088:
1089: public void setBoolean(String key, boolean val, List pflist,
1090: boolean exact) {
1091: //check if property exists anywhere
1092: DPBoolean oldBoolean = getBoolean(key, pflist, false);
1093: if (oldBoolean == null) {
1094: // property does not exist, throw an error
1095: throw new DPError(
1096: "XMLDPProperties.setBoolean(): property does not exist name="
1097: + key);
1098: }
1099: DPBoolean newBoolean = null;
1100: if (!oldBoolean.isPropagate()) {
1101: newBoolean = oldBoolean;
1102: newBoolean.setPropagate(false);
1103: newBoolean.setBooleanValue(val);
1104: } else {
1105: //property set to closest match
1106: if (!exact) {
1107: if (!isPropertyFromThis(oldBoolean)) {
1108: // property is not local, add to this
1109: DPProperties dpp = oldBoolean.getProperties();
1110: List pflistMatched = ((XMLDPProperties) dpp)
1111: .getMatchedPropertiesFilters(key, pflist);
1112: newBoolean = (DPBoolean) add(oldBoolean,
1113: pflistMatched);
1114: } else {
1115: // property is local, just set to new value
1116: newBoolean = oldBoolean;
1117: }
1118: newBoolean.setBooleanValue(val);
1119: //property set to exact match
1120: } else {
1121: //check if this is an exact match
1122: newBoolean = getBoolean(key, pflist, true);
1123: if (newBoolean != null) {
1124: if (!isPropertyFromThis(newBoolean)) { // do we need to propagate?
1125: newBoolean = (DPBoolean) add(newBoolean, pflist); // propagate
1126: }
1127: newBoolean.setBooleanValue(val);
1128: } else {
1129: DPProperty property = (DPBoolean) createProperty(
1130: key, new Boolean(val));
1131: newBoolean = (DPBoolean) add(property, pflist);
1132: }
1133: }
1134: }
1135: return;
1136: }
1137:
1138: public DPCollection getCollection(String key) {
1139: return getCollection(key, null, true);
1140: }
1141:
1142: public DPCollection getCollection(String key, List pflist,
1143: boolean exact) {
1144: DPProperty dpp = get(key, pflist, exact);
1145: if (dpp == null) {
1146: return null;
1147: }
1148: if (dpp.getType() != COLLECTION_DP) {
1149: return null;
1150: }
1151:
1152: return (DPCollection) dpp;
1153: }
1154:
1155: public DPCollection setCollection(String key, Map val) {
1156: return setCollection(key, val, null);
1157: }
1158:
1159: public DPCollection setCollection(String key, Map val, List pflist) {
1160: return setCollection(key, val, pflist, false);
1161: }
1162:
1163: public DPCollection setCollection(String key, Map val, List pflist,
1164: boolean exact) {
1165: //check if property exists anywhere
1166: DPCollection oldCollection = getCollection(key, pflist, false);
1167: if (oldCollection == null) {
1168: // property does not exist, throw an error
1169: throw new DPError(
1170: "XMLDPProperties.setCollection(): property does not exist name="
1171: + key);
1172: }
1173: DPCollection newCollection = null;
1174: if (!oldCollection.isPropagate()) {
1175: newCollection = oldCollection;
1176: newCollection.setPropagate(false);
1177: newCollection.setCollectionValue(val);
1178: } else {
1179: //property set to closest match
1180: if (!exact) {
1181: if (!isPropertyFromThis(oldCollection)) {
1182: // property is not local, add to this
1183: DPProperties dpp = oldCollection.getProperties();
1184: List pflistMatched = ((XMLDPProperties) dpp)
1185: .getMatchedPropertiesFilters(key, pflist);
1186: add(oldCollection, true, false, false,
1187: pflistMatched);
1188: // get merged copy
1189: newCollection = getCollection(key, pflist, false);
1190: } else {
1191: // property is local, just set to new value
1192: newCollection = oldCollection;
1193: }
1194: newCollection.setCollectionValue(val);
1195: //property set to exact match
1196: } else {
1197: //check if this is an exact match
1198: newCollection = getCollection(key, pflist, true);
1199: if (newCollection != null) {
1200: if (!isPropertyFromThis(newCollection)) { // do we need to propagate?
1201: newCollection = (DPCollection) add(
1202: newCollection, pflist); // propagate
1203: }
1204: newCollection.setCollectionValue(val);
1205: } else {
1206: DPProperty property = (DPCollection) createProperty(
1207: key, val);
1208: newCollection = (DPCollection) add(property, pflist);
1209: }
1210: }
1211: }
1212: return newCollection;
1213: }
1214:
1215: public DPCollection setCollection(String key, List val) {
1216: return setCollection(key, val, null);
1217: }
1218:
1219: public DPCollection setCollection(String key, List val, List pflist) {
1220: return setCollection(key, val, pflist, false);
1221: }
1222:
1223: public DPCollection setCollection(String key, List val,
1224: List pflist, boolean exact) {
1225: //check if property exists anywhere
1226: DPCollection oldCollection = getCollection(key, pflist, false);
1227: if (oldCollection == null) {
1228: // property does not exist, throw an error
1229: throw new DPError(
1230: "XMLDPProperties.setCollection(): property does not exist name="
1231: + key);
1232: }
1233: DPCollection newCollection = null;
1234: if (!oldCollection.isPropagate()) {
1235: newCollection = oldCollection;
1236: newCollection.setPropagate(false);
1237: newCollection.setCollectionValue(val);
1238: } else {
1239: //property set to closest match
1240: if (!exact) {
1241: if (!isPropertyFromThis(oldCollection)) {
1242: // property is not local, add to this
1243: DPProperties dpp = oldCollection.getProperties();
1244: List pflistMatched = ((XMLDPProperties) dpp)
1245: .getMatchedPropertiesFilters(key, pflist);
1246: add(oldCollection, true, false, false,
1247: pflistMatched);
1248: // get merged copy
1249: newCollection = getCollection(key, pflist, false);
1250: } else {
1251: // property is local, just set to new value
1252: newCollection = oldCollection;
1253: }
1254: newCollection.setCollectionValue(val);
1255: //property set to exact match
1256: } else {
1257: //check if this is an exact match
1258: newCollection = getCollection(key, pflist, true);
1259: if (newCollection != null) {
1260: if (!isPropertyFromThis(newCollection)) { // do we need to propagate?
1261: newCollection = (DPCollection) add(
1262: newCollection, pflist); // propagate
1263: }
1264: newCollection.setCollectionValue(val);
1265: } else {
1266: DPProperty property = (DPCollection) createProperty(
1267: key, val);
1268: newCollection = (DPCollection) add(property, pflist);
1269: }
1270: }
1271: }
1272: return newCollection;
1273: }
1274:
1275: protected Element getMergedElement() {
1276: Map map = getCollectionValue();
1277: Element e = createElement(getContext(), getRoot(),
1278: getDocument(), map);
1279:
1280: return e;
1281: }
1282:
1283: static Element createElement(DPContext dpc, Document d) {
1284: Element e = XMLDPObject.createElement(dpc, d, PROPERTIES_TAG);
1285: setDefaultsElement(e);
1286:
1287: return e;
1288: }
1289:
1290: private static Element createElement(DPContext dpc, DPRoot r,
1291: Document d, Map m) {
1292: Element e = createElement(dpc, d);
1293:
1294: XMLDPFactory factory = XMLDPFactory.getInstance();
1295: for (Iterator i = m.keySet().iterator(); i.hasNext();) {
1296: String name = (String) i.next();
1297: Object o = m.get(name);
1298: Element newElement = null;
1299: if (isConditionalPropertiesName(name)) {
1300: Iterator j = parseConditionalPropertiesName(name)
1301: .iterator();
1302: String condition = (String) j.next();
1303: String conditionValue = (String) j.next();
1304: DPConditionalProperties dptp = factory
1305: .createConditionalProperties(dpc, r, d,
1306: condition, conditionValue, (Map) o);
1307: XMLDPConditionalProperties xmlDPTP = (XMLDPConditionalProperties) dptp;
1308: newElement = xmlDPTP.getElement();
1309: } else if (isLocaleName(name)) {
1310: Iterator j = parseLocaleName(name).iterator();
1311: String lang = (String) j.next();
1312: String country = (String) j.next();
1313: String variant = (String) j.next();
1314: DPLocale dpl = factory.createLocale(dpc, r, d, lang,
1315: country, variant, (Map) o);
1316: XMLDPLocale xmlDPL = (XMLDPLocale) dpl;
1317: newElement = xmlDPL.getElement();
1318: } else {
1319: DPProperty dpp = XMLDPFactory.getInstance()
1320: .createProperty(dpc, r, d, name, o);
1321: XMLDPProperty xmlDPP = (XMLDPProperty) dpp;
1322: newElement = xmlDPP.getElement();
1323: }
1324: e.appendChild(newElement);
1325: }
1326:
1327: setDefaultsElement(e);
1328:
1329: return e;
1330: }
1331:
1332: public void toXML(StringBuffer b, int indent) {
1333:
1334: if (isDummy()) {
1335: return;
1336: }
1337: indentBuffer(b, indent);
1338:
1339: appendStartTag(b);
1340:
1341: appendMergeAttr(b);
1342: appendLockAttr(b);
1343: appendAdvancedAttr(b);
1344: appendPropagateAttr(b);
1345:
1346: b.append(">\n");
1347: appendChildProperty(b, indent);
1348: indentBuffer(b, indent);
1349:
1350: appendEndTag(b);
1351: }
1352:
1353: public DPProperty remove(String key, List pflist) {
1354: if (pflist == null || pflist.size() == 0) {
1355: return remove(key);
1356: }
1357: PropertiesFilter pf = (PropertiesFilter) pflist.get(0);
1358: String condition = null;
1359: String conditionValue = null;
1360: try {
1361: condition = pf.getCondition();
1362: conditionValue = pf.getValue();
1363: } catch (PropertiesFilterException pfe) {
1364: throw new DPError(
1365: "XMLDPProperties.add(): cannot access pf=" + pf,
1366: pfe);
1367: }
1368: DPConditionalProperties dptp = getConditionalPropertiesFromThis(
1369: condition, conditionValue);
1370: if (dptp != null) {
1371: return ((XMLDPConditionalProperties) dptp).remove(key,
1372: pflist.subList(1, pflist.size()));
1373: }
1374: return dptp;
1375: }
1376:
1377: }
1378:
1379: class RankedDPProperty {
1380: DPProperty dpProperty = null;
1381: int rank = 0;
1382:
1383: RankedDPProperty() {
1384: }
1385:
1386: RankedDPProperty(DPProperty dpProperty, int rank) {
1387: this.dpProperty = dpProperty;
1388: this.rank = rank;
1389: }
1390: }
|