001: /*
002: * $RCSfile: RegistryMode.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:57:19 $
010: * $State: Exp $
011: */
012: package javax.media.jai;
013:
014: import java.lang.reflect.Method;
015: import java.util.Enumeration;
016: import java.util.HashSet;
017: import java.util.Hashtable;
018: import java.util.Set;
019: import javax.media.jai.registry.CollectionRegistryMode;
020: import javax.media.jai.registry.RemoteRenderableRegistryMode;
021: import javax.media.jai.registry.RemoteRenderedRegistryMode;
022: import javax.media.jai.registry.RenderableCollectionRegistryMode;
023: import javax.media.jai.registry.RenderableRegistryMode;
024: import javax.media.jai.registry.RenderedRegistryMode;
025: import javax.media.jai.registry.TileDecoderRegistryMode;
026: import javax.media.jai.registry.TileEncoderRegistryMode;
027: import javax.media.jai.util.CaselessStringKey;
028:
029: /**
030: * A class which provides information about a registry mode. The
031: * static methods of the class act to maintain a global list of
032: * known modes. All <code>RegistryMode</code>s known
033: * to JAI are added to this list when this class is loaded. The
034: * <code>RegistryMode</code>s installed by JAI cannot be
035: * replaced or removed.
036: *
037: * The <code>String</code>s used to represent the registry modes
038: * are all used in a case-insensitive manner.
039: *
040: * @since JAI 1.1
041: */
042: public class RegistryMode {
043:
044: /**
045: * Cache of known RegistryMode-s hashed by
046: * <code>CaselessStringKey</code>s which wraps a String and performs
047: * case-insensitive equals()
048: */
049: private static Hashtable registryModes;
050:
051: /**
052: * Set of <code>CaselessStringKey</code>s of registryModes which
053: * cannot be replaced or removed.
054: */
055: private static HashSet immutableNames;
056:
057: // Instance variables.
058: private CaselessStringKey name;
059: private Class descriptorClass;
060: private Class productClass;
061: private Method factoryMethod;
062: private boolean arePreferencesSupported;
063: private boolean arePropertiesSupported;
064:
065: // Load all JAI-defined registryModes.
066: static {
067: registryModes = new Hashtable(4);
068: immutableNames = new HashSet();
069:
070: // operation modes
071: addMode(new RenderedRegistryMode(), true);
072: addMode(new RenderableRegistryMode(), true);
073: addMode(new CollectionRegistryMode(), true);
074: addMode(new RenderableCollectionRegistryMode(), true);
075:
076: // remote modes
077: addMode(new RemoteRenderedRegistryMode(), true);
078: addMode(new RemoteRenderableRegistryMode(), true);
079:
080: // Tilecodec modes
081: addMode(new TileEncoderRegistryMode(), true);
082: addMode(new TileDecoderRegistryMode(), true);
083: }
084:
085: /**
086: * Adds a new RegistryMode to the existing list. If immutable is
087: * "true" then the CaselessStringKey is added to immutableNames
088: * also. This mode must <u>not</u> already exist in the list.
089: */
090: private static boolean addMode(RegistryMode mode, boolean immutable) {
091:
092: if (registryModes.containsKey(mode.name))
093: return false;
094:
095: registryModes.put(mode.name, mode);
096:
097: if (immutable)
098: immutableNames.add(mode.name);
099:
100: return true;
101: }
102:
103: /**
104: * Adds a new <code>RegistryMode</code> to the existing list. This
105: * succeeds only if the mode is <u>not</u> already present in the
106: * list. New <code>RegistryMode</code> names can not clash (in a
107: * case insensitive manner) with the ones installed by JAI (done
108: * statically when this class is loaded)
109: *
110: * @param mode the new RegistryMode to be added to list
111: *
112: * @return false if the mode was already in the list. true otherwise
113: */
114: public synchronized static boolean addMode(RegistryMode mode) {
115: return addMode(mode, false);
116: }
117:
118: /**
119: * Removes a mode from the existing list of known registryModes.
120: * If the mode is one of the JAI-installed ones, it can not
121: * be removed.
122: *
123: * @param mode the RegistryMode to be removed from the list
124: *
125: * @return false if the mode can not be removed because it was added
126: * by JAI or because the mode was not previously add.
127: * returns true otherwise.
128: */
129: public synchronized static boolean removeMode(String name) {
130:
131: CaselessStringKey key = new CaselessStringKey(name);
132:
133: if (immutableNames.contains(key))
134: return false;
135:
136: return registryModes.remove(key) != null;
137: }
138:
139: /**
140: * Get the list of the known registry mode names.
141: *
142: * @return <code>null</code>, if there are no registered modes.
143: * Otherwise returns an array of <code>String</code>s of registered
144: * mode names.
145: */
146: public static synchronized String[] getModeNames() {
147:
148: String names[] = new String[registryModes.size()];
149:
150: int i = 0;
151:
152: for (Enumeration e = registryModes.keys(); e.hasMoreElements();) {
153: CaselessStringKey key = (CaselessStringKey) e.nextElement();
154:
155: names[i++] = key.getName();
156: }
157:
158: if (i <= 0)
159: return null;
160:
161: return names;
162: }
163:
164: /**
165: * Get a list of all known registry modes associated with the
166: * specified <code>descriptorClass</code>.
167: *
168: * @param descriptorClass a <code>Class</code>
169: *
170: * @return <code>null</code> if there are no modes registered
171: * against the specified descriptorClass. Otherwise returns an
172: * array of <code>String</code>s of mode names associated with the
173: * descriptorClass.
174: */
175: public static synchronized String[] getModeNames(
176: Class descriptorClass) {
177:
178: String names[] = new String[registryModes.size()];
179:
180: int i = 0;
181:
182: for (Enumeration e = registryModes.elements(); e
183: .hasMoreElements();) {
184: RegistryMode mode = (RegistryMode) e.nextElement();
185:
186: if (mode.getDescriptorClass() == descriptorClass)
187: names[i++] = mode.getName();
188: }
189:
190: if (i <= 0)
191: return null;
192:
193: String matchedNames[] = new String[i];
194:
195: for (int j = 0; j < i; j++)
196: matchedNames[j] = names[j];
197:
198: return matchedNames;
199: }
200:
201: /**
202: * Get the registry mode corresponding to this name.
203: */
204: public static RegistryMode getMode(String name) {
205:
206: CaselessStringKey key = new CaselessStringKey(name);
207:
208: return (RegistryMode) registryModes.get(key);
209: }
210:
211: /**
212: * Get a <code>Set</code> of all descriptor classes over
213: * all registry modes.
214: */
215: public static synchronized Set getDescriptorClasses() {
216: HashSet set = new HashSet();
217:
218: for (Enumeration e = registryModes.elements(); e
219: .hasMoreElements();) {
220: RegistryMode mode = (RegistryMode) e.nextElement();
221:
222: set.add(mode.descriptorClass);
223: }
224:
225: return set;
226: }
227:
228: /**
229: * Constructor. Protected access allows only instantiation of
230: * subclasses.
231: *
232: * @param name name of the registry mode
233: * @param descriptorClass the specific sub-class of
234: * <code>RegistryElementDescriptor</code> associated with
235: * this registry mode.
236: * @param productClass the <code>Class</code> of the objects
237: * produced by this registry mode. This would typically
238: * be <code>factoryMethod.getReturnType()</code>.
239: * @param factoryMethod the method used to "create" an object.
240: * @param arePreferencesSupported does this registry mode support
241: * preferences between products or instances of the "modes"
242: * @param arePropertiesSupported do properties have to be managed
243: * for this registry mode.
244: */
245: protected RegistryMode(String name, Class descriptorClass,
246: Class productClass, Method factoryMethod,
247: boolean arePreferencesSupported,
248: boolean arePropertiesSupported) {
249:
250: this .name = new CaselessStringKey(name);
251: this .descriptorClass = descriptorClass;
252: this .productClass = productClass;
253: this .factoryMethod = factoryMethod;
254: this .arePreferencesSupported = arePreferencesSupported;
255: this .arePropertiesSupported = arePropertiesSupported;
256: }
257:
258: /** Get the registry mode name (case-preserved) */
259: public final String getName() {
260: return name.getName();
261: }
262:
263: /** Get the factory method that corresponds to "create" */
264: public final Method getFactoryMethod() {
265: return factoryMethod;
266: }
267:
268: /** Does this registry mode support preferences ? */
269: public final boolean arePreferencesSupported() {
270: return arePreferencesSupported;
271: }
272:
273: /**
274: * Are properties to be managed for this registry mode ?
275: */
276: public final boolean arePropertiesSupported() {
277: return arePropertiesSupported;
278: }
279:
280: /**
281: * Returns the descriptor class that corresponds to this registry mode.
282: *
283: * For eg. this would be OperationDescriptor for rendered, renderable,
284: * collection ... and TileCodecDescriptor for tilecodec etc.
285: */
286: public final Class getDescriptorClass() {
287: return descriptorClass;
288: }
289:
290: /**
291: * The <code>Class</code> of the objects produced by this
292: * registry mode.
293: */
294: public final Class getProductClass() {
295: return productClass;
296: }
297:
298: /**
299: * A convenience method which essentially returns
300: * getFactoryMethod().getDeclaringClass()
301: */
302: public final Class getFactoryClass() {
303: return factoryMethod.getDeclaringClass();
304: }
305: }
|