Source Code Cross Referenced for CollectionOp.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) 


0001:        /*
0002:         * $RCSfile: CollectionOp.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.2 $
0009:         * $Date: 2006/06/16 22:52:05 $
0010:         * $State: Exp $
0011:         */
0012:        package javax.media.jai;
0013:
0014:        import java.awt.RenderingHints;
0015:        import java.awt.image.RenderedImage;
0016:        import java.awt.image.renderable.ParameterBlock;
0017:        import java.awt.image.renderable.RenderContext;
0018:        import java.awt.image.renderable.RenderableImage;
0019:        import java.beans.PropertyChangeEvent;
0020:        import java.beans.PropertyChangeListener;
0021:        import java.util.Collection;
0022:        import java.util.Collections;
0023:        import java.util.Comparator;
0024:        import java.util.HashSet;
0025:        import java.util.Iterator;
0026:        import java.util.Locale;
0027:        import java.util.Set;
0028:        import java.util.SortedSet;
0029:        import java.util.TreeSet;
0030:        import java.util.Vector;
0031:        import javax.media.jai.registry.CIFRegistry;
0032:        import javax.media.jai.registry.RCIFRegistry;
0033:        import javax.media.jai.registry.CollectionRegistryMode;
0034:        import javax.media.jai.registry.RenderableCollectionRegistryMode;
0035:        import com.sun.media.jai.util.ImageUtil;
0036:        import com.sun.media.jai.util.PropertyUtil;
0037:
0038:        /**
0039:         * A node in a <code>CollectionImage</code> chain. A <code>CollectionOp</code>
0040:         * stores an operation name, a <code>ParameterBlock</code> containing sources
0041:         * and parameters, and a <code>RenderingHints</code> containing hints which
0042:         * may be used in rendering the node.  A set of nodes may be joined together
0043:         * via the source <code>Vector</code>s within their respective
0044:         * <code>ParameterBlock</code>s to form a <u>d</u>irected <u>a</u>cyclic
0045:         * <u>g</u>raph (DAG).  The topology, i.e., connectivity, of the graph may be
0046:         * altered by changing the node's sources.  The operation name, parameters,
0047:         * and rendering hints may also be changed.  A <code>CollectionOp</code> may
0048:         * be used in either the rendered or the renderable mode for
0049:         * <code>Collection</code>s, i.e., "collection" or "renderableCollection"
0050:         * mode, respectively.
0051:         *
0052:         * <p> A <code>CollectionOp</code> may be constructed directly as, for example,
0053:         * <pre>
0054:         * <code>
0055:         * Collection srcCol;
0056:         * double[] constants;
0057:         * ParameterBlock pb =
0058:         *     (new ParameterBlock()).addSource(srcCol).add(constants);
0059:         * CollectionOp node =
0060:         *     new CollectionOp("addConstToCollection", pb, null);
0061:         * </code>
0062:         * </pre>
0063:         * or by the <code>createCollection</code> or <code>createCollectionNS()</code>
0064:         * "collection" mode methods or the <code>createRenderableCollection()</code>
0065:         * or <code>createRenderableCollectionNS()</code> "renderableCollection" mode
0066:         * methods defined in the <code>JAI</code> class.  The difference between
0067:         * direct construction of a node and creation via a convenience method is that
0068:         * in the latter case:
0069:         *
0070:         * <ol>
0071:         * <li> It is verified that the operation supports the appropriate mode,
0072:         *      i.e., "collection" or "renderableCollection".</li>
0073:         * <li> It is verified that the operation generates a
0074:         *      <code>CollectionImage</code>, a <code>RenderedImage</code>
0075:         *      ("collection" mode only), or a <code>RenderableImage</code>
0076:         *      ("renderableCollection" mode only).</li>
0077:         * <li> Global <code>RenderingHints</code> maintained by the <code>JAI</code>
0078:         *      instance are merged with the local <code>RenderingHints</code> with the
0079:         *      local hints taking precedence.</li>
0080:         * <li> Using the <code>validateArguments()</code> method of the associated
0081:         *      <code>OperationDescriptor</code>, the arguments (sources and parameters)
0082:         *      are validated as being compatible with the specified operation in
0083:         *      the appropriate mode.</li>
0084:         * <li> If the arguments are valid, then the <code>CollectionOp</code> is
0085:         *      created; otherwise any source <code>Collection</code>s are
0086:         *      "unwrapped" until a valid argument list is obtained or it is
0087:         *      determined that such is impossible.
0088:         * <li> If the operation is in the rendered mode and is defined to be
0089:         *      "immediate" (the <code>isImmediate()</code> method of the corresponding
0090:         *      <code>OperationDescriptor</code> returns <code>true</code>)
0091:         *      then the node is rendered.</li>
0092:         * </ol>
0093:         *
0094:         * <p> When a chain of nodes is rendered by any means a "parallel" chain of
0095:         * <code>CollectionImage</code>s is created.  Each node in the chain of
0096:         * <code>CollectionOp</code>s corresponds to a node in the chain of
0097:         * <code>CollectionImage</code>s.  <code>Collection</code> methods invoked
0098:         * on the <code>CollectionOp</code> are in general forwarded to the associated
0099:         * <code>CollectionImage</code> which is referred to as the <i>rendering</i>
0100:         * of the node.  The rendering of the node may be a rendered or renderable
0101:         * <code>CollectionImage</code>, i.e., eventually contain
0102:         * <code>RenderedImage</code>s or <code>RenderableImage</code>s, respectively,
0103:         * depending on the mode in which the node is used.
0104:         *
0105:         * <p> The translation between <code>CollectionOp</code> chains and
0106:         * <code>CollectionImage</code> chains makes  use of two levels of
0107:         * indirection provided by the <code>OperationRegistry</code> and either the
0108:         * <code>CollectionImageFactory</code> (CIF) or the
0109:         * <code>RenderableCollectionImageFactory</code> (RCIF) facilities.
0110:         * First, the local <code>OperationRegistry</code> is used to map the
0111:         * operation name into a CIF or RCIF.  This factory then constructs
0112:         * a <code>CollectionImage</code>.  The local
0113:         * <code>OperationRegistry</code> is used in order to take advantage
0114:         * of the best possible implementation of the operation.
0115:         *
0116:         * <p> A node may be rendered explicitly by invoking the method
0117:         * <code>getCollection()</code> which also returns the rendering of the
0118:         * node.  A node may be rendered implicitly by invoking any method
0119:         * defined in the <code>Collection</code> interface.  A rendering of a
0120:         * node may also be obtained by means of the <code>createInstance()</code>
0121:         * method.  This method returns a <code>Collection</code> rendering without
0122:         * marking the node as having been rendered.  If the node is not
0123:         * marked as rendered then it will not fire
0124:         * <code>CollectionChangeEvent</code>s as described below.
0125:         *
0126:         * <p> <code>CollectionOp</code> nodes may participate in Java Bean-style
0127:         * events.  The <code>PropertyChangeEmitter</code> methods may be used
0128:         * to register and unregister <code>PropertyChangeListener</code>s.
0129:         * <code>CollectionOp</code>s are also <code>PropertyChangeListener</code>s
0130:         * so that they may be registered as listeners of other
0131:         * <code>PropertyChangeEmitter</code>s or the equivalent.  Each
0132:         * <code>CollectionOp</code> also automatically receives any
0133:         * <code>CollectionChangeEvent</code>s emitted by any of its sources which
0134:         * are also <code>CollectionOp</code>s and <code>RenderingChangeEvent</code>s
0135:         * from any <code>RenderedOp</code> sources.
0136:         *
0137:         * <p> Certain <code>PropertyChangeEvent</code>s may be emitted by the
0138:         * <code>CollectionOp</code>.  These include the
0139:         * <code>PropertyChangeEventJAI</code>s and
0140:         * <code>PropertySourceChangeEvent</code>s required by virtue of implementing
0141:         * the <code>OperationNode</code> interface.  Additionally a
0142:         * <code>CollectionChangeEvent</code> may be emitted if the node is
0143:         * operating in the "collection" mode, has already been rendered, and one of
0144:         * the following conditions is satisfied:
0145:         * <ul>
0146:         * <li>any of the critical attributes is changed (edited), i.e., the
0147:         * operation name, operation registry, node sources, parameters, or rendering
0148:         * hints; or</li>
0149:         * <li>the node receives a <code>CollectionChangeEvent</code> from one of
0150:         * its <code>CollectionOp</code> sources or a <code>RenderingChangeEvent</code>
0151:         * from one if its <code>RenderedOp</code>.</li>
0152:         * </ul>
0153:         * In either case the following sequence of actions should occur:
0154:         * <ol>
0155:         * <li> A. If the operation name or the registry has changed, a new
0156:         * <code>CollectionImage</code> will be generated by the
0157:         * <code>OperationRegistry</code> for the new operation.
0158:         * <br> B. If the operation name has not changed, an attempt will be made to
0159:         * re-use some elements of the previously generated
0160:         * <code>CollectionImage</code> by invoking <code>update()</code> on the
0161:         * <code>CollectionImageFactory</code> which generated it.  If this attempt
0162:         * fails, a new <code>CollectionImage</code> for this operation will be
0163:         * requested from the <code>OperationRegistry</code>.</li>
0164:         * <li> A <code>CollectionChangeEvent</code> will be fired to all registered
0165:         * listeners of the "Collection" <code>PropertyChangeEvent</code> and to all
0166:         * sinks which are <code>PropertyChangeListener</code>s.  The new and old
0167:         * values set on the event object correspond to the previous and current
0168:         * <code>CollectionImage</code>s, respectively, associated with this node.</li>
0169:         * </ol>
0170:         *
0171:         * <p> <code>CollectionOp</code> nodes are <code>WritablePropertySource</code>s
0172:         * and so manage a name-value database of image meta-data also known as image
0173:         * properties.  Properties may be set on and requested from a node.  The
0174:         * value of a property not explicitly set on the node (via
0175:         * <code>setProperty()</code>) is obtained from the property environment of
0176:         * the node.  When a property is derived from the property environment it is
0177:         * cached locally to ensure synchronization, i.e., that properties do not
0178:         * change spontaneously if for example the same property is modified upstream.
0179:         *
0180:         * <p> The property environment of a <code>CollectionOp</code> is initially
0181:         * derived from that of the corresponding <code>OperationDescriptor</code>
0182:         * as maintained by the <code>OperationRegistry</code>.  It may be modified
0183:         * locally by adding <code>PropertyGenerator</code>s, directives to copy
0184:         * certain properties from specific sources, or requests to suppress certain
0185:         * properties.  These modifications per se cannot be undone directly but
0186:         * may be eliminated as a side effect of other changes to the node as
0187:         * described below.
0188:         * 
0189:         * <p> When a property value is requested an attempt will be made to derive
0190:         * it from the several entities in the following order of precedence:
0191:         * <ol>
0192:         * <li> local properties; </li>
0193:         * <li> the rendering of the node if it is a <code>PropertySource</code>;</li>
0194:         * <li> any registered <code>PropertyGenerator</code>s, or
0195:         * <br> a source specified via a copy-from-source directive;</li>
0196:         * <li> the first source which defines the property. </li>
0197:         * </ol>
0198:         * Local properties are those which have been cached locally either by virtue
0199:         * of direct invocation of <code>setProperty()</code> or due to caching of a
0200:         * property derived from the property environment.
0201:         *
0202:         * <p> All dynamically computed properties of a <code>CollectionOp</code> which
0203:         * have been cached locally, i.e., those cached properties which were not set
0204:         * by an explicit call to <code>setProperty()</code>, will be cleared when any
0205:         * of the critical attributes of the node is edited.  By implication these
0206:         * properties will also be cleared when a <code>CollectionChangeEvent</code>
0207:         * is received from any node source.  The property environment or the cached
0208:         * properties may also be cleared by invoking <code>resetProperties()</code>.
0209:         *
0210:         * @see CollectionImage
0211:         * @see OperationRegistry
0212:         * @see RenderableOp
0213:         * @see RenderedOp
0214:         *
0215:         */
0216:        public class CollectionOp extends CollectionImage implements 
0217:                OperationNode, PropertyChangeListener {
0218:
0219:            /**
0220:             * An object to assist in implementing <code>OperationNode</code>.
0221:             *
0222:             * @since JAI 1.1
0223:             */
0224:            protected OperationNodeSupport nodeSupport;
0225:
0226:            /**
0227:             * The <code>PropertySource</code> containing the combined properties
0228:             * of all of the node's sources.
0229:             *
0230:             * @since JAI 1.1
0231:             */
0232:            protected PropertySource thePropertySource;
0233:
0234:            /**
0235:             * Flag indicating whether the operation is being instantiated in
0236:             * renderable mode.
0237:             *
0238:             * @since JAI 1.1
0239:             */
0240:            protected boolean isRenderable = false;
0241:
0242:            /**
0243:             * The RenderingHints when the node was last rendered, i.e., when
0244:             * "theImage" was set to its current value.
0245:             */
0246:            private transient RenderingHints oldHints;
0247:
0248:            /** Node event names. */
0249:            private static Set nodeEventNames = null;
0250:
0251:            static {
0252:                nodeEventNames = new HashSet();
0253:                nodeEventNames.add("operationname");
0254:                nodeEventNames.add("operationregistry");
0255:                nodeEventNames.add("parameterblock");
0256:                nodeEventNames.add("sources");
0257:                nodeEventNames.add("parameters");
0258:                nodeEventNames.add("renderinghints");
0259:            }
0260:
0261:            /**
0262:             * Constructs a <code>CollectionOp</code> that will be used to
0263:             * instantiate a particular <code>Collection</code> operation from a given
0264:             * operation registry, an operation name, a <code>ParameterBlock</code>,
0265:             * and a set of rendering hints.
0266:             *
0267:             * <p> This method does not validate the contents of the supplied
0268:             * <code>ParameterBlock</code>.  The caller should ensure that
0269:             * the sources and parameters in the <code>ParameterBlock</code>
0270:             * are suitable for the operation this node represents; otherwise
0271:             * some form of error or exception may occur at the time of rendering.
0272:             *
0273:             * <p> The <code>ParameterBlock</code> may include
0274:             * <code>DeferredData</code> parameters.  These will not be evaluated
0275:             * until their values are actually required, i.e., when a collection
0276:             * rendering is requested.
0277:             *
0278:             * <p> The node is added automatically as a sink of any
0279:             * <code>PlanarImage</code> or <code>CollectionImage</code> sources.
0280:             *
0281:             * @param registry  The <code>OperationRegistry</code> to be used for
0282:             *        instantiation.  if <code>null</code>, the default registry
0283:             *        is used.  Saved by reference.
0284:             * @param opName  The operation name.  Saved by reference.
0285:             * @param pb  The sources and other parameters. If <code>null</code>,
0286:             *        it is assumed that this node has no sources and parameters.
0287:             *        This parameter is cloned.
0288:             * @param hints  The rendering hints.  If <code>null</code>, it is assumed
0289:             *        that no hints are associated with the rendering.
0290:             *        This parameter is cloned.
0291:             * @param isRenderable  Whether the operation is being executed in
0292:             *	      renderable mode.
0293:             *
0294:             * @throws <code>IllegalArgumentException</code> if <code>opName</code>
0295:             *         is <code>null</code>.
0296:             *
0297:             * @since JAI 1.1
0298:             */
0299:            public CollectionOp(OperationRegistry registry, String opName,
0300:                    ParameterBlock pb, RenderingHints hints,
0301:                    boolean isRenderable) {
0302:
0303:                if (opName == null) {
0304:                    throw new IllegalArgumentException(JaiI18N
0305:                            .getString("Generic0"));
0306:                }
0307:
0308:                if (pb == null) {
0309:                    // Ensure that the PB is non-null.
0310:                    pb = new ParameterBlock();
0311:                } else {
0312:                    // Clone the PB per the doc.
0313:                    pb = (ParameterBlock) pb.clone();
0314:                }
0315:
0316:                if (hints != null) {
0317:                    // Clone the hints per the doc.
0318:                    hints = (RenderingHints) hints.clone();
0319:                }
0320:
0321:                // Initialize the various helper objects.
0322:                eventManager = new PropertyChangeSupportJAI(this );
0323:
0324:                properties = new WritablePropertySourceImpl(null, null,
0325:                        eventManager);
0326:
0327:                nodeSupport = new OperationNodeSupport(getRegistryModeName(),
0328:                        opName, registry, pb, hints, eventManager);
0329:
0330:                this .isRenderable = isRenderable;
0331:
0332:                // Add the node as a PropertyChangeListener of itself for
0333:                // the critical attributes of the node.  Case is ignored
0334:                // in the property names but infix caps are used here anyway.
0335:                addPropertyChangeListener("OperationName", this );
0336:                addPropertyChangeListener("OperationRegistry", this );
0337:                addPropertyChangeListener("ParameterBlock", this );
0338:                addPropertyChangeListener("Sources", this );
0339:                addPropertyChangeListener("Parameters", this );
0340:                addPropertyChangeListener("RenderingHints", this );
0341:
0342:                // Add self as a sink of any CollectionImage or PlanarImage sources.
0343:                Vector nodeSources = pb.getSources();
0344:                if (nodeSources != null) {
0345:                    Iterator it = nodeSources.iterator();
0346:                    while (it.hasNext()) {
0347:                        Object src = it.next();
0348:                        if (src instanceof  CollectionImage) {
0349:                            ((CollectionImage) src).addSink(this );
0350:                        } else if (src instanceof  PlanarImage) {
0351:                            ((PlanarImage) src).addSink(this );
0352:                        }
0353:                    }
0354:                }
0355:            }
0356:
0357:            /**
0358:             * Constructs a <code>CollectionOp</code> that will be used to
0359:             * instantiate a particular <code>Collection</code> operation from a given
0360:             * operation registry, an operation name, a <code>ParameterBlock</code>,
0361:             * and a set of rendering hints.  The operation will use the rendered mode.
0362:             *
0363:             * <p> This method does not validate the contents of the supplied
0364:             * <code>ParameterBlock</code>.  The caller should ensure that
0365:             * the sources and parameters in the <code>ParameterBlock</code>
0366:             * are suitable for the operation this node represents; otherwise
0367:             * some form of error or exception may occur at the time of rendering.
0368:             *
0369:             * <p> The <code>ParameterBlock</code> may include
0370:             * <code>DeferredData</code> parameters.  These will not be evaluated
0371:             * until their values are actually required, i.e., when a collection
0372:             * rendering is requested.
0373:             *
0374:             * @param registry  The <code>OperationRegistry</code> to be used for
0375:             *        instantiation.  if <code>null</code>, the default registry
0376:             *        is used.  Saved by reference.
0377:             * @param opName  The operation name.  Saved by reference.
0378:             * @param pb  The sources and other parameters. If <code>null</code>,
0379:             *        it is assumed that this node has no sources and parameters.
0380:             *        This parameter is cloned.
0381:             * @param hints  The rendering hints.  If <code>null</code>, it is assumed
0382:             *        that no hints are associated with the rendering.
0383:             *        This parameter is cloned.
0384:             *
0385:             * @throws IllegalArgumentException if <code>opName</code> is
0386:             *         <code>null</code>.
0387:             */
0388:            public CollectionOp(OperationRegistry registry, String opName,
0389:                    ParameterBlock pb, RenderingHints hints) {
0390:                this (registry, opName, pb, hints, false);
0391:            }
0392:
0393:            /**
0394:             * Constructs a <code>CollectionOp</code> that will be used to
0395:             * instantiate a particular <code>Collection</code> operation from a given
0396:             * operation name, a <code>ParameterBlock</code>, and a set of
0397:             * rendering hints.  The default operation registry is used.
0398:             *
0399:             * <p> This method does not validate the contents of the supplied
0400:             * <code>ParameterBlock</code>.  The caller should ensure that
0401:             * the sources and parameters in the <code>ParameterBlock</code>
0402:             * are suitable for the operation this node represents; otherwise
0403:             * some form of error or exception may occur at the time of rendering.
0404:             *
0405:             * <p> The <code>ParameterBlock</code> may include
0406:             * <code>DeferredData</code> parameters.  These will not be evaluated
0407:             * until their values are actually required, i.e., when a collection
0408:             * rendering is requested.
0409:             *
0410:             * @param opName  The operation name.  Saved by reference.
0411:             * @param pb  The sources and other parameters. If <code>null</code>,
0412:             *        it is assumed that this node has no sources and parameters.
0413:             *        This parameter is cloned.
0414:             * @param hints  The rendering hints.  If <code>null</code>, it is assumed
0415:             *        that no hints are associated with the rendering.
0416:             *        This parameter is cloned.
0417:             *
0418:             * @throws <code>IllegalArgumentException</code> if <code>opName</code> is
0419:             *         <code>null</code>.
0420:             */
0421:            public CollectionOp(String opName, ParameterBlock pb,
0422:                    RenderingHints hints) {
0423:                this (null, opName, pb, hints);
0424:            }
0425:
0426:            /**
0427:             * Constructs a <code>CollectionOp</code> that will be used to
0428:             * instantiate a particular <code>Collection</code> operation from a given
0429:             * operation registry, an operation name, and a
0430:             * <code>ParameterBlock</code>  There are no rendering hints
0431:             * associated with this operation.
0432:             * The operation will use the rendered mode.
0433:             *
0434:             * <p> This method does not validate the contents of the supplied
0435:             * <code>ParameterBlock</code>.  The caller should ensure that
0436:             * the sources and parameters in the <code>ParameterBlock</code>
0437:             * are suitable for the operation this node represents; otherwise
0438:             * some form of error or exception may occur at the time of rendering.
0439:             *
0440:             * <p> The <code>ParameterBlock</code> may include
0441:             * <code>DeferredData</code> parameters.  These will not be evaluated
0442:             * until their values are actually required, i.e., when a collection
0443:             * rendering is requested.
0444:             *
0445:             * @param registry  The <code>OperationRegistry</code> to be used for
0446:             *        instantiation.  if <code>null</code>, the default registry
0447:             *        is used.  Saved by reference.
0448:             * @param opName  The operation name.  Saved by reference.
0449:             * @param pb  The sources and other parameters. If <code>null</code>,
0450:             *        it is assumed that this node has no sources and parameters.
0451:             *        This parameter is cloned.
0452:             *
0453:             * @throws <code>IllegalArgumentException</code> if <code>opName</code> is
0454:             *         <code>null</code>.
0455:             *
0456:             * @deprecated as of JAI 1.1.
0457:             * @see #CollectionOp(OperationRegistry,String,ParameterBlock,RenderingHints)
0458:             */
0459:            public CollectionOp(OperationRegistry registry, String opName,
0460:                    ParameterBlock pb) {
0461:                this (registry, opName, pb, null);
0462:            }
0463:
0464:            /**
0465:             * Returns whether the operation is being instantiated in renderable mode.
0466:             *
0467:             * @since JAI 1.1
0468:             */
0469:            public boolean isRenderable() {
0470:                return isRenderable;
0471:            }
0472:
0473:            /**
0474:             * Returns the name of the <code>RegistryMode</code> corresponding to
0475:             * this <code>CollectionOp</code>.
0476:             *
0477:             * @since JAI 1.1
0478:             */
0479:            public String getRegistryModeName() {
0480:                return isRenderable ? RenderableCollectionRegistryMode.MODE_NAME
0481:                        : CollectionRegistryMode.MODE_NAME;
0482:            }
0483:
0484:            /* ----- Critical attribute accessors and mutators. ----- */
0485:
0486:            /**
0487:             * Returns the <code>OperationRegistry</code> that is used
0488:             * by this node.  If the registry had not been set, the default
0489:             * registry is returned.
0490:             */
0491:            public synchronized OperationRegistry getRegistry() {
0492:                return nodeSupport.getRegistry();
0493:            }
0494:
0495:            /**
0496:             * Sets the <code>OperationRegistry</code> that is used by
0497:             * this node.  If the specified registry is <code>null</code>, the
0498:             * default registry is used.  The parameter is saved by reference.
0499:             *
0500:             * <p> If the supplied registry does not equal the current registry, a
0501:             * <code>PropertyChangeEventJAI</code> named "OperationRegistry"
0502:             * will be fired and a <code>CollectionChangeEvent</code> may be
0503:             * fired if the node has already been rendered.
0504:             *
0505:             * @param registry  The new <code>OperationRegistry</code> to be set;
0506:             *        it may be <code>null</code>.
0507:             */
0508:            public synchronized void setRegistry(OperationRegistry registry) {
0509:                nodeSupport.setRegistry(registry);
0510:            }
0511:
0512:            /**
0513:             * Returns the name of the operation this node represents as
0514:             * a <code>String</code>.
0515:             */
0516:            public String getOperationName() {
0517:                return nodeSupport.getOperationName();
0518:            }
0519:
0520:            /**
0521:             * Sets the name of the operation this node represents.
0522:             * The parameter is saved by reference.
0523:             *
0524:             * <p> If the supplied name does not equal the current operation name, a
0525:             * <code>PropertyChangeEventJAI</code> named "OperationName"
0526:             * will be fired and a <code>CollectionChangeEvent</code> may be
0527:             * fired if the node has already been rendered.
0528:             *
0529:             * @param opName  The new operation name to be set.
0530:             *
0531:             * @throws <code>IllegalArgumentException</code> if <code>opName</code> is
0532:             *         <code>null</code>.
0533:             */
0534:            public synchronized void setOperationName(String opName) {
0535:                nodeSupport.setOperationName(opName);
0536:            }
0537:
0538:            /** Returns a clone of the <code>ParameterBlock</code> of this node. */
0539:            public ParameterBlock getParameterBlock() {
0540:                return (ParameterBlock) nodeSupport.getParameterBlock().clone();
0541:            }
0542:
0543:            /**
0544:             * Sets the <code>ParameterBlock</code> of this node.
0545:             * If the specified new <code>ParameterBlock</code> is <code>null</code>,
0546:             * it is assumed that this node has no input sources and parameters.
0547:             * The supplied parameter is cloned.
0548:             *
0549:             * <p> This method does not validate the contents of the supplied
0550:             * <code>ParameterBlock</code>.  The caller should ensure that
0551:             * the sources and parameters in the <code>ParameterBlock</code>
0552:             * are suitable for the operation this node represents; otherwise
0553:             * some form of error or exception may occur at the time of rendering.
0554:             *
0555:             * <p> If the supplied <code>ParameterBlock</code> does not equal the
0556:             * current <code>ParameterBlock</code>, a
0557:             * <code>PropertyChangeEventJAI</code> named "ParameterBlock", "Sources",
0558:             * or "Parameters" will be fired. A <code>CollectionChangeEvent</code>
0559:             * may also be fired if the node has already been rendered.
0560:             *
0561:             * <p> The <code>ParameterBlock</code> may include
0562:             * <code>DeferredData</code> parameters.  These will not be evaluated
0563:             * until their values are actually required, i.e., when a collection
0564:             * rendering is requested.
0565:             *
0566:             * <p> The node is registered as a sink of any <code>PlanarImage</code>
0567:             * or <code>CollectionImage</code> sources contained in the supplied
0568:             * <code>ParameterBlock</code>.  The node is also removed as a sink of
0569:             * any previous <code>PlanarImage</code> or <code>CollectionImage</code>
0570:             * sources if these are not in the new <code>ParameterBlock</code>.
0571:             *
0572:             * @param pb  The new <code>ParameterBlock</code> to be set;
0573:             *        it may be <code>null</code>.
0574:             */
0575:            public synchronized void setParameterBlock(ParameterBlock pb) {
0576:                Vector nodeSources = nodeSupport.getParameterBlock()
0577:                        .getSources();
0578:                if (nodeSources != null && nodeSources.size() > 0) {
0579:                    Iterator it = nodeSources.iterator();
0580:                    while (it.hasNext()) {
0581:                        Object src = it.next();
0582:                        if (src instanceof  PlanarImage) {
0583:                            ((PlanarImage) src).removeSink(this );
0584:                        } else if (src instanceof  CollectionImage) {
0585:                            ((CollectionImage) src).removeSink(this );
0586:                        }
0587:                    }
0588:                }
0589:
0590:                if (pb != null) {
0591:                    Vector newSources = pb.getSources();
0592:                    ;
0593:                    if (newSources != null && newSources.size() > 0) {
0594:                        Iterator it = newSources.iterator();
0595:                        while (it.hasNext()) {
0596:                            Object src = it.next();
0597:                            if (src instanceof  PlanarImage) {
0598:                                ((PlanarImage) src).addSink(this );
0599:                            } else if (src instanceof  CollectionImage) {
0600:                                ((CollectionImage) src).addSink(this );
0601:                            }
0602:                        }
0603:                    }
0604:                }
0605:
0606:                nodeSupport.setParameterBlock(pb == null ? new ParameterBlock()
0607:                        : (ParameterBlock) pb.clone());
0608:            }
0609:
0610:            /**
0611:             * Returns a clone of the <code>RenderingHints</code> of this node or
0612:             * <code>null</code>.
0613:             */
0614:            public RenderingHints getRenderingHints() {
0615:                RenderingHints hints = nodeSupport.getRenderingHints();
0616:                return hints == null ? null : (RenderingHints) hints.clone();
0617:            }
0618:
0619:            /**
0620:             * Sets the <code>RenderingHints</code> of this node.
0621:             * The supplied parameter is cloned if non-<code>null</code>.
0622:             *
0623:             * <p> If the supplied <code>RenderingHints</code> does not equal the
0624:             * current <code>RenderingHints</code>, a
0625:             * <code>PropertyChangeEventJAI</code> named "RenderingHints"
0626:             * will be fired and a <code>CollectionChangeEvent</code> may be
0627:             * fired if the node has already been rendered.
0628:             *
0629:             * @param hints The new <code>RenderingHints</code> to be set;
0630:             *        it may be <code>null</code>.
0631:             */
0632:            public synchronized void setRenderingHints(RenderingHints hints) {
0633:                if (hints != null) {
0634:                    hints = (RenderingHints) hints.clone();
0635:                }
0636:                nodeSupport.setRenderingHints(hints);
0637:            }
0638:
0639:            /* ----- Collection generation methods. ----- */
0640:
0641:            /**
0642:             * Returns the <code>Collection</code> rendering associated with
0643:             * this operation.
0644:             *
0645:             * <p> This method does not validate the sources and parameters
0646:             * stored in the <code>ParameterBlock</code> against the specification
0647:             * of the operation this node represents.  It is the responsibility
0648:             * of the caller to ensure that the data in the
0649:             * <code>ParameterBlock</code> are suitable for this operation.
0650:             * Otherwise, some kind of exception or error will occur.  Invoking
0651:             * this method will cause any <code>DeferredData</code> parameters
0652:             * in the <code>ParameterBlock</code> to be evaluated.
0653:             *
0654:             * <p> Invoking this method will cause any source <code>RenderedOp</code>
0655:             * nodes to be rendered using <code>getRendering()</code> and any
0656:             * source <code>CollectionOp</code> nodes to be rendered using
0657:             * <code>getCollection()</code>.  Any <code>DeferredData</code> parameters
0658:             * in the <code>ParameterBlock</code> will also be evaluated.
0659:             *
0660:             * @throws RuntimeException if the image factory charged with rendering
0661:             *         the node is unable to create a rendering.
0662:             */
0663:            public Collection getCollection() {
0664:                createCollection();
0665:                return imageCollection;
0666:            }
0667:
0668:            /** Creates a <code>Collection</code> rendering if none exists. */
0669:            private synchronized void createCollection() {
0670:                if (imageCollection == null) {
0671:                    imageCollection = createInstance(true);
0672:                }
0673:            }
0674:
0675:            /**
0676:             * Instantiates a <code>Collection</code> operator that computes
0677:             * the result of this <code>CollectionOp</code>.
0678:             *
0679:             * <p> This method does not validate the sources and parameters
0680:             * stored in the <code>ParameterBlock</code> against the specification
0681:             * of the operation this node represents.  It is the responsibility
0682:             * of the caller to ensure that the data in the
0683:             * <code>ParameterBlock</code> are suitable for this operation.
0684:             * Otherwise, some kind of exception or error will occur.
0685:             *
0686:             * <p> Invoking this method will cause any source <code>RenderedOp</code>
0687:             * or <code>CollectionOp</code> nodes to be rendered using their
0688:             * respective <code>createInstance()</code> methods.  Any
0689:             * <code>DeferredData</code> parameters in the <code>ParameterBlock</code>
0690:             * will also be evaluated.
0691:             *
0692:             * @throws RuntimeException if the image factory charged with rendering
0693:             *         the node is unable to create a rendering.
0694:             */
0695:            public synchronized Collection createInstance() {
0696:                return createInstance(false);
0697:            }
0698:
0699:            /**
0700:             * This method performs the actions described by the documentation of
0701:             * <code>createInstance()</code>.  The parameter value selects the method
0702:             * used to render the source(s).
0703:             *
0704:             * @throws RuntimeException if the image factory charged with rendering
0705:             *         the node is unable to create a rendering.
0706:             */
0707:            private synchronized Collection createInstance(boolean isChainFrozen) {
0708:                // Get the PB evaluating any DeferredData objects in the process.
0709:                ParameterBlock args = ImageUtil.evaluateParameters(nodeSupport
0710:                        .getParameterBlock());
0711:
0712:                ParameterBlock pb = new ParameterBlock();
0713:                pb.setParameters(args.getParameters());
0714:
0715:                int numSources = args.getNumSources();
0716:                for (int i = 0; i < numSources; i++) {
0717:                    Object source = args.getSource(i);
0718:                    Object src = null;
0719:
0720:                    if (source instanceof  RenderedOp) {
0721:                        src = isChainFrozen ? ((RenderedOp) source)
0722:                                .getRendering() : ((RenderedOp) source)
0723:                                .createInstance();
0724:                    } else if (source instanceof  CollectionOp) {
0725:                        CollectionOp co = (CollectionOp) source;
0726:                        src = isChainFrozen ? co.getCollection() : co
0727:                                .createInstance();
0728:                    } else if (source instanceof  RenderedImage
0729:                            || source instanceof  RenderableImage
0730:                            || source instanceof  Collection) {
0731:                        src = source;
0732:                    } else {
0733:                        // Source is some other type. Pass on (for now).
0734:                        src = source;
0735:                    }
0736:                    pb.addSource(src);
0737:                }
0738:
0739:                Collection instance = null;
0740:                if (isRenderable) {
0741:                    instance = RCIFRegistry.create(nodeSupport.getRegistry(),
0742:                            nodeSupport.getOperationName(), pb);
0743:                } else {
0744:                    CollectionImageFactory cif = CIFRegistry.get(nodeSupport
0745:                            .getRegistry(), nodeSupport.getOperationName());
0746:                    instance = cif.create(pb, nodeSupport.getRenderingHints());
0747:
0748:                    // Set the CollectionImageFactory on the result.
0749:                    if (instance != null) {
0750:                        ((CollectionImage) instance).setImageFactory(cif);
0751:                    }
0752:                }
0753:
0754:                // Throw an error if the rendering is null.
0755:                if (instance == null) {
0756:                    throw new RuntimeException(JaiI18N
0757:                            .getString("CollectionOp0"));
0758:                }
0759:
0760:                // Save the RenderingHints.
0761:                oldHints = nodeSupport.getRenderingHints() == null ? null
0762:                        : (RenderingHints) nodeSupport.getRenderingHints()
0763:                                .clone();
0764:
0765:                return instance;
0766:            }
0767:
0768:            /**
0769:             * Returns the <code>Collection</code> rendering associated with this
0770:             * operation with any contained <code>RenderableImage</code>s rendered
0771:             * using the supplied <code>RenderContext</code> parameter.  If the
0772:             * operation is being executed in rendered mode
0773:             * (<code>isRenderable()</code> returns <code>false</code>), invoking
0774:             * this method is equivalent to invoking <code>getCollection()</code>,
0775:             * i.e., the parameter is ignored.  If the operation is being
0776:             * executed in renderable mode, the <code>Collection</code> will differ
0777:             * from that returned by <code>getCollection()</code> due to any contained
0778:             * <code>RenderableImage</code>s having been rendered.  If the
0779:             * <code>Collection</code> contains any nested <code>Collection</code>s,
0780:             * these will be unwrapped recursively such that a rendering is created
0781:             * for all <code>RenderableImage</code>s encountered.  Any
0782:             * <code>RenderingHints</code> in the <code>RenderContext</code> are
0783:             * merged with those set on the node with the argument hints taking
0784:             * precedence.
0785:             *
0786:             * @since JAI 1.1
0787:             */
0788:            public Collection createRendering(RenderContext renderContext) {
0789:                if (!isRenderable) {
0790:                    return this ;
0791:                }
0792:
0793:                // Merge argument hints with node hints.
0794:                RenderingHints mergedHints = JAI.mergeRenderingHints(
0795:                        nodeSupport.getRenderingHints(), renderContext
0796:                                .getRenderingHints());
0797:                if (mergedHints != renderContext.getRenderingHints()) {
0798:                    renderContext = (RenderContext) renderContext.clone();
0799:                    renderContext.setRenderingHints(mergedHints);
0800:                }
0801:
0802:                return renderCollection(imageCollection, renderContext);
0803:            }
0804:
0805:            /**
0806:             * Returns a new <code>Collection</code> with any
0807:             * <code>RenderableImage</code>s rendered using the supplied
0808:             * <code>RenderContext</code>.  This method is re-entrant and
0809:             * invokes itself if there is a nested <code>Collection</code>.
0810:             */
0811:            private Collection renderCollection(Collection cIn, RenderContext rc) {
0812:                if (cIn == null || rc == null) {
0813:                    throw new IllegalArgumentException(); // no message.
0814:                }
0815:
0816:                Collection cOut;
0817:                if (cIn instanceof  Set) {
0818:                    cOut = Collections.synchronizedSet(new HashSet(cIn.size()));
0819:                } else if (cIn instanceof  SortedSet) {
0820:                    Comparator comparator = ((SortedSet) cIn).comparator();
0821:                    cOut = Collections.synchronizedSortedSet(new TreeSet(
0822:                            comparator));
0823:                } else {
0824:                    cOut = new Vector(cIn.size());
0825:                }
0826:
0827:                Iterator it = cIn.iterator();
0828:                while (it.hasNext()) {
0829:                    Object element = it.next();
0830:                    if (element instanceof  RenderableImage) {
0831:                        cOut.add(((RenderableImage) cIn).createRendering(rc));
0832:                    } else if (element instanceof  Collection) {
0833:                        cOut.add(renderCollection((Collection) element, rc));
0834:                    } else {
0835:                        cOut.add(element);
0836:                    }
0837:                }
0838:
0839:                return cOut;
0840:            }
0841:
0842:            /* ----- PropertyChangeListener method. ----- */
0843:
0844:            /**
0845:             * Implementation of <code>PropertyChangeListener</code>.
0846:             *
0847:             * <p> When invoked with an event which is an instance of either
0848:             * <code>CollectionChangeEvent</code> or
0849:             * <code>RenderingChangeEvent</code> emitted by a
0850:             * <code>CollectionOp</code> or <code>RenderedOp</code> source,
0851:             * respectively, the node will respond by
0852:             * re-rendering itself while retaining any data possible.
0853:             *
0854:             * @since JAI 1.1
0855:             */
0856:            public synchronized void propertyChange(PropertyChangeEvent evt) {
0857:                // If this is a renderable node just return as CollectionChangeEvents
0858:                // should not be emitted for "renderablecollection" mode.
0859:                if (isRenderable())
0860:                    return;
0861:
0862:                //
0863:                // React if and only if the node has been rendered and
0864:                // A: a non-PropertySourceChangeEvent PropertyChangeEventJAI
0865:                //    was received from this node, or
0866:                // B: a CollectionChangeEvent was received from a source node, or
0867:                // C: a RenderingChangeEvent was received from a source node.
0868:                //
0869:
0870:                // Cache event and node sources.
0871:                Object evtSrc = evt.getSource();
0872:                Vector nodeSources = nodeSupport.getParameterBlock()
0873:                        .getSources();
0874:
0875:                // Get the name of the bean property and convert it to lower
0876:                // case now for efficiency later.
0877:                String propName = evt.getPropertyName().toLowerCase(
0878:                        Locale.ENGLISH);
0879:
0880:                if (imageCollection != null
0881:                        && ((evt instanceof  PropertyChangeEventJAI
0882:                                && evtSrc == this 
0883:                                && !(evt instanceof  PropertySourceChangeEvent) && nodeEventNames
0884:                                .contains(propName)) || ((evt instanceof  CollectionChangeEvent || evt instanceof  RenderingChangeEvent) && nodeSources
0885:                                .contains(evtSrc)))) {
0886:
0887:                    // Save the previous rendering.
0888:                    Collection theOldCollection = imageCollection;
0889:
0890:                    // Initialize the event flag.
0891:                    boolean fireEvent = false;
0892:
0893:                    if (!(imageCollection instanceof  CollectionImage)) {
0894:
0895:                        // Collection is not a CollectionImage so no update possible;
0896:                        // invalidate the entire rendering.
0897:                        fireEvent = true;
0898:                        imageCollection = null;
0899:
0900:                    } else if (evtSrc == this 
0901:                            && (propName.equals("operationname") || propName
0902:                                    .equals("operationregistry"))) {
0903:
0904:                        // Operation name or OperationRegistry changed:
0905:                        // invalidate the entire rendering.
0906:                        fireEvent = true;
0907:                        imageCollection = null;
0908:
0909:                    } else if (evt instanceof  CollectionChangeEvent) {
0910:
0911:                        // Set the event flag.
0912:                        fireEvent = true;
0913:
0914:                        // Save the previous image factory.  We know that the old
0915:                        // Collection is a CollectionImage or the first branch of
0916:                        // the if-block would have been entered above.
0917:                        CollectionImageFactory oldCIF = ((CollectionImage) theOldCollection)
0918:                                .getImageFactory();
0919:
0920:                        if (oldCIF == null) {
0921:
0922:                            // The factory is null: no update possible.
0923:                            imageCollection = null;
0924:
0925:                        } else {
0926:
0927:                            // CollectionChangeEvent from a source CollectionOp.
0928:                            CollectionChangeEvent ccEvent = (CollectionChangeEvent) evt;
0929:
0930:                            // Construct old and new ParameterBlocks.
0931:                            Vector parameters = nodeSupport.getParameterBlock()
0932:                                    .getParameters();
0933:                            parameters = ImageUtil
0934:                                    .evaluateParameters(parameters);
0935:                            ParameterBlock oldPB = new ParameterBlock(
0936:                                    (Vector) nodeSources.clone(), parameters);
0937:                            ParameterBlock newPB = new ParameterBlock(
0938:                                    (Vector) nodeSources.clone(), parameters);
0939:                            int sourceIndex = nodeSources.indexOf(ccEvent
0940:                                    .getSource());
0941:                            oldPB.setSource(ccEvent.getOldValue(), sourceIndex);
0942:                            newPB.setSource(ccEvent.getNewValue(), sourceIndex);
0943:
0944:                            // Update the collection.
0945:                            imageCollection = oldCIF.update(oldPB, oldHints,
0946:                                    newPB, oldHints,
0947:                                    (CollectionImage) theOldCollection, this );
0948:                        }
0949:
0950:                    } else {
0951:                        // not op name, registry change, nor CollectionChangeEvent
0952:
0953:                        // Save the previous image factory.
0954:                        CollectionImageFactory oldCIF = ((CollectionImage) theOldCollection)
0955:                                .getImageFactory();
0956:
0957:                        if (oldCIF == null
0958:                                || oldCIF != CIFRegistry.get(nodeSupport
0959:                                        .getRegistry(), nodeSupport
0960:                                        .getOperationName())) {
0961:
0962:                            // Impossible to update unless the old and new CIFs
0963:                            // are equal and non-null.
0964:                            imageCollection = null;
0965:
0966:                            // Set event flag.
0967:                            fireEvent = true;
0968:
0969:                        } else {
0970:
0971:                            // Attempt to update the Collection rendering.
0972:
0973:                            ParameterBlock oldPB = null;
0974:                            ParameterBlock newPB = null;
0975:
0976:                            boolean updateCollection = false;
0977:
0978:                            if (propName.equals("parameterblock")) {
0979:                                oldPB = (ParameterBlock) evt.getOldValue();
0980:                                newPB = (ParameterBlock) evt.getNewValue();
0981:                                updateCollection = true;
0982:                            } else if (propName.equals("sources")) {
0983:                                // Replace source(s)
0984:                                Vector params = nodeSupport.getParameterBlock()
0985:                                        .getParameters();
0986:                                oldPB = new ParameterBlock((Vector) evt
0987:                                        .getOldValue(), params);
0988:                                newPB = new ParameterBlock((Vector) evt
0989:                                        .getNewValue(), params);
0990:                                updateCollection = true;
0991:                            } else if (propName.equals("parameters")) {
0992:                                // Replace parameter(s)
0993:                                oldPB = new ParameterBlock(nodeSources,
0994:                                        (Vector) evt.getOldValue());
0995:                                newPB = new ParameterBlock(nodeSources,
0996:                                        (Vector) evt.getNewValue());
0997:                                updateCollection = true;
0998:                            } else if (propName.equals("renderinghints")) {
0999:                                oldPB = newPB = nodeSupport.getParameterBlock();
1000:                                updateCollection = true;
1001:                            } else if (evt instanceof  RenderingChangeEvent) {
1002:                                // Event from a RenderedOp source.
1003:
1004:                                // Replace appropriate source.
1005:                                int renderingIndex = nodeSources.indexOf(evt
1006:                                        .getSource());
1007:                                Vector oldSources = (Vector) nodeSources
1008:                                        .clone();
1009:                                Vector newSources = (Vector) nodeSources
1010:                                        .clone();
1011:                                oldSources.set(renderingIndex, evt
1012:                                        .getOldValue());
1013:                                newSources.set(renderingIndex, evt
1014:                                        .getNewValue());
1015:
1016:                                Vector params = nodeSupport.getParameterBlock()
1017:                                        .getParameters();
1018:
1019:                                oldPB = new ParameterBlock(oldSources, params);
1020:                                newPB = new ParameterBlock(newSources, params);
1021:
1022:                                updateCollection = true;
1023:                            }
1024:
1025:                            if (updateCollection) {
1026:                                // Set event flag.
1027:                                fireEvent = true;
1028:
1029:                                // Evaluate any DeferredData parameters.
1030:                                oldPB = ImageUtil.evaluateParameters(oldPB);
1031:                                newPB = ImageUtil.evaluateParameters(newPB);
1032:
1033:                                // Update the collection.
1034:                                RenderingHints newHints = nodeSupport
1035:                                        .getRenderingHints();
1036:                                if ((imageCollection = oldCIF.update(oldPB,
1037:                                        oldHints, newPB, newHints,
1038:                                        (CollectionImage) theOldCollection,
1039:                                        this )) != null) {
1040:                                    oldHints = newHints;
1041:                                }
1042:                            }
1043:                        }
1044:                    }
1045:
1046:                    // Re-render the node. This will only occur if imageCollection
1047:                    // has been set to null above.
1048:                    getCollection();
1049:
1050:                    // Fire an event if the flag was set.
1051:                    if (fireEvent) {
1052:                        // Clear the synthetic and cached properties and reset the
1053:                        // property source.
1054:                        resetProperties(true);
1055:
1056:                        // Create the event object.
1057:                        CollectionChangeEvent ccEvent = new CollectionChangeEvent(
1058:                                this , theOldCollection, imageCollection);
1059:
1060:                        // Fire to all registered listeners.
1061:                        eventManager.firePropertyChange(ccEvent);
1062:
1063:                        // Fire to all PropertyChangeListener sinks.
1064:                        Set sinks = getSinks();
1065:                        if (sinks != null) {
1066:                            Iterator it = sinks.iterator();
1067:                            while (it.hasNext()) {
1068:                                Object sink = it.next();
1069:                                if (sink instanceof  PropertyChangeListener) {
1070:                                    ((PropertyChangeListener) sink)
1071:                                            .propertyChange(ccEvent);
1072:                                }
1073:                            }
1074:                        }
1075:                    }
1076:                }
1077:            }
1078:
1079:            /* ----- Property-related methods. ----- */
1080:
1081:            /** Creates a <code>PropertySource</code> if none exists. */
1082:            private synchronized void createPropertySource() {
1083:                if (thePropertySource == null) {
1084:                    getCollection();
1085:
1086:                    PropertySource defaultPS = null;
1087:                    if (imageCollection instanceof  PropertySource) {
1088:                        // Create a <code>PropertySource</code> wrapper of the rendering.
1089:                        defaultPS = new PropertySource() {
1090:                            /**
1091:                             * Retrieve the names from an instance of the node.
1092:                             */
1093:                            public String[] getPropertyNames() {
1094:                                return ((PropertySource) imageCollection)
1095:                                        .getPropertyNames();
1096:                            }
1097:
1098:                            public String[] getPropertyNames(String prefix) {
1099:                                return PropertyUtil.getPropertyNames(
1100:                                        getPropertyNames(), prefix);
1101:                            }
1102:
1103:                            public Class getPropertyClass(String name) {
1104:                                return null;
1105:                            }
1106:
1107:                            /**
1108:                             * Retrieve the actual property values from a
1109:                             * rendering of the node.
1110:                             */
1111:                            public Object getProperty(String name) {
1112:                                return ((PropertySource) imageCollection)
1113:                                        .getProperty(name);
1114:                            }
1115:                        };
1116:                    }
1117:
1118:                    // Create a <code>PropertySource</code> encapsulating the
1119:                    // property environment of the node.
1120:                    thePropertySource = nodeSupport.getPropertySource(this ,
1121:                            defaultPS);
1122:
1123:                    // Add the <code>PropertySource</code> to the helper object.
1124:                    properties.addProperties(thePropertySource);
1125:                }
1126:            }
1127:
1128:            /**
1129:             * Resets the <code>PropertySource</code>.  If the parameter is
1130:             * <code>true</code> then the property environment is completely
1131:             * reset; if <code>false</code> then only cached properties are
1132:             * cleared, i.e., those which were derived from the property
1133:             * environment and are now stored in the local cache.
1134:             *
1135:             * @since JAI 1.1
1136:             */
1137:            protected synchronized void resetProperties(
1138:                    boolean resetPropertySource) {
1139:                properties.clearCachedProperties();
1140:                if (resetPropertySource && thePropertySource != null) {
1141:                    properties.removePropertySource(thePropertySource);
1142:                    thePropertySource = null;
1143:                }
1144:            }
1145:
1146:            /**
1147:             * Returns the names of properties available from this node.
1148:             * These properties are a combination of those derived
1149:             * from prior nodes in the operation chain and those set locally.
1150:             *
1151:             * @return An array of <code>String</code>s containing valid
1152:             *         property names or <code>null</code> if there are none.
1153:             *
1154:             * @since JAI 1.1
1155:             */
1156:            public synchronized String[] getPropertyNames() {
1157:                createPropertySource();
1158:                return properties.getPropertyNames();
1159:            }
1160:
1161:            /**
1162:             * Returns the class expected to be returned by a request for
1163:             * the property with the specified name.  If this information
1164:             * is unavailable, <code>null</code> will be returned.
1165:             *
1166:             * @return The <code>Class</code> expected to be return by a
1167:             *         request for the value of this property or <code>null</code>.
1168:             * @exception IllegalArgumentException if <code>name</code>
1169:             *                                     is <code>null</code>.
1170:             *
1171:             * @since JAI 1.1
1172:             */
1173:            public Class getPropertyClass(String name) {
1174:                createPropertySource();
1175:                return properties.getPropertyClass(name);
1176:            }
1177:
1178:            /**
1179:             * Gets a property from the property set of this <code>Collection</code>.
1180:             * If the property name is not recognized,
1181:             * <code>java.awt.Image.UndefinedProperty</code> will be returned.
1182:             *
1183:             * @param name the name of the property to get, as a String.
1184:             * @return a reference to the property Object, or the value
1185:             *         java.awt.Image.UndefinedProperty.
1186:             * @exception IllegalArgumentException if <code>name</code>
1187:             *                                     is <code>null</code>.
1188:             *
1189:             * @since JAI 1.1
1190:             */
1191:            public Object getProperty(String name) {
1192:                createPropertySource();
1193:                return properties.getProperty(name);
1194:            }
1195:
1196:            /**
1197:             * Sets a local property on a node.  Local property settings override
1198:             * properties derived from prior nodes in the operation chain.
1199:             *
1200:             * @param name a String representing the property name.
1201:             * @param value the property's value, as an Object.
1202:             * @exception IllegalArgumentException if <code>name</code>
1203:             *                                     or <code>value</code>
1204:             *                                     is <code>null</code>.
1205:             *
1206:             * @since JAI 1.1
1207:             */
1208:            public void setProperty(String name, Object value) {
1209:                createPropertySource();
1210:                properties.setProperty(name, value);
1211:            }
1212:
1213:            /**
1214:             * Removes the named property from the local property
1215:             * set of the <code>CollectionOp</code> as well as from its property
1216:             * environment.
1217:             *
1218:             * @exception IllegalArgumentException if <code>name</code>
1219:             *                                     is <code>null</code>.
1220:             *
1221:             * @since JAI 1.1
1222:             */
1223:            public void removeProperty(String name) {
1224:                createPropertySource();
1225:                properties.removeProperty(name);
1226:            }
1227:
1228:            /**
1229:             * Returns the property associated with the specified property name,
1230:             * or <code>java.awt.Image.UndefinedProperty</code> if the specified
1231:             * property is not set on the image.  This method is dynamic in the
1232:             * sense that subsequent invocations of this method on the same object
1233:             * may return different values as a function of changes in the property
1234:             * environment of the node, e.g., a change in which
1235:             * <code>PropertyGenerator</code>s are registered or in the values
1236:             * associated with properties of node sources.  The case of the property
1237:             * name passed to this method is ignored.
1238:             *
1239:             * @param name A <code>String</code> naming the property.
1240:             *
1241:             * @throws IllegalArgumentException if 
1242:             *         <code>name</code> is <code>null</code>.
1243:             *
1244:             * @since JAI 1.1
1245:             */
1246:            public synchronized Object getDynamicProperty(String name) {
1247:                createPropertySource();
1248:                return thePropertySource.getProperty(name);
1249:            }
1250:
1251:            /**
1252:             * Adds a PropertyGenerator to the node.  The property values
1253:             * emitted by this property generator override any previous
1254:             * definitions.
1255:             *
1256:             * @param pg a PropertyGenerator to be added to this node's
1257:             *        property environment.
1258:             *
1259:             * @since JAI 1.1
1260:             */
1261:            public void addPropertyGenerator(PropertyGenerator pg) {
1262:                nodeSupport.addPropertyGenerator(pg);
1263:            }
1264:
1265:            /**
1266:             * Forces a property to be copied from the specified source node.
1267:             * By default, a property is copied from the first source node
1268:             * that emits it.  The result of specifying an invalid source is
1269:             * undefined.
1270:             *
1271:             * @param propertyName the name of the property to be copied.
1272:             * @param sourceIndex the index of the from which to copy the property.
1273:             * @throws IllegalArgumentException if <code>propertyName</code> is
1274:             *         <code>null</code>.
1275:             *
1276:             * @since JAI 1.1
1277:             */
1278:            public synchronized void copyPropertyFromSource(
1279:                    String propertyName, int sourceIndex) {
1280:                nodeSupport.copyPropertyFromSource(propertyName, sourceIndex);
1281:            }
1282:
1283:            /**
1284:             * Removes a named property from the property environment of this
1285:             * node.  Unless the property is stored locally either due
1286:             * to having been set explicitly via <code>setProperty()</code>
1287:             * or to having been cached for property
1288:             * synchronization purposes, subsequent calls to
1289:             * <code>getProperty(name)</code> will return
1290:             * <code>java.awt.Image.UndefinedProperty</code>, and <code>name</code> 
1291:             * will not appear on the list of properties emitted by
1292:             * <code>getPropertyNames()</code>.  To delete the property from the
1293:             * local property set of the node, <code>removeProperty()</code> should
1294:             * be used.
1295:             *
1296:             * @param name a String naming the property to be suppressed.
1297:             * @throws <code>IllegalArgumentException</code> if 
1298:             * <code>name</code> is <code>null</code>.
1299:             *
1300:             * @since JAI 1.1
1301:             */
1302:            public void suppressProperty(String name) {
1303:                nodeSupport.suppressProperty(name);
1304:            }
1305:
1306:            /*****************************************************************
1307:             * The following methods override public or protected methods in *
1308:             * CollectionImage thus causing the Collection to be created.    *
1309:             *****************************************************************/
1310:
1311:            /**
1312:             * Creates the <code>Collection</code> rendering if none yet exists, and
1313:             * returns the number of elements in this <code>Collection</code>.
1314:             */
1315:            public int size() {
1316:                createCollection();
1317:                return imageCollection.size();
1318:            }
1319:
1320:            /**
1321:             * Creates the <code>Collection</code> rendering if none yet exists, and
1322:             * returns <code>true</code> if this <code>Collection</code> contains
1323:             * no element.
1324:             */
1325:            public boolean isEmpty() {
1326:                createCollection();
1327:                return imageCollection.isEmpty();
1328:            }
1329:
1330:            /**
1331:             * Creates the <code>Collection</code> rendering if none yet exists, and
1332:             * returns <code>true</code> if this <code>Collection</code> contains
1333:             * the specified object.
1334:             */
1335:            public boolean contains(Object o) {
1336:                createCollection();
1337:                return imageCollection.contains(o);
1338:            }
1339:
1340:            /**
1341:             * Creates the <code>Collection</code> rendering if none yet exists, and
1342:             * returns an <code>Iterator</code> over the elements in this
1343:             * <code>Collection</code>.
1344:             */
1345:            public Iterator iterator() {
1346:                createCollection();
1347:                return imageCollection.iterator();
1348:            }
1349:
1350:            /**
1351:             * Creates the <code>Collection</code> rendering if none yet exists, and
1352:             * returns an array containing all of the elements in this
1353:             * <code>Collection</code>.
1354:             */
1355:            public Object[] toArray() {
1356:                createCollection();
1357:                return imageCollection.toArray();
1358:            }
1359:
1360:            /**
1361:             * Creates the <code>Collection</code> rendering if none yet exists, and
1362:             * returns an array containing all of the elements in this
1363:             * <code>Collection</code> whose runtime type is that of the specified
1364:             * array.
1365:             *
1366:             * @throws <code>ArrayStoreException</code> if the runtime type of the
1367:             *         specified array is not a supertype of the runtime type of
1368:             *         every element in this <code>Collection</code>.
1369:             */
1370:            public Object[] toArray(Object[] a) {
1371:                createCollection();
1372:                return imageCollection.toArray(a);
1373:            }
1374:
1375:            /**
1376:             * Creates the <code>Collection</code> rendering if none yet exists, and
1377:             * adds the specified object to this <code>Collection</code>.
1378:             */
1379:            public boolean add(Object o) {
1380:                createCollection();
1381:                return imageCollection.add(o);
1382:            }
1383:
1384:            /**
1385:             * Creates the <code>Collection</code> rendering if none yet exists, and
1386:             * removes the specified object from this <code>Collection</code>.
1387:             */
1388:            public boolean remove(Object o) {
1389:                createCollection();
1390:                return imageCollection.remove(o);
1391:            }
1392:
1393:            /**
1394:             * Creates the <code>Collection</code> rendering if none yet exists, and
1395:             * returns <code>true</code> if this <code>Collection</code> contains
1396:             * all of the elements in the specified <code>Collection</code>.
1397:             */
1398:            public boolean containsAll(Collection c) {
1399:                createCollection();
1400:                return imageCollection.containsAll(c);
1401:            }
1402:
1403:            /**
1404:             * Creates the <code>Collection</code> rendering if none yet exists, and
1405:             * adds all of the elements in the specified <code>Collection</code>
1406:             * to this <code>Collection</code>.
1407:             */
1408:            public boolean addAll(Collection c) {
1409:                createCollection();
1410:                return imageCollection.addAll(c);
1411:            }
1412:
1413:            /**
1414:             * Creates the <code>Collection</code> rendering if none yet exists, and
1415:             * removes all this <code>Collection</code>'s elements that are also
1416:             * contained in the specified <code>Collection</code>.
1417:             */
1418:            public boolean removeAll(Collection c) {
1419:                createCollection();
1420:                return imageCollection.removeAll(c);
1421:            }
1422:
1423:            /**
1424:             * Creates the <code>Collection</code> rendering if none yet exists, and
1425:             * retains only the elements in this <code>Collection</code> that are
1426:             * contained in the specified <code>Collection</code>.
1427:             */
1428:            public boolean retainAll(Collection c) {
1429:                createCollection();
1430:                return imageCollection.retainAll(c);
1431:            }
1432:
1433:            /**
1434:             * Creates the <code>Collection</code> rendering if none yet exists, and
1435:             * removes all of the elements from this <code>Collection</code>.
1436:             */
1437:            public void clear() {
1438:                createCollection();
1439:                imageCollection.clear();
1440:            }
1441:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.