0001: /*
0002: * $RCSfile: DescriptorCache.java,v $
0003: *
0004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * Use is subject to license terms.
0007: *
0008: * $Revision: 1.1 $
0009: * $Date: 2005/02/11 04:57:07 $
0010: * $State: Exp $
0011: */
0012: package javax.media.jai;
0013:
0014: import java.text.MessageFormat;
0015: import java.util.ArrayList;
0016: import java.util.Enumeration;
0017: import java.util.Hashtable;
0018: import java.util.Iterator;
0019: import java.util.List;
0020: import java.util.Locale;
0021: import java.util.Vector;
0022: import javax.media.jai.util.CaselessStringKey;
0023:
0024: /**
0025: * A class to manage the descriptors belong to a certain
0026: * <code>RegistryMode</code>
0027: *
0028: * The <code>RegistryElementDescriptor</code> names are used in a
0029: * case-insensitive manner.
0030: */
0031: class DescriptorCache {
0032:
0033: /**
0034: * The name of the mode for which the cache of descriptors is
0035: * being maintained.
0036: */
0037: final String modeName;
0038:
0039: /**
0040: * Cache the RegistryMode since it is bound to get used
0041: * many, many times.
0042: */
0043: final RegistryMode mode;
0044:
0045: /** Does the registry mode for this cache support preferences. */
0046: final boolean arePreferencesSupported;
0047:
0048: /** Does the registry mode for this cache support properties. */
0049: final boolean arePropertiesSupported;
0050:
0051: /**
0052: * A Hashtable of all the <code>RegistryElementDescriptor</code>s,
0053: * hashed by their name.
0054: */
0055: private Hashtable descriptorNames;
0056:
0057: /**
0058: * A Hashtable of all the products, hashed by the
0059: * name of the <code>RegistryElementDescriptor</code> to which they belong.
0060: */
0061: private Hashtable products;
0062:
0063: /**
0064: * A Hashtable of all the product preferences, hashed by the
0065: * descriptor name that the products belong to. The product
0066: * preferences are stored in a <code>Vector</code>. The elements
0067: * of the <code>Vector</code> consist of <code>String[2]</code>
0068: * objects, each storing the preferred product's name, and the other
0069: * product's name within it.
0070: */
0071: private Hashtable productPrefs;
0072:
0073: //
0074: // Property related tables...
0075: //
0076:
0077: /**
0078: * A Hashtable of <code>Vector</code>s containing all the
0079: * <code>PropertyGenerator</code>s, hashed by the descriptor
0080: * name that the <code>PropertyGenerator</code>s belong to.
0081: */
0082: private Hashtable properties;
0083:
0084: /**
0085: * A Hashtable of <code>Vector</code>s containing the names
0086: * of all the properties to be suppressed, hashed by the descriptor
0087: * name whose properties are to be suppressed.
0088: */
0089: private Hashtable suppressed;
0090:
0091: /**
0092: * A Hashtable containing information about which source a property
0093: * should be copied from, hashed by the descriptor name to which the
0094: * property belongs. The information about which source a property
0095: * should be copied from is stored in a Hashtable containing the
0096: * index of the source, hashed by the property name.
0097: */
0098: private Hashtable sourceForProp;
0099:
0100: /**
0101: * A Hashtable that stores the <code>PropertySource</code>s for all
0102: * the properties, hashed by the descriptor name that the properties
0103: * belong to. The <code>PropertySource</code>s are stored in a
0104: * Hashtable, hashed by the name of the property.
0105: */
0106: private Hashtable propNames;
0107:
0108: /**
0109: * The Constructor. Create a <code>RegistryElementDescriptor</code>
0110: * cache for maintaining descriptors for the specified mode.
0111: *
0112: * @param modeName the registry mode name.
0113: *
0114: */
0115: DescriptorCache(String modeName) {
0116:
0117: this .modeName = modeName;
0118: this .mode = RegistryMode.getMode(modeName);
0119:
0120: arePreferencesSupported = mode.arePreferencesSupported();
0121: arePropertiesSupported = mode.arePropertiesSupported();
0122:
0123: descriptorNames = new Hashtable();
0124: products = new Hashtable();
0125:
0126: if (arePreferencesSupported)
0127: productPrefs = new Hashtable();
0128:
0129: // Property related tables.
0130: properties = new Hashtable();
0131: suppressed = new Hashtable();
0132: sourceForProp = new Hashtable();
0133: propNames = new Hashtable();
0134: }
0135:
0136: /**
0137: * Adds a <code>RegistryElementDescriptor</code> to the cache.
0138: *
0139: * <p> An <code>RegistryElementDescriptor</code> cannot be added against a
0140: * descriptor name under which another <code>RegistryElementDescriptor</code>
0141: * was added previously.
0142: *
0143: * @param rdesc an <code>RegistryElementDescriptor</code> containing
0144: * information about the descriptor.
0145: *
0146: * @return false, if one already existed. true otherwise.
0147: *
0148: * @throws IllegalArgumentException is rdesc in null
0149: * @throws IllegalArgumentException if the descriptor has
0150: * already been registered in this cache.
0151: */
0152: boolean addDescriptor(RegistryElementDescriptor rdesc) {
0153:
0154: if (rdesc == null) {
0155: throw new IllegalArgumentException(JaiI18N
0156: .getString("Generic0"));
0157: }
0158:
0159: String descriptorName = rdesc.getName();
0160:
0161: // Use a caseless version of the key.
0162: CaselessStringKey key = new CaselessStringKey(descriptorName);
0163:
0164: // If the key has already been added bail out ...
0165: if (descriptorNames.containsKey(key) == true) {
0166: throw new IllegalArgumentException(JaiI18N.formatMsg(
0167: "DescriptorCache0", new Object[] { descriptorName,
0168: modeName }));
0169: }
0170:
0171: // Store the RegistryElementDescriptor hashed by its global name
0172: descriptorNames.put(key, rdesc);
0173:
0174: // Store the ProductOperationGraph hashed by the caseless
0175: // descriptor name
0176: if (arePreferencesSupported)
0177: products.put(key, new ProductOperationGraph());
0178:
0179: // if properties arent supported by this descriptor we are done.
0180: if (rdesc.arePropertiesSupported() == false)
0181: return true;
0182:
0183: // Store the Property Generators associated with this descriptor
0184: // for the specified mode.
0185: PropertyGenerator props[] = rdesc
0186: .getPropertyGenerators(modeName);
0187:
0188: if (props != null) {
0189: for (int i = 0; i < props.length; i++) {
0190:
0191: Vector v = (Vector) properties.get(key);
0192: if (v == null) {
0193: v = new Vector();
0194: v.addElement(props[i]);
0195: properties.put(key, v);
0196: } else {
0197: v.addElement(props[i]);
0198: }
0199:
0200: v = (Vector) suppressed.get(key);
0201: Hashtable h = (Hashtable) sourceForProp.get(key);
0202: String names[] = props[i].getPropertyNames();
0203:
0204: for (int j = 0; j < names.length; j++) {
0205: CaselessStringKey name = new CaselessStringKey(
0206: names[j]);
0207:
0208: if (v != null)
0209: v.remove(name);
0210: if (h != null)
0211: h.remove(name);
0212: }
0213: }
0214: }
0215:
0216: return true;
0217: }
0218:
0219: /**
0220: * Removes a <code>RegistryElementDescriptor</code> from the cache.
0221: *
0222: * @param descriptorName the descriptor name as a String.
0223: *
0224: * @return false, if one wasnt previously registered, true otherwise.
0225: *
0226: * @throws IllegalArgumentException if descriptorName is null or
0227: * was not previously registered.
0228: * @throws IllegalArgumentException if any of the
0229: * <code>PropertyGenerator</code>s associated with the
0230: * <code>RegistryElementDescriptor</code> to be removed is null.
0231: */
0232: boolean removeDescriptor(String descriptorName) {
0233:
0234: // Use a caseless version of the key.
0235: CaselessStringKey key = new CaselessStringKey(descriptorName);
0236:
0237: // If it is not present in the cache already, then return false.
0238: if (descriptorNames.containsKey(key) == false) {
0239: throw new IllegalArgumentException(JaiI18N.formatMsg(
0240: "DescriptorCache1", new Object[] { descriptorName,
0241: modeName }));
0242: }
0243:
0244: RegistryElementDescriptor rdesc = (RegistryElementDescriptor) descriptorNames
0245: .get(key);
0246:
0247: PropertyGenerator props[] = null;
0248:
0249: // if properties arent supported by this descriptor we are done.
0250: if (rdesc.arePropertiesSupported() == true)
0251: props = rdesc.getPropertyGenerators(modeName);
0252:
0253: // Remove the Property Generators associated with this descriptor
0254: if (props != null) {
0255: for (int i = 0; i < props.length; i++) {
0256:
0257: if (props[i] == null) {
0258: throw new IllegalArgumentException(JaiI18N
0259: .formatMsg("DescriptorCache2",
0260: new Object[] { new Integer(i),
0261: descriptorName, modeName }));
0262: }
0263:
0264: Vector v = (Vector) properties.get(key);
0265: if (v != null) {
0266: v.removeElement(props[i]);
0267: }
0268: }
0269: }
0270:
0271: // Remove the RegistryElementDescriptor hashed by its global name
0272: descriptorNames.remove(key);
0273:
0274: if (arePreferencesSupported)
0275: products.remove(key);
0276:
0277: return true;
0278: }
0279:
0280: /**
0281: * Removes a <code>RegistryElementDescriptor</code> from the cache.
0282: *
0283: * @param rdesc an <code>RegistryElementDescriptor</code> to be removed.
0284: *
0285: * @return false, if one wasnt previously registered, true otherwise.
0286: *
0287: * @throws IllegalArgumentException if rdesc is null.
0288: * @throws IllegalArgumentException if rdesc was not
0289: * previously registered.
0290: * @throws IllegalArgumentException if any of the
0291: * <code>PropertyGenerator</code>s associated with the
0292: * <code>RegistryElementDescriptor</code> to be removed is null.
0293: */
0294: boolean removeDescriptor(RegistryElementDescriptor rdesc) {
0295: if (rdesc == null) {
0296: throw new IllegalArgumentException(JaiI18N
0297: .getString("Generic0"));
0298: }
0299: return removeDescriptor(rdesc.getName());
0300: }
0301:
0302: /**
0303: * Returns the <code>RegistryElementDescriptor</code> that is
0304: * currently registered under the given name, or null if none
0305: * exists.
0306: *
0307: * @param descriptorName the String to be queried.
0308: *
0309: * @return an <code>RegistryElementDescriptor</code>.
0310: *
0311: * @throws IllegalArgumentException if descriptorName is null
0312: */
0313: RegistryElementDescriptor getDescriptor(String descriptorName) {
0314: // Use a caseless version of the key.
0315: CaselessStringKey key = new CaselessStringKey(descriptorName);
0316:
0317: return (RegistryElementDescriptor) descriptorNames.get(key);
0318: }
0319:
0320: /**
0321: * Returns a <code>List</code> of all currently registered
0322: * <code>RegistryElementDescriptor</code>s.
0323: *
0324: * @return a List of <code>RegistryElementDescriptor</code>s.
0325: */
0326: List getDescriptors() {
0327:
0328: ArrayList list = new ArrayList();
0329:
0330: for (Enumeration en = descriptorNames.elements(); en
0331: .hasMoreElements();) {
0332: list.add(en.nextElement());
0333: }
0334:
0335: return list;
0336: }
0337:
0338: /**
0339: * Returns a list of names under which all the
0340: * <code>RegistryElementDescriptor</code>s in the registry are registered.
0341: *
0342: * @return a list of currently existing descriptor names.
0343: */
0344: String[] getDescriptorNames() {
0345:
0346: Enumeration e = descriptorNames.keys();
0347: int size = descriptorNames.size();
0348: String names[] = new String[size];
0349:
0350: for (int i = 0; i < size; i++) {
0351: CaselessStringKey key = (CaselessStringKey) e.nextElement();
0352: names[i] = key.getName();
0353: }
0354:
0355: return names;
0356: }
0357:
0358: /**
0359: * Registers a product name against a descriptor. The descriptor
0360: * must already exist in the cache. If the product already existed
0361: * under the descriptor, the old one is returned without adding
0362: * another.
0363: *
0364: * @param descriptorName the descriptor name as a String
0365: * @param productName the product name as a String.
0366: *
0367: * @return null, if the descriptor or the product did not exist or the product
0368: *
0369: * @throws IllegalArgumentException if descriptorName is null
0370: */
0371: OperationGraph addProduct(String descriptorName, String productName) {
0372: // Use a caseless version of the key.
0373: CaselessStringKey key = new CaselessStringKey(descriptorName);
0374:
0375: if (productName == null)
0376: throw new IllegalArgumentException(JaiI18N
0377: .getString("Generic0"));
0378:
0379: ProductOperationGraph pog = (ProductOperationGraph) products
0380: .get(key);
0381:
0382: if (pog == null)
0383: return null;
0384:
0385: PartialOrderNode pon = pog.lookupOp(productName);
0386:
0387: if (pon == null) {
0388: pog.addProduct(productName);
0389:
0390: pon = pog.lookupOp(productName);
0391: }
0392:
0393: return (OperationGraph) pon.getData();
0394: }
0395:
0396: /**
0397: * Unregisters a product name against a descriptor. The
0398: * descriptor must already exist in the cache and the procduct
0399: * must have been registered against the descriptor
0400: *
0401: * @param descriptorName the descriptor name as a String
0402: * @param productName the product name as a String.
0403: *
0404: * @return false, if the descriptor did not exist or the product
0405: * was not already registered.
0406: *
0407: * @throws IllegalArgumentException if descriptorName is null
0408: */
0409: boolean removeProduct(String descriptorName, String productName) {
0410: // Use a caseless version of the key.
0411: CaselessStringKey key = new CaselessStringKey(descriptorName);
0412:
0413: if (productName == null)
0414: throw new IllegalArgumentException(JaiI18N
0415: .getString("Generic0"));
0416:
0417: ProductOperationGraph pog = (ProductOperationGraph) products
0418: .get(key);
0419:
0420: if (pog == null)
0421: return false;
0422:
0423: PartialOrderNode pon = pog.lookupOp(productName);
0424:
0425: if (pon == null)
0426: return false;
0427:
0428: pog.removeOp(productName);
0429:
0430: return true;
0431: }
0432:
0433: /**
0434: * Looks up a product name against a descriptor.
0435: *
0436: * @param descriptorName the descriptor name as a String
0437: * @param productName the product name as a String.
0438: *
0439: * @return null, if the descriptor did not exist or the product
0440: * was not already registered. Otherwise returns the
0441: * <code>PartialOrderNode</code> corresponding to this product
0442: *
0443: * @throws IllegalArgumentException if descriptorName is null
0444: */
0445: OperationGraph lookupProduct(String descriptorName,
0446: String productName) {
0447: // Use a caseless version of the key.
0448: CaselessStringKey key = new CaselessStringKey(descriptorName);
0449:
0450: if (productName == null)
0451: throw new IllegalArgumentException(JaiI18N
0452: .getString("Generic0"));
0453:
0454: ProductOperationGraph pog = (ProductOperationGraph) products
0455: .get(key);
0456:
0457: if (pog == null)
0458: return null;
0459:
0460: PartialOrderNode pon = pog.lookupOp(productName);
0461:
0462: if (pon == null)
0463: return null;
0464:
0465: return (OperationGraph) pon.getData();
0466: }
0467:
0468: /**
0469: * Sets a preference between two products registered under
0470: * a common <code>RegistryElementDescriptor</code>.
0471: * if the descriptor was not registered previously and no preference
0472: * will be set. Any attempt to set a preference between a product
0473: * and itself will be ignored.
0474: *
0475: * @param descriptorName the operation name as a String.
0476: * @param preferredProductName the product to be preferred.
0477: * @param otherProductName the other product.
0478: *
0479: * @return false, if the descriptor was not registered previously
0480: * or if either if the products were not already
0481: * added against the descriptor.
0482: *
0483: * @throws IllegalArgumentException if this registry mode does
0484: * not support preferences.
0485: * @throws IllegalArgumentException if any of the args is null
0486: * @throws IllegalArgumentException if descriptorName or either of
0487: * the products were not previously registered.
0488: */
0489: boolean setProductPreference(String descriptorName,
0490: String preferredProductName, String otherProductName) {
0491:
0492: if (!arePreferencesSupported) {
0493: throw new IllegalArgumentException(JaiI18N.formatMsg(
0494: "DescriptorCache6", new Object[] { modeName }));
0495: }
0496:
0497: if ((descriptorName == null) || (preferredProductName == null)
0498: || (otherProductName == null))
0499: throw new IllegalArgumentException(JaiI18N
0500: .getString("Generic0"));
0501:
0502: // Attempt to set preference of a product with itself, do nothing.
0503: if (preferredProductName.equalsIgnoreCase(otherProductName)) {
0504: return false;
0505: }
0506:
0507: // Use a caseless version of the key.
0508: CaselessStringKey key = new CaselessStringKey(descriptorName);
0509:
0510: if (descriptorNames.containsKey(key) == false) {
0511: throw new IllegalArgumentException(JaiI18N.formatMsg(
0512: "DescriptorCache1", new Object[] { descriptorName,
0513: modeName }));
0514: }
0515:
0516: ProductOperationGraph og = (ProductOperationGraph) products
0517: .get(key);
0518:
0519: if (og == null) {
0520: throw new IllegalArgumentException(JaiI18N.formatMsg(
0521: "DescriptorCache3", new Object[] { descriptorName,
0522: modeName }));
0523: }
0524:
0525: if (og.lookupOp(preferredProductName) == null) {
0526: throw new IllegalArgumentException(JaiI18N.formatMsg(
0527: "DescriptorCache4", new Object[] { descriptorName,
0528: modeName, preferredProductName }));
0529: }
0530:
0531: if (og.lookupOp(otherProductName) == null) {
0532: throw new IllegalArgumentException(JaiI18N.formatMsg(
0533: "DescriptorCache4", new Object[] { descriptorName,
0534: modeName, otherProductName }));
0535: }
0536:
0537: og.setPreference(preferredProductName, otherProductName);
0538:
0539: String[] prefs = { preferredProductName, otherProductName };
0540:
0541: // Update structures to reflect this new product preference.
0542: if (productPrefs.containsKey(key) == false) {
0543: Vector v = new Vector();
0544: v.addElement(prefs);
0545:
0546: productPrefs.put(key, v);
0547:
0548: } else {
0549: Vector v = (Vector) productPrefs.get(key);
0550: v.addElement(prefs);
0551: }
0552:
0553: return true;
0554: }
0555:
0556: /**
0557: * Removes a preference between two products registered under
0558: * a common <code>RegistryElementDescriptor</code>. An error message will
0559: * be printed out if the operation was not registered previously.
0560: *
0561: * @param descriptorName the operation name as a String.
0562: * @param preferredProductName the product formerly preferred.
0563: * @param otherProductName the other product.
0564: *
0565: * @return false, if the descriptor was not registered previously
0566: * or if either if the products were not already
0567: * added against the descriptor.
0568: *
0569: * @throws IllegalArgumentException if this registry mode does
0570: * not support preferences.
0571: * @throws IllegalArgumentException if any of the args is null
0572: * @throws IllegalArgumentException if descriptorName or either of
0573: * the products were not previously registered.
0574: */
0575: boolean unsetProductPreference(String descriptorName,
0576: String preferredProductName, String otherProductName) {
0577:
0578: if (!arePreferencesSupported) {
0579: throw new IllegalArgumentException(JaiI18N.formatMsg(
0580: "DescriptorCache6", new Object[] { modeName }));
0581: }
0582:
0583: if ((descriptorName == null) || (preferredProductName == null)
0584: || (otherProductName == null))
0585: throw new IllegalArgumentException(JaiI18N
0586: .getString("Generic0"));
0587:
0588: // Attempt to unset preference of a product with itself, do nothing.
0589: if (preferredProductName.equalsIgnoreCase(otherProductName)) {
0590: return false;
0591: }
0592:
0593: // Use a caseless version of the key.
0594: CaselessStringKey key = new CaselessStringKey(descriptorName);
0595:
0596: if (descriptorNames.containsKey(key) == false) {
0597: throw new IllegalArgumentException(JaiI18N.formatMsg(
0598: "DescriptorCache1", new Object[] { descriptorName,
0599: modeName }));
0600: }
0601:
0602: ProductOperationGraph og = (ProductOperationGraph) products
0603: .get(key);
0604:
0605: if (og == null) {
0606: throw new IllegalArgumentException(JaiI18N.formatMsg(
0607: "DescriptorCache3", new Object[] { descriptorName,
0608: modeName }));
0609: }
0610:
0611: if (og.lookupOp(preferredProductName) == null) {
0612: throw new IllegalArgumentException(JaiI18N.formatMsg(
0613: "DescriptorCache4", new Object[] { descriptorName,
0614: modeName, preferredProductName }));
0615: }
0616:
0617: if (og.lookupOp(otherProductName) == null) {
0618: throw new IllegalArgumentException(JaiI18N.formatMsg(
0619: "DescriptorCache4", new Object[] { descriptorName,
0620: modeName, otherProductName }));
0621: }
0622:
0623: og.unsetPreference(preferredProductName, otherProductName);
0624:
0625: // Update structures to reflect removal of this product preference.
0626: if (productPrefs.containsKey(key) == false) {
0627: throw new IllegalArgumentException(JaiI18N.formatMsg(
0628: "DescriptorCache5", new Object[] { descriptorName,
0629: modeName }));
0630: }
0631:
0632: Vector v = (Vector) productPrefs.get(key);
0633: Iterator it = v.iterator();
0634: while (it.hasNext()) {
0635: String[] prefs = (String[]) it.next();
0636:
0637: if (prefs[0].equalsIgnoreCase(preferredProductName)
0638: && prefs[1].equalsIgnoreCase(otherProductName)) {
0639: it.remove();
0640: break;
0641: }
0642: }
0643:
0644: return true;
0645: }
0646:
0647: /**
0648: * Removes all preferences between products registered under
0649: * a common <code>RegistryElementDescriptor</code>. An error message will
0650: * be printed out if the operation was not registered previously.
0651: *
0652: * @param descriptorName the operation name as a String.
0653: *
0654: * @throws IllegalArgumentException if this registry mode does
0655: * not support preferences.
0656: * @throws IllegalArgumentException if descriptorName is null.
0657: */
0658: boolean clearProductPreferences(String descriptorName) {
0659:
0660: if (!arePreferencesSupported) {
0661: throw new IllegalArgumentException(JaiI18N.formatMsg(
0662: "DescriptorCache6", new Object[] { modeName }));
0663: }
0664:
0665: // Use a caseless version of the key.
0666: CaselessStringKey key = new CaselessStringKey(descriptorName);
0667:
0668: if (descriptorNames.containsKey(key) == false) {
0669: throw new IllegalArgumentException(JaiI18N.formatMsg(
0670: "DescriptorCache1", new Object[] { descriptorName,
0671: modeName }));
0672: }
0673:
0674: ProductOperationGraph og = (ProductOperationGraph) products
0675: .get(key);
0676:
0677: if (og == null) {
0678: throw new IllegalArgumentException(JaiI18N.formatMsg(
0679: "DescriptorCache3", new Object[] { descriptorName,
0680: modeName }));
0681: }
0682:
0683: // if there are no preferences to clear..
0684: if (productPrefs.containsKey(key) == false)
0685: return true;
0686:
0687: Vector v = (Vector) productPrefs.get(key);
0688: Enumeration e = v.elements();
0689:
0690: while (e.hasMoreElements()) {
0691: String prefs[] = (String[]) e.nextElement();
0692:
0693: String pref = prefs[0];
0694: String other = prefs[1];
0695:
0696: if (og.lookupOp(pref) == null) {
0697: throw new IllegalArgumentException(JaiI18N.formatMsg(
0698: "DescriptorCache4", new Object[] {
0699: descriptorName, modeName, pref }));
0700: }
0701:
0702: if (og.lookupOp(other) == null) {
0703: throw new IllegalArgumentException(JaiI18N.formatMsg(
0704: "DescriptorCache4", new Object[] {
0705: descriptorName, modeName, other }));
0706: }
0707:
0708: og.unsetPreference(pref, other);
0709: }
0710: productPrefs.remove(key);
0711: return true;
0712: }
0713:
0714: /**
0715: * Returns a list of the pairwise product preferences
0716: * under a particular <code>RegistryElementDescriptor</code>. If no product
0717: * preferences have been set, returns null.
0718: *
0719: * @param descriptorName the operation name as a String.
0720: * @return an array of 2-element arrays of Strings.
0721: *
0722: * @throws IllegalArgumentException if this registry mode does
0723: * not support preferences.
0724: * @throws IllegalArgumentException if descriptorName is null
0725: */
0726: String[][] getProductPreferences(String descriptorName) {
0727:
0728: if (!arePreferencesSupported) {
0729: throw new IllegalArgumentException(JaiI18N.formatMsg(
0730: "DescriptorCache6", new Object[] { modeName }));
0731: }
0732:
0733: // Use a caseless version of the key.
0734: CaselessStringKey key = new CaselessStringKey(descriptorName);
0735:
0736: Vector v;
0737:
0738: if (productPrefs.containsKey(key) == false) {
0739: // No product preferences have been set.
0740: return null;
0741: } else {
0742: v = (Vector) productPrefs.get(key);
0743: int s = v.size();
0744: if (s == 0) {
0745: return null;
0746: }
0747: String productPreferences[][] = new String[s][2];
0748: int count = 0;
0749: Enumeration e = v.elements();
0750: while (e.hasMoreElements()) {
0751: String[] o = (String[]) e.nextElement();
0752: productPreferences[count][0] = o[0];
0753: productPreferences[count++][1] = o[1];
0754: }
0755:
0756: return productPreferences;
0757: }
0758: }
0759:
0760: /**
0761: * Returns a list of the products registered under a particular
0762: * <code>RegistryElementDescriptor</code>, in an ordering that
0763: * satisfies all of the pairwise preferences that have been
0764: * set. Returns <code>null</code> if cycles exist. Returns
0765: * <code>null</code> if no <code>RegistryElementDescriptor</code>
0766: * has been registered under this descriptorName, or if no products
0767: * exist for this operation.
0768: *
0769: * @param descriptorName the operation name as a String.
0770: *
0771: * @return a Vector of Strings representing product names. returns
0772: * null if this registry mode does not support preferences.
0773: *
0774: * @throws IllegalArgumentException if descriptorName is null.
0775: */
0776: Vector getOrderedProductList(String descriptorName) {
0777:
0778: if (!arePreferencesSupported)
0779: return null;
0780:
0781: // Use a caseless version of the key.
0782: CaselessStringKey key = new CaselessStringKey(descriptorName);
0783:
0784: if (descriptorNames.containsKey(key) == false) {
0785: return null;
0786: }
0787:
0788: ProductOperationGraph productGraph = (ProductOperationGraph) products
0789: .get(key);
0790:
0791: // If no products exist under this Operation Name
0792: if (productGraph == null) {
0793: return null;
0794: }
0795:
0796: // Get the ordered vector of PartialOrderNodes
0797: Vector v1 = productGraph.getOrderedOperationList();
0798:
0799: if (v1 == null)
0800: return null;
0801:
0802: int size = v1.size();
0803:
0804: if (size == 0) { // no element
0805: return null;
0806: } else {
0807: Vector v2 = new Vector();
0808: for (int i = 0; i < size; i++) {
0809: v2.addElement(((PartialOrderNode) v1.elementAt(i))
0810: .getName());
0811: }
0812:
0813: return v2;
0814: }
0815: }
0816:
0817: // Property management
0818:
0819: private boolean arePropertiesSupported(String descriptorName) {
0820:
0821: CaselessStringKey key = new CaselessStringKey(descriptorName);
0822:
0823: RegistryElementDescriptor rdesc = (RegistryElementDescriptor) descriptorNames
0824: .get(key);
0825:
0826: if (rdesc == null) {
0827: throw new IllegalArgumentException(JaiI18N.formatMsg(
0828: "DescriptorCache1", new Object[] { descriptorName,
0829: modeName }));
0830: }
0831:
0832: return arePropertiesSupported;
0833: }
0834:
0835: /**
0836: * Removes all property associated information from this
0837: * <code>DescriptorCache</code>.
0838: */
0839: void clearPropertyState() {
0840:
0841: if (arePropertiesSupported == false) {
0842: throw new IllegalArgumentException(JaiI18N.formatMsg(
0843: "DescriptorCache7", new Object[] { modeName }));
0844: }
0845:
0846: properties = new Hashtable();
0847: suppressed = new Hashtable();
0848: }
0849:
0850: /**
0851: * Adds a <code>PropertyGenerator</code> to the a particular
0852: * descriptor.
0853: *
0854: * @param descriptorName the operation name as a String.
0855: * @param generator the <code>PropertyGenerator</code> to be added.
0856: */
0857: void addPropertyGenerator(String descriptorName,
0858: PropertyGenerator generator) {
0859:
0860: if ((descriptorName == null) || (generator == null))
0861: throw new IllegalArgumentException(JaiI18N
0862: .getString("Generic0"));
0863:
0864: if (arePropertiesSupported(descriptorName) == false) {
0865: throw new IllegalArgumentException(JaiI18N.formatMsg(
0866: "DescriptorCache7", new Object[] { modeName }));
0867: }
0868:
0869: CaselessStringKey key = new CaselessStringKey(descriptorName);
0870:
0871: Vector v = (Vector) properties.get(key);
0872:
0873: if (v == null) {
0874: v = new Vector();
0875: properties.put(key, v);
0876: }
0877:
0878: v.addElement(generator);
0879:
0880: v = (Vector) suppressed.get(key);
0881: Hashtable h = (Hashtable) sourceForProp.get(key);
0882:
0883: String names[] = generator.getPropertyNames();
0884:
0885: for (int j = 0; j < names.length; j++) {
0886: CaselessStringKey name = new CaselessStringKey(names[j]);
0887:
0888: if (v != null)
0889: v.remove(name);
0890: if (h != null)
0891: h.remove(name);
0892: }
0893: }
0894:
0895: private void hashNames(String descriptorName) {
0896: CaselessStringKey key = new CaselessStringKey(descriptorName);
0897:
0898: Vector c = (Vector) properties.get(key);
0899: Vector s = (Vector) suppressed.get(key);
0900:
0901: Hashtable h = new Hashtable();
0902: propNames.put(key, h);
0903:
0904: if (c != null) {
0905: PropertyGenerator pg;
0906: String names[];
0907:
0908: for (Iterator it = c.iterator(); it.hasNext();) {
0909: pg = (PropertyGenerator) it.next();
0910: names = pg.getPropertyNames();
0911:
0912: for (int i = 0; i < names.length; i++) {
0913: CaselessStringKey name = new CaselessStringKey(
0914: names[i]);
0915:
0916: // Don't add a property that was suppressed
0917: if ((s == null) || !s.contains(name)) {
0918: h.put(name, pg);
0919: }
0920: }
0921: }
0922: }
0923:
0924: Hashtable htable = (Hashtable) sourceForProp.get(key);
0925:
0926: if (htable != null) {
0927: for (Enumeration e = htable.keys(); e.hasMoreElements();) {
0928: CaselessStringKey name = (CaselessStringKey) e
0929: .nextElement();
0930:
0931: int i = ((Integer) htable.get(name)).intValue();
0932:
0933: PropertyGenerator generator = new PropertyGeneratorFromSource(
0934: i, name.getName());
0935:
0936: h.put(name, generator);
0937: }
0938: }
0939: }
0940:
0941: /**
0942: * Removes a <code>PropertyGenerator</code> from its association
0943: * with a particular descriptor. If the generator was not associated
0944: * with the descriptor, nothing happens.
0945: *
0946: * @param descriptorName the operation name as a String.
0947: * @param generator the <code>PropertyGenerator</code> to be removed.
0948: *
0949: * @throws IllegalArgumentException if descriptorName is null.
0950: * @throws IllegalArgumentException if generator is null.
0951: */
0952: void removePropertyGenerator(String descriptorName,
0953: PropertyGenerator generator) {
0954:
0955: if ((descriptorName == null) || (generator == null)) {
0956: throw new IllegalArgumentException(JaiI18N
0957: .getString("Generic0"));
0958: }
0959:
0960: if (arePropertiesSupported(descriptorName) == false) {
0961: throw new IllegalArgumentException(JaiI18N.formatMsg(
0962: "DescriptorCache7", new Object[] { modeName }));
0963: }
0964:
0965: CaselessStringKey key = new CaselessStringKey(descriptorName);
0966:
0967: Vector v = (Vector) properties.get(key);
0968:
0969: if (v != null) {
0970: v.removeElement(generator);
0971: }
0972: }
0973:
0974: /**
0975: * Forces a particular property to be suppressed by nodes associated
0976: * with a particular descriptor. By default, properties are passed
0977: * through unchanged.
0978: *
0979: * @param descriptorName the operation name as a String.
0980: * @param propertyName the name of the property to be suppressed.
0981: *
0982: * @throws IllegalArgumentException if descriptorName is null.
0983: * @throws IllegalArgumentException if propertyName is null.
0984: */
0985: void suppressProperty(String descriptorName, String propertyName) {
0986:
0987: if ((descriptorName == null) || (propertyName == null)) {
0988: throw new IllegalArgumentException(JaiI18N
0989: .getString("Generic0"));
0990: }
0991:
0992: if (arePropertiesSupported(descriptorName) == false) {
0993: throw new IllegalArgumentException(JaiI18N.formatMsg(
0994: "DescriptorCache7", new Object[] { modeName }));
0995: }
0996:
0997: CaselessStringKey key = new CaselessStringKey(descriptorName);
0998: CaselessStringKey propertyKey = new CaselessStringKey(
0999: propertyName);
1000:
1001: // Mark the property name as suppressed.
1002: Vector v = (Vector) suppressed.get(key);
1003:
1004: if (v == null) {
1005: v = new Vector();
1006: suppressed.put(key, v);
1007: }
1008:
1009: v.addElement(propertyKey);
1010:
1011: Hashtable h = (Hashtable) sourceForProp.get(key);
1012:
1013: if (h != null) {
1014: h.remove(propertyKey);
1015: }
1016: }
1017:
1018: /**
1019: * Forces all properties to be suppressed by nodes associated with a
1020: * particular descriptor. By default, properties are passed through
1021: * unchanged.
1022: *
1023: * @param descriptorName the operation name as a String.
1024: *
1025: * @throws IllegalArgumentException if descriptorName is null.
1026: */
1027: void suppressAllProperties(String descriptorName) {
1028:
1029: if (arePropertiesSupported(descriptorName) == false) {
1030: throw new IllegalArgumentException(JaiI18N.formatMsg(
1031: "DescriptorCache7", new Object[] { modeName }));
1032: }
1033:
1034: // In this method synchronized takes care of the fact that all the
1035: // operations take place in a sequential fashion, while
1036: // suppressProperty's writeLock insures that all changes are
1037: // made by only one thread.
1038: CaselessStringKey key = new CaselessStringKey(descriptorName);
1039:
1040: // Get names of all properties that this descriptorName
1041: // is associated with
1042: Vector v = (Vector) properties.get(key);
1043:
1044: if (v != null) {
1045: PropertyGenerator pg;
1046:
1047: for (Iterator it = v.iterator(); it.hasNext();) {
1048: pg = (PropertyGenerator) it.next();
1049: String propertyNames[] = pg.getPropertyNames();
1050: for (int i = 0; i < propertyNames.length; i++) {
1051: suppressProperty(descriptorName, propertyNames[i]);
1052: }
1053: }
1054: }
1055: }
1056:
1057: /**
1058: * Forces a property to be copied from the specified source index
1059: * by nodes associated with a particular descriptor. By default, a
1060: * property is copied from the first source node that emits it. The
1061: * result of specifying an invalid source is undefined.
1062: *
1063: * @param descriptorName the operation name as a String.
1064: * @param propertyName the name of the property to be copied.
1065: * @param sourceIndex the index of the source to copy the property from.
1066: *
1067: * @throws IllegalArgumentException if descriptorName is null.
1068: * @throws IllegalArgumentException if propertyName is null.
1069: */
1070: void copyPropertyFromSource(String descriptorName,
1071: String propertyName, int sourceIndex) {
1072:
1073: if ((descriptorName == null) || (propertyName == null)) {
1074: throw new IllegalArgumentException(JaiI18N
1075: .getString("Generic0"));
1076: }
1077:
1078: if (arePropertiesSupported(descriptorName) == false) {
1079: throw new IllegalArgumentException(JaiI18N.formatMsg(
1080: "DescriptorCache7", new Object[] { modeName }));
1081: }
1082:
1083: CaselessStringKey key = new CaselessStringKey(descriptorName);
1084: CaselessStringKey propertyKey = new CaselessStringKey(
1085: propertyName);
1086:
1087: Hashtable h = (Hashtable) sourceForProp.get(key);
1088:
1089: if (h == null) {
1090: h = new Hashtable();
1091: sourceForProp.put(key, h);
1092: }
1093:
1094: h.put(propertyKey, new Integer(sourceIndex));
1095:
1096: Vector v = (Vector) suppressed.get(key);
1097:
1098: if (v != null) {
1099: v.remove(propertyKey);
1100: }
1101: }
1102:
1103: /**
1104: * Returns a list of the properties generated by nodes implementing
1105: * the functionality associated with a particular descriptor.
1106: * Returns null if no properties are generated.
1107: *
1108: * @param descriptorName the operation name as a String.
1109: * @return an array of Strings.
1110: *
1111: * @throws IllegalArgumentException if descriptorName is null.
1112: */
1113: String[] getGeneratedPropertyNames(String descriptorName) {
1114:
1115: if (arePropertiesSupported(descriptorName) == false) {
1116: throw new IllegalArgumentException(JaiI18N.formatMsg(
1117: "DescriptorCache7", new Object[] { modeName }));
1118: }
1119:
1120: CaselessStringKey key = new CaselessStringKey(descriptorName);
1121:
1122: hashNames(descriptorName);
1123:
1124: Hashtable h = (Hashtable) propNames.get(key);
1125:
1126: if (h != null && h.size() > 0) {
1127: String names[] = new String[h.size()];
1128: int count = 0;
1129: for (Enumeration e = h.keys(); e.hasMoreElements();) {
1130: CaselessStringKey str = (CaselessStringKey) e
1131: .nextElement();
1132: names[count++] = str.getName();
1133: }
1134:
1135: return count > 0 ? names : null;
1136: }
1137:
1138: return null;
1139: }
1140:
1141: /**
1142: * Merge mode-specific property environment with mode-independent
1143: * property environment of the descriptor. Array elements of
1144: * "sources" are expected to be in the same ordering as referenced
1145: * by the "sourceIndex" parameter of copyPropertyFromSource().
1146: *
1147: * @param descriptorName the descriptor name as a <code>String</code>
1148: * @param sources the <code>PropertySource</code>s corresponding to
1149: * the sources of the object representing the named descriptor
1150: * in the indicated mode.
1151: * @param op the <code>Object</code> from which properties will
1152: * be generated.
1153: *
1154: * @return A <code>PropertySource</code> which encapsulates
1155: * the global property environment for the object representing
1156: * the named descriptor in the indicated mode.
1157: *
1158: * @throws IllegalArgumentException if any of the arguments
1159: * is <code>null</code>
1160: * @throws IllegalArgumentException if there is no <code>
1161: * RegistryElementDescriptor</code> registered against
1162: * the <code>descriptorName</code>
1163: * @throws IllegalArgumentException if the specified mode does not
1164: * support properties.
1165: *
1166: * @since JAI 1.1
1167: */
1168: PropertySource getPropertySource(String descriptorName, Object op,
1169: Vector sources) {
1170:
1171: if ((descriptorName == null) || (op == null)
1172: || (sources == null)) {
1173: throw new IllegalArgumentException(JaiI18N
1174: .getString("Generic0"));
1175: }
1176:
1177: if (arePropertiesSupported(descriptorName) == false) {
1178: throw new IllegalArgumentException(JaiI18N.formatMsg(
1179: "DescriptorCache7", new Object[] { modeName }));
1180: }
1181:
1182: CaselessStringKey key = new CaselessStringKey(descriptorName);
1183:
1184: Vector pg = (Vector) properties.get(key);
1185: Vector sp = (Vector) suppressed.get(key);
1186:
1187: Hashtable sfp = (Hashtable) sourceForProp.get(key);
1188:
1189: return new PropertyEnvironment(sources, pg, sp, sfp, op);
1190: }
1191: }
|