Source Code Cross Referenced for OperationNodeSupport.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » javax » media » jai » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » Java Advanced Imaging » javax.media.jai 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $RCSfile: OperationNodeSupport.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:13 $
010:         * $State: Exp $
011:         */
012:        package javax.media.jai;
013:
014:        import java.awt.RenderingHints;
015:        import java.awt.image.Raster;
016:        import java.awt.image.RenderedImage;
017:        import java.awt.image.renderable.ParameterBlock;
018:        import java.io.IOException;
019:        import java.io.ObjectInputStream;
020:        import java.io.ObjectOutputStream;
021:        import java.io.Serializable;
022:        import java.util.Hashtable;
023:        import java.util.Iterator;
024:        import java.util.Observable;
025:        import java.util.Observer;
026:        import java.util.Vector;
027:        import javax.media.jai.remote.SerializableState;
028:        import javax.media.jai.remote.SerializerFactory;
029:
030:        /**
031:         * This is a utility class that can be used by <code>OperationNode</code>s
032:         * to consolidate common functionality.  An instance of this class may be
033:         * used as a member field of the <code>OperationNode</code> and some of the
034:         * <code>OperationNode</code>'s work delegated to it.
035:         *
036:         * @since JAI 1.1
037:         */
038:        public class OperationNodeSupport implements  Serializable {
039:
040:            // Constants supporting compare().
041:            private static final int PB_EQUAL = 0x0;
042:            private static final int PB_SOURCES_DIFFER = 0x1;
043:            private static final int PB_PARAMETERS_DIFFER = 0x2;
044:            private static final int PB_DIFFER = PB_SOURCES_DIFFER
045:                    | PB_PARAMETERS_DIFFER;
046:
047:            // The OperationRegistryMode.
048:            private String registryModeName;
049:
050:            // Critical attributes.
051:            private String opName;
052:            private transient OperationRegistry registry;
053:            private transient ParameterBlock pb;
054:            private transient RenderingHints hints;
055:
056:            // Event helper.
057:            private PropertyChangeSupportJAI eventManager;
058:
059:            /**
060:             * This instance variable is lazily constructed only when one of the
061:             * PropertySource methods or one of the local property environment
062:             * mutators is accessed. PropertyEnvironment is a package scope class.
063:             */
064:            private transient PropertyEnvironment propertySource = null;
065:
066:            /**
067:             * Stores local property environment modifications sequentially as
068:             * a PropertyGenerator, a String, or a CopyDirective depending
069:             * on which local property environment mutator method was invoked.
070:             */
071:            private Vector localPropEnv = new Vector();
072:
073:            /**
074:             * <code>Map</code> of <code>ParamObserver</code>s of instances of
075:             * <code>DeferredData</code> in the parameter <code>Vector</code>.
076:             */
077:            private Hashtable paramObservers = new Hashtable();
078:
079:            /**
080:             * Compare the contents of two <code>ParameterBlock</code>s.
081:             */
082:            private static int compare(ParameterBlock pb1, ParameterBlock pb2) {
083:                if (pb1 == null && pb2 == null) {
084:                    return PB_EQUAL;
085:                }
086:
087:                if ((pb1 == null && pb2 != null)
088:                        || (pb1 != null && pb2 == null)) {
089:                    return PB_DIFFER;
090:                }
091:
092:                int result = PB_EQUAL;
093:                if (!equals(pb1.getSources(), pb2.getSources())) {
094:                    result |= PB_SOURCES_DIFFER;
095:                }
096:                if (!equals(pb1.getParameters(), pb2.getParameters())) {
097:                    result |= PB_PARAMETERS_DIFFER;
098:                }
099:
100:                return result;
101:            }
102:
103:            private static boolean equals(ParameterBlock pb1, ParameterBlock pb2) {
104:                return pb1 == null ? pb2 == null : equals(pb1.getSources(), pb2
105:                        .getSources())
106:                        && equals(pb1.getParameters(), pb2.getParameters());
107:            }
108:
109:            private static boolean equals(Object o1, Object o2) {
110:                return o1 == null ? o2 == null : o1.equals(o2);
111:            }
112:
113:            /**
114:             * Constructs an <code>OperationNodeSupport</code> instance.
115:             * All parameters except <code>opName</code> may be <code>null</code>.
116:             * If non-<code>null</code> the <code>PropertyChangeSupportJAI</code>
117:             * should have been created with the node as its event source (note
118:             * that this cannot be verified).
119:             *
120:             * <p> The <code>ParameterBlock</code> may include
121:             * <code>DeferredData</code> parameters.  These will not be evaluated
122:             * until their values are actually required, i.e., when the node is
123:             * rendered.  Any <code>Observable</code> events generated by such
124:             * <code>DeferredData</code> parameters will be trapped by the node,
125:             * converted to a <code>PropertyChangeEventJAI</code> named "parameters",
126:             * and forwarded to any listeners registered with the supplied.
127:             * <code>eventManager</code>.  The old and new values of the event object
128:             * so generated will be the previous and current values, respectively, of
129:             * the data object wrapped by the <code>DeferredData</code> parameter,
130:             * and thus will be instances of the class returned by the
131:             * <code>getDataClass()</code> method of the <code>DeferredData</code>
132:             * parameter.
133:             *
134:             * @param registryModeName  The name of the registry mode concerned.
135:             * @param opName  The operation name to set.
136:             * @param registry  The <code>OperationRegistry</code> to set;
137:             *        it may be <code>null</code> in which case the registry
138:             *        will be set to the default JAI registry.
139:             * @param pb  The <code>ParameterBlock</code> to set;
140:             *        it may be <code>null</code>.
141:             * @param hints The new <code>RenderingHints</code> to be set;
142:             *        it may be <code>null</code>.
143:             * @param eventManager The event helper object.  The property change
144:             *        event source of this object should be the
145:             *        <code>OperationNode</code> which is using the constructed
146:             *        <code>OperationNodeSupport</code> instance.  If <code>null</code>
147:             *        no events will be fired.
148:             *
149:             * @throws IllegalArgumentException if <code>registryModeName</code>
150:             *         or <code>opName</code> is <code>null</code>.
151:             */
152:            public OperationNodeSupport(String registryModeName, String opName,
153:                    OperationRegistry registry, ParameterBlock pb,
154:                    RenderingHints hints, PropertyChangeSupportJAI eventManager) {
155:                if (registryModeName == null || opName == null) {
156:                    throw new IllegalArgumentException(JaiI18N
157:                            .getString("Generic0"));
158:                }
159:
160:                // Set instance variables.
161:                this .registryModeName = registryModeName;
162:                this .opName = opName;
163:                if (registry == null)
164:                    this .registry = JAI.getDefaultInstance()
165:                            .getOperationRegistry();
166:                else
167:                    this .registry = registry;
168:                this .pb = pb;
169:                this .hints = hints;
170:                this .eventManager = eventManager;
171:
172:                // Set any DeferredData Observers.
173:                if (pb != null) {
174:                    updateObserverMap(pb.getParameters());
175:                }
176:            }
177:
178:            /**
179:             * Class representing a copy-from-source directive set via
180:             * <code>copyPropertyFromSource()</code>.
181:             */
182:            private class CopyDirective implements  Serializable {
183:                /** The name of the property. */
184:                private String name;
185:
186:                /** The index of the source from which to copy the property. */
187:                private int index;
188:
189:                /**
190:                 * Constructor.
191:                 *
192:                 * @param name The name of the property.
193:                 * @param index The index of the source from which to copy the
194:                 *              property.
195:                 */
196:                CopyDirective(String name, int index) {
197:                    if (name == null) {
198:                        throw new IllegalArgumentException(JaiI18N
199:                                .getString("Generic0"));
200:                    }
201:                    this .name = name;
202:                    this .index = index;
203:                }
204:
205:                String getName() {
206:                    return name;
207:                }
208:
209:                int getIndex() {
210:                    return index;
211:                }
212:            }
213:
214:            /**
215:             * Class which is an <code>Observer</code> of a <code>DeferredData</code>
216:             * parameter.
217:             */
218:            private class ParamObserver implements  Observer {
219:                /** The index of the associated parameter. */
220:                final int paramIndex;
221:
222:                /** The <code>DeferredData</code> object to observe. */
223:                final DeferredData dd;
224:
225:                /**
226:                 * Constructor.
227:                 *
228:                 * @param paramIndex The index of the associated parameter.
229:                 * @param dd The <code>DeferredData</code> object to observe.
230:                 */
231:                ParamObserver(int paramIndex, DeferredData dd) {
232:                    if (dd == null) {
233:                        throw new IllegalArgumentException(JaiI18N
234:                                .getString("Generic0"));
235:                    } else if (paramIndex < 0
236:                            || (pb != null && (paramIndex >= ((ParameterBlock) pb)
237:                                    .getNumParameters()))) {
238:                        throw new ArrayIndexOutOfBoundsException();
239:                    }
240:
241:                    this .paramIndex = paramIndex;
242:                    this .dd = dd;
243:
244:                    // Add this object as an Observer of the Deferred Data.
245:                    dd.addObserver(this );
246:                }
247:
248:                /**
249:                 * Implementation of <code>Observer</code>.  An update from the
250:                 * observed <code>DeferredData</code> causes an event to be fired
251:                 * if the <code>DeferredData</code> had been previously evaluated
252:                 * and there are event listeners.
253:                 */
254:                public synchronized void update(Observable o, Object arg) {
255:                    if (!(o == dd)) {
256:                        return;
257:                    }
258:
259:                    // Do nothing unless the DeferredData was already evaluated.
260:                    if (arg != null && eventManager != null) {
261:                        Vector params = pb.getParameters();
262:                        Vector oldParams = (Vector) params.clone();
263:                        Vector newParams = (Vector) params.clone();
264:
265:                        oldParams.set(paramIndex, arg);
266:                        newParams.set(paramIndex, dd.getData());
267:
268:                        fireEvent("Parameters", oldParams, newParams);
269:                    }
270:                }
271:            }
272:
273:            /**
274:             * Updates the <code>Map</code> of <code>Observer</code>s of
275:             * <code>DeferredData</code> instances in the parameter
276:             * <code>Vector</code>.
277:             */
278:            private void updateObserverMap(Vector parameters) {
279:                if (parameters == null) {
280:                    return;
281:                }
282:
283:                int numParameters = parameters.size();
284:                for (int i = 0; i < numParameters; i++) {
285:                    Object parameter = parameters.get(i);
286:                    Integer index = new Integer(i);
287:
288:                    // Replace or remove ParamObserver as needed.
289:                    Object oldObs;
290:                    if (parameter instanceof  DeferredData) {
291:                        Observer obs = new ParamObserver(i,
292:                                (DeferredData) parameter);
293:                        oldObs = paramObservers.put(index, obs);
294:                    } else {
295:                        oldObs = paramObservers.remove(index);
296:                    }
297:
298:                    // Unregister Observer from the associated DeferredData.
299:                    if (oldObs != null) {
300:                        ParamObserver obs = (ParamObserver) oldObs;
301:                        obs.dd.deleteObserver(obs);
302:                    }
303:                }
304:            }
305:
306:            /**
307:             * Returns the name of <code>RegistryMode</code> corresponding to
308:             * this <code>OperationNode</code>.  This value shoud be immutable
309:             * for a given node.  The value is returned by reference.
310:             */
311:            public String getRegistryModeName() {
312:                return registryModeName;
313:            }
314:
315:            /**
316:             * Returns the name of the operation the associated node represents.
317:             * The value is returned by reference.
318:             */
319:            public String getOperationName() {
320:                return opName;
321:            }
322:
323:            /**
324:             * Sets the name of the operation the associated node represents.
325:             * The value is set by reference.
326:             *
327:             * <p> If the operation name changes as a result of calling this
328:             * method according to a case-insensitive
329:             * comparison by <code>equals()</code> of the old and new names,
330:             * a <code>PropertyChangeEventJAI<code> named "OperationName"
331:             * will be fired by the event helper object with old and new values
332:             * set to the old and new values of the operation name, respectively.
333:             *
334:             * @param opName The new operation name to be set.
335:             *
336:             * @throws IllegalArgumentException if <code>opName</code> is
337:             * <code>null</code>.
338:             */
339:            public void setOperationName(String opName) {
340:                if (opName == null) {
341:                    throw new IllegalArgumentException(JaiI18N
342:                            .getString("Generic0"));
343:                }
344:
345:                if (opName.equalsIgnoreCase(this .opName))
346:                    return;
347:
348:                String oldOpName = this .opName;
349:                this .opName = opName;
350:                fireEvent("OperationName", oldOpName, opName);
351:                resetPropertyEnvironment(false);
352:            }
353:
354:            /**
355:             * Returns the <code>OperationRegistry</code> used by the associated
356:             * node.  The value is returned by reference.
357:             */
358:            public OperationRegistry getRegistry() {
359:                return registry;
360:            }
361:
362:            /**
363:             * Sets the <code>OperationRegistry</code> that is used by the associated
364:             * node.  If the specified registry is <code>null</code>, the
365:             * registry will be set to the default JAI registry.  The value is
366:             * set by reference.
367:             *
368:             * <p> If the registry changes according to a direct comparison
369:             * of the old and new registry references,
370:             * a <code>PropertyChangeEventJAI<code> named "OperationRegistry"
371:             * will be fired by the event helper object with old and new values
372:             * set to the old and new values of the registry, respectively.
373:             *
374:             * @param registry  The new <code>OperationRegistry</code> to be set;
375:             *        it may be <code>null</code>.
376:             */
377:            public void setRegistry(OperationRegistry registry) {
378:                if (registry == null) {
379:                    registry = JAI.getDefaultInstance().getOperationRegistry();
380:                }
381:                if (registry != this .registry) {
382:                    OperationRegistry oldRegistry = this .registry;
383:                    this .registry = registry;
384:                    fireEvent("OperationRegistry", oldRegistry, registry);
385:                    resetPropertyEnvironment(false);
386:                }
387:            }
388:
389:            /**
390:             * Returns the <code>ParameterBlock</code> of the associated node
391:             * by reference.  Nodes desirous of maintaining a consistent state
392:             * for their <code>ParameterBlock</code> may prefer to clone the
393:             * value returned by this method.
394:             */
395:            public ParameterBlock getParameterBlock() {
396:                return pb;
397:            }
398:
399:            /**
400:             * Sets the <code>ParameterBlock</code> of the associated node by
401:             * reference.  If the specified <code>ParameterBlock</code> is
402:             * <code>null</code>, it is assumed that the associated node has
403:             * neither input sources nor parameters.  Nodes desirous of maintaining
404:             * a consistent state for their <code>ParameterBlock</code> may prefer
405:             * to clone any user-supplied <code>ParameterBlock</code> before passing
406:             * it to this method.
407:             *
408:             * <p> This method does not validate the content of the supplied
409:             * <code>ParameterBlock</code>.  The caller should ensure that
410:             * the sources and parameters in the <code>ParameterBlock</code>
411:             * are suitable for the operation the associated node represents; otherwise
412:             * some form of error or exception may occur at the time of rendering.
413:             *
414:             * <p> If the <code>ParameterBlock</code> changes according to a
415:             * comparison of the sources and parameters <code>Vector</code>s of the
416:             * old and new <code>ParameterBlock</code>s using <code>equals()</code>,
417:             * a <code>PropertyChangeEventJAI<code> named "ParameterBlock"
418:             * will be fired by the event helper object with old and new values
419:             * set to the old and new values of the <code>ParameterBlock</code>,
420:             * respectively.  A <code>PropertyChangeEventJAI<code> named "Sources" or
421:             * "Parameters" will instead be fired if it can be determined that the
422:             * <code>ParameterBlock</code> modification has affected only the sources
423:             * or parameters of the node, respectively.
424:             *
425:             * <p> The <code>ParameterBlock</code> may include
426:             * <code>DeferredData</code> parameters.  These will not be evaluated
427:             * until their values are actually required, i.e., when the node is
428:             * rendered.  Any <code>Observable</code> events generated by such
429:             * <code>DeferredData</code> parameters will be trapped by the node,
430:             * converted to a <code>PropertyChangeEventJAI</code> named "parameters",
431:             * and forwarded to any listeners registered with the supplied.
432:             * <code>eventManager</code>.  The old and new values of the event object
433:             * so generated will be the previous and current values, respectively, of
434:             * the data object wrapped by the <code>DeferredData</code> parameter,
435:             * and thus will be instances of the class returned by the
436:             * <code>getDataClass()</code> method of the <code>DeferredData</code>
437:             * parameter.
438:             *
439:             * @param pb  The new <code>ParameterBlock</code> to be set;
440:             *        it may be <code>null</code>.
441:             */
442:            public void setParameterBlock(ParameterBlock pb) {
443:                int comparison = compare(this .pb, pb);
444:                if (comparison == PB_EQUAL) {
445:                    return;
446:                }
447:
448:                ParameterBlock oldPB = this .pb;
449:                this .pb = pb;
450:
451:                // Set any DeferredData Observers.
452:                if (pb != null) {
453:                    updateObserverMap(pb.getParameters());
454:                }
455:
456:                if (comparison == PB_SOURCES_DIFFER) {
457:                    // Sources have changed.
458:                    fireEvent("Sources", oldPB.getSources(), pb.getSources());
459:                } else if (comparison == PB_PARAMETERS_DIFFER) {
460:                    // Parameters have changed.
461:                    fireEvent("Parameters", oldPB.getParameters(), pb
462:                            .getParameters());
463:                } else {
464:                    // Sources and parameters have changed.
465:                    fireEvent("ParameterBlock", oldPB, pb);
466:                }
467:
468:                resetPropertyEnvironment(false);
469:            }
470:
471:            /**
472:             * Returns the <code>RenderingHints</code> of the associated node
473:             * by reference. Nodes desirous of maintaining a consistent state
474:             * for their <code>RenderingHints</code> may prefer to clone the
475:             * value returned by this method.
476:             */
477:            public RenderingHints getRenderingHints() {
478:                return hints;
479:            }
480:
481:            /**
482:             * Sets the <code>RenderingHints</code> of the associated node.  It is
483:             * legal for nodes to ignore <code>RenderingHints</code> set on them by
484:             * this mechanism.  Nodes desirous of maintaining
485:             * a consistent state for their <code>RenderingHints</code> may prefer
486:             * to clone any user-supplied <code>RenderingHints</code> before passing
487:             * it to this method.
488:             *
489:             * <p> If the <code>RenderingHints</code> changes according to a
490:             * comparison by <code>equals()</code> of the old and new hints,
491:             * a <code>PropertyChangeEventJAI<code> named "RenderingHints"
492:             * will be fired by the event helper object with old and new values
493:             * set to the old and new values of the <code>RenderingHints</code>,
494:             * respectively.
495:             *
496:             * @param hints The new <code>RenderingHints</code> to be set;
497:             *        it may be <code>null</code>.
498:             */
499:            public void setRenderingHints(RenderingHints hints) {
500:                if (equals(this .hints, hints)) {
501:                    return;
502:                }
503:                RenderingHints oldHints = this .hints;
504:                this .hints = hints;
505:                fireEvent("RenderingHints", oldHints, hints);
506:                resetPropertyEnvironment(false);
507:            }
508:
509:            /**
510:             * Adds a <code>PropertyGenerator</code> to the node.  The property values
511:             * emitted by this property generator override any previous definitions.
512:             *
513:             * @param pg A <code>PropertyGenerator</code> to be added to the
514:             *        associated node's property environment.
515:             *
516:             * @throws IllegalArgumentException if
517:             * <code>pg</code> is <code>null</code>.
518:             */
519:            public void addPropertyGenerator(PropertyGenerator pg) {
520:                if (pg == null) {
521:                    throw new IllegalArgumentException(JaiI18N
522:                            .getString("Generic0"));
523:                }
524:                localPropEnv.add(pg);
525:                if (propertySource != null) {
526:                    propertySource.addPropertyGenerator(pg);
527:                }
528:            }
529:
530:            /**
531:             * Forces a property to be copied from the specified source node.
532:             * By default, a property is copied from the first source node that
533:             * that emits it.  The result of specifying an invalid source is
534:             * undefined.
535:             *
536:             * @param propertyName the name of the property to be copied.
537:             * @param sourceIndex the index of the source to copy the property from.
538:             * @throws IllegalArgumentException if propertyName is null.
539:             */
540:            public void copyPropertyFromSource(String propertyName,
541:                    int sourceIndex) {
542:                if (propertyName == null) {
543:                    throw new IllegalArgumentException(JaiI18N
544:                            .getString("Generic0"));
545:                }
546:                localPropEnv.add(new CopyDirective(propertyName, sourceIndex));
547:                if (propertySource != null) {
548:                    propertySource.copyPropertyFromSource(propertyName,
549:                            sourceIndex);
550:                }
551:            }
552:
553:            /**
554:             * Removes a named property from the property environment of the
555:             * associated node.  Unless the property is stored locally either due
556:             * to having been set explicitly or to having been cached for property
557:             * synchronization purposes, subsequent calls to
558:             * <code>getProperty(name)</code> will return
559:             * <code>java.awt.Image.UndefinedProperty</code>, and <code>name</code>
560:             * will not appear on the list of properties emitted by
561:             * <code>getPropertyNames()</code>.
562:             *
563:             * @param name A <code>String</code> naming the property to be suppressed.
564:             *
565:             * @throws IllegalArgumentException if
566:             * <code>name</code> is <code>null</code>.
567:             */
568:            public void suppressProperty(String name) {
569:                if (name == null) {
570:                    throw new IllegalArgumentException(JaiI18N
571:                            .getString("Generic0"));
572:                }
573:                localPropEnv.add(name);
574:                if (propertySource != null) {
575:                    propertySource.suppressProperty(name);
576:                }
577:            }
578:
579:            /**
580:             * Constructs and returns a <code>PropertySource</code> suitable for
581:             * use by the specified <code>OperationNode</code>.  If the registry mode
582:             * identified by <code>getRegistryModeName()</code> supports properties,
583:             * i.e., the statement
584:             * <pre>
585:             * Registry.getMode(getRegistryModeName()).arePropertiesSupported()
586:             * </pre>
587:             * evaluates to <code>true</code>, then the <code>PropertySource</code> 
588:             * will include the global property environment as managed by the
589:             * <code>OperationRegistry</code> for the corresponding operation. 
590:             * Prior and subsequent modifications to the local property environment
591:             * made via this object will be reflected in the returned
592:             * <code>PropertySource</code>.
593:             *
594:             * @param opNode the <code>OperationNode</code> requesting its
595:             *        <code>PropertySource</code>.
596:             * @param defaultPS a <code>PropertySource</code> to be used to derive
597:             *        property values if and only if they would otherwise be
598:             *        derived by inheritance from a source rather than from a
599:             *        a <code>PropertyGenerator</code> or a copy-from-source
600:             *        directive.
601:             *
602:             * @throws IllegalArgumentException if opNode is null.
603:             *
604:             * @return A <code>PropertySource</code> including the local and, if
605:             * applicable, the global property environment for the operation.
606:             *
607:             * @see RegistryMode
608:             * @see OperationRegistry#getPropertySource(OperationNode op)
609:             */
610:            public PropertySource getPropertySource(OperationNode opNode,
611:                    PropertySource defaultPS) {
612:
613:                if (opNode == null) {
614:                    throw new IllegalArgumentException(JaiI18N
615:                            .getString("Generic0"));
616:                }
617:
618:                if (propertySource == null) {
619:                    synchronized (this ) {
620:                        RegistryMode regMode = RegistryMode
621:                                .getMode(registryModeName);
622:                        if (regMode != null && regMode.arePropertiesSupported()) {
623:                            // Get the global property environment.
624:                            propertySource = (PropertyEnvironment) registry
625:                                    .getPropertySource(opNode);
626:                        } else {
627:                            // This mode does not support properties so we create
628:                            // a default environment to permit property inheritance
629:                            // from the sources. The PropertyGenerators,
630:                            // copy-from-source directives, and suppressed properties
631:                            // are null.
632:                            propertySource = new PropertyEnvironment(
633:                                    pb != null ? pb.getSources() : null, null,
634:                                    null, null, opNode);
635:                        }
636:
637:                        // Update from the local environment.
638:                        updatePropertyEnvironment(propertySource);
639:                    }
640:                }
641:
642:                // Add the specified default source.
643:                propertySource.setDefaultPropertySource(defaultPS);
644:
645:                return propertySource;
646:            }
647:
648:            /**
649:             * Resets the property environment.  The list of local property
650:             * environment modifications made directly on this object is reset
651:             * if and only if the parameter is <code>true</code>.
652:             *
653:             * @param resetLocalEnvironment Whether to clear the list of property
654:             *        environment changes made directly on this object.
655:             */
656:            public void resetPropertyEnvironment(boolean resetLocalEnvironment) {
657:                propertySource = null;
658:                if (resetLocalEnvironment) {
659:                    localPropEnv.clear();
660:                }
661:            }
662:
663:            // Add items from local environment cache.
664:            private void updatePropertyEnvironment(PropertyEnvironment pe) {
665:                if (pe != null) { // "pe" should never null but check anyway.
666:                    synchronized (this ) {
667:                        // Add items from the local environment.
668:                        int size = localPropEnv.size();
669:                        for (int i = 0; i < size; i++) {
670:                            Object element = localPropEnv.get(i);
671:                            if (element instanceof  String) { // suppressed property
672:                                pe.suppressProperty((String) element);
673:                            } else if (element instanceof  CopyDirective) {
674:                                CopyDirective cd = (CopyDirective) element;
675:                                pe.copyPropertyFromSource(cd.getName(), cd
676:                                        .getIndex());
677:                            } else if (element instanceof  PropertyGenerator) {
678:                                pe
679:                                        .addPropertyGenerator((PropertyGenerator) element);
680:                            }
681:                        }
682:                    }
683:                }
684:            }
685:
686:            private void fireEvent(String propName, Object oldVal, Object newVal) {
687:                if (eventManager != null) {
688:                    Object eventSource = eventManager
689:                            .getPropertyChangeEventSource();
690:                    PropertyChangeEventJAI evt = new PropertyChangeEventJAI(
691:                            eventSource, propName, oldVal, newVal);
692:                    eventManager.firePropertyChange(evt);
693:                }
694:            }
695:
696:            // Note that at present in RenderedOp and RenderableOp the only
697:            // non-serializable classes handled are RenderedImage, Raster, and
698:            // RenderingHints. How should this best be handled? Should an OpNode
699:            // be forced to implement for example
700:            //
701:            //  void writePB(ParameterBlock pb, ObjectOutputStream out)
702:            //  void ParameterBlock readPB(ObjectInputStream in)
703:            //
704:            // perhaps in a SerializableOperationNode?
705:            // Or does this require a more generic approach using Proxy?
706:
707:            /**
708:             * Serializes the <code>OperationNodeSupport</code>.
709:             */
710:            private void writeObject(ObjectOutputStream out) throws IOException {
711:                ParameterBlock pbClone = pb;
712:                boolean pbCloned = false;
713:
714:                // Wrap RenderedImage sources in RenderedImageStates.
715:                for (int index = 0; index < pbClone.getNumSources(); index++) {
716:                    Object source = pbClone.getSource(index);
717:                    if (source != null && !(source instanceof  Serializable)) {
718:                        if (!pbCloned) {
719:                            pbClone = (ParameterBlock) pb.clone();
720:                            pbCloned = true;
721:                        }
722:                        if (source instanceof  RenderedImage) {
723:                            SerializableState serializableImage = SerializerFactory
724:                                    .getState(source, null);
725:                            pbClone.setSource(serializableImage, index);
726:                        } else {
727:                            throw new RuntimeException(source.getClass()
728:                                    .getName()
729:                                    + JaiI18N
730:                                            .getString("OperationNodeSupport0"));
731:                        }
732:                    }
733:                }
734:
735:                // Wrap RenderedImage parameters in RenderedImageState objects;
736:                // wrap Raster parameters in RasterState objects;
737:                // check other parameters for serializability.
738:                for (int index = 0; index < pbClone.getNumParameters(); index++) {
739:                    Object parameter = pbClone.getObjectParameter(index);
740:                    if (parameter != null
741:                            && !(parameter instanceof  Serializable)) {
742:                        if (!pbCloned) {
743:                            pbClone = (ParameterBlock) pb.clone();
744:                            pbCloned = true;
745:                        }
746:                        if (parameter instanceof  Raster) {
747:                            pbClone.set(SerializerFactory.getState(parameter,
748:                                    null), index);
749:                        } else if (parameter instanceof  RenderedImage) {
750:                            RenderedImage ri = (RenderedImage) parameter;
751:                            RenderingHints hints = new RenderingHints(null);
752:                            hints.put(JAI.KEY_SERIALIZE_DEEP_COPY, new Boolean(
753:                                    true));
754:                            pbClone.set(SerializerFactory.getState(ri, hints),
755:                                    index);
756:                        } else {
757:                            throw new RuntimeException(parameter.getClass()
758:                                    .getName()
759:                                    + JaiI18N
760:                                            .getString("OperationNodeSupport1"));
761:                        }
762:                    }
763:                }
764:
765:                // Serialize the object.
766:                // Write non-static and non-transient fields.
767:                out.defaultWriteObject();
768:                // Write ParameterBlock.
769:                out.writeObject(pbClone);
770:                // Write RenderingHints.
771:                out.writeObject(SerializerFactory.getState(hints, null));
772:            }
773:
774:            /**
775:             * Deserializes the <code>OperationNodeSupport</code>.
776:             */
777:            private synchronized void readObject(ObjectInputStream in)
778:                    throws IOException, ClassNotFoundException {
779:
780:                // Read non-static and non-transient fields.
781:                in.defaultReadObject();
782:                // Read ParameterBlock.
783:                pb = (ParameterBlock) in.readObject();
784:                // Read RenderingHints.
785:                SerializableState ss = (SerializableState) in.readObject();
786:                hints = (RenderingHints) ss.getObject();
787:
788:                // Wrap any RenderedImageState sources in PlanarImage objects.
789:                for (int index = 0; index < pb.getNumSources(); index++) {
790:                    Object source = pb.getSource(index);
791:                    if (source instanceof  SerializableState) {
792:                        ss = (SerializableState) source;
793:                        PlanarImage pi = PlanarImage
794:                                .wrapRenderedImage((RenderedImage) ss
795:                                        .getObject());
796:                        pb.setSource(pi, index);
797:                    }
798:                }
799:
800:                // Extract Raster and PlanarImage parameters from RasterState and
801:                // RenderedImageState wrappers, respectively.
802:                for (int index = 0; index < pb.getNumParameters(); index++) {
803:                    Object parameter = pb.getObjectParameter(index);
804:                    if (parameter instanceof  SerializableState) {
805:                        Object object = ((SerializableState) parameter)
806:                                .getObject();
807:                        if (object instanceof  Raster)
808:                            pb.set(object, index);
809:                        else if (object instanceof  RenderedImage)
810:                            pb.set(PlanarImage
811:                                    .wrapRenderedImage((RenderedImage) object),
812:                                    index);
813:                        else
814:                            pb.set(object, index);
815:                    }
816:                }
817:
818:                registry = JAI.getDefaultInstance().getOperationRegistry();
819:            }
820:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.