Source Code Cross Referenced for AbstractFactory.java in  » GIS » GeoTools-2.4.1 » org » geotools » factory » 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 » GIS » GeoTools 2.4.1 » org.geotools.factory 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005:         *
006:         *    This library is free software; you can redistribute it and/or
007:         *    modify it under the terms of the GNU Lesser General Public
008:         *    License as published by the Free Software Foundation;
009:         *    version 2.1 of the License.
010:         *
011:         *    This library is distributed in the hope that it will be useful,
012:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014:         *    Lesser General Public License for more details.
015:         */
016:        package org.geotools.factory;
017:
018:        // J2SE dependencies
019:        import java.util.Map;
020:        import java.util.HashSet;
021:        import java.util.LinkedHashMap;
022:        import java.util.IdentityHashMap;
023:        import java.util.Collections;
024:        import java.util.Iterator;
025:        import java.io.Writer;
026:        import java.io.IOException;
027:        import java.awt.RenderingHints;
028:        import javax.imageio.spi.ServiceRegistry;
029:        import javax.imageio.spi.RegisterableService;
030:
031:        // OpenGIS dependencies
032:        import org.opengis.referencing.AuthorityFactory;
033:
034:        // Geotools dependencies
035:        import org.geotools.io.TableWriter;
036:        import org.geotools.resources.Utilities;
037:        import org.geotools.resources.i18n.Errors;
038:        import org.geotools.resources.i18n.ErrorKeys;
039:
040:        /**
041:         * Skeletal implementation of factories. This base classe provides no {@code createFoo} methods,
042:         * (they must be provided by subclasses), but provides two convenience features:
043:         * <p>
044:         * <ul>
045:         *   <li>An initially empty {@linkplain #hints map of hints} to be filled by subclasses
046:         *       constructors. They are the hints to be returned by {@link #getImplementationHints}.</li>
047:         *   <li>An automatic {@linkplain ServiceRegistry#setOrdering ordering} applied
048:         *       on the basis of subclasses-provided {@linkplain #priority} rank.</li>
049:         * </ul>
050:         * <p>
051:         * When more than one factory implementation is
052:         * {@linkplain ServiceRegistry#registerServiceProvider registered} for the same category (i.e. they
053:         * implement the same {@link Factory} sub-interface), the actual instance to be used is selected
054:         * according their {@linkplain ServiceRegistry#setOrdering ordering} and user-supplied
055:         * {@linkplain Hints hints}. Hints have precedence. If more than one factory matches the hints
056:         * (including the common case where the user doesn't provide any hint at all), then ordering
057:         * matter.
058:         * <p>
059:         * The ordering is unspecified for every pairs of factories with the same {@linkplain #priority}.
060:         * This implies that the ordering is unspecified between all factories created with the
061:         * {@linkplain #AbstractFactory() default constructor}, since they all have the same
062:         * {@linkplain #NORMAL_PRIORITY default priority} level.
063:         *
064:         * <h3>How hints are set</h3>
065:         * Hints are used for two purposes. The distinction is important because the set
066:         * of hints may not be identical in both cases:
067:         * <p>
068:         * <ol>
069:         *   <li>Hints are used for creating new factories.</li>
070:         *   <li>Hints are used in order to check if an <em>existing</em> factory is suitable.</li>
071:         * </ol>
072:         * <p>
073:         * {@code AbstractFactory} do <strong>not</strong> provides any facility for the first case.
074:         * Factories implementations shall inspect themselves all relevant hints supplied by the user,
075:         * and pass them to any dependencies. Do <strong>not</strong> use the {@link #hints} field for
076:         * that; use the hints provided by the user in the constructor. If all dependencies are created
077:         * at construction time (<cite>constructor injection</cite>), there is no need to keep user's hints
078:         * once the construction is finished.
079:         * <p>
080:         * The {@link #hints} field is for the second case only. Implementations shall copy in this
081:         * field only the user's hints that are know to be relevant to this factory. If a hint is
082:         * relevant but the user didn't specified any value, the hint key should be added to the
083:         * {@link #hints} map anyway with a {@code null} value. Only direct dependencies shall be put
084:         * in the {@link #hints} map. Indirect dependencies (i.e. hints used by other factories used
085:         * by this factory) will be inspected automatically by {@link FactoryRegistry} in a recursive way.
086:         * <p>
087:         * <strong>Note:</strong> The lack of constructor expecting a {@link Map} argument is intentional.
088:         * This is in order to discourage blind-copy of all user-supplied hints to the {@link #hints} map.
089:         * <p>
090:         * <strong>Example:</strong> Lets two factories, A and B. Factory A need an instance of Factory B.
091:         * Factory A can be implemented as below:
092:         *
093:         * <table border='1'>
094:         * <tr><th>Code</th><th>Observations</th></tr>
095:         * <tr><td><blockquote><pre>
096:         * class FactoryA extends AbstractFactory {
097:         *     FactoryB fb;
098:         *
099:         *     FactoryA(Hints userHints) {
100:         *         fb = FactoryFinder.getFactoryB(userHints);
101:         *         hints.put(Hints.FACTORY_B, fb);
102:         *     }
103:         * }
104:         * </pre></blockquote></td>
105:         * <td>
106:         * <ul>
107:         *   <li>The user-supplied map ({@code userHints}) is never modified.</li>
108:         *   <li>All hints relevant to other factories are used in the constructor. Hints relevant to
109:         *       factory B are used when {@code FactoryFinder.getFactoryB(...)} is invoked.</li>
110:         *   <li>The {@code FactoryA} constructor stores only the hints relevant to {@code FactoryA}.
111:         *       Indirect dependencies (e.g. hints relevant to {@code FactoryB}) will be inspected
112:         *       recursively by {@link FactoryRegistry}.</li>
113:         *   <li>In the above example, {@link #hints} will never be used for creating new factories.</li>
114:         * </ul>
115:         * </td></tr></table>
116:         *
117:         * @since 2.1
118:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/factory/AbstractFactory.java $
119:         * @version $Id: AbstractFactory.java 25421 2007-05-05 16:55:18Z desruisseaux $
120:         * @author Martin Desruisseaux
121:         */
122:        public class AbstractFactory implements  Factory, RegisterableService {
123:            /**
124:             * The minimum priority for a factory, which is {@value}. Factories with lowest priority
125:             * will be used only if there is no other factory in the same
126:             * {@linkplain ServiceRegistry#getCategories category}.
127:             *
128:             * @see #priority
129:             * @see #onRegistration
130:             */
131:            public static final int MINIMUM_PRIORITY = 1;
132:
133:            /**
134:             * The default priority, which is {@value}.
135:             *
136:             * @see #priority
137:             * @see #onRegistration
138:             */
139:            public static final int NORMAL_PRIORITY = 50;
140:
141:            /**
142:             * The maximum priority for a factory, which is {@value}. Factories with highest
143:             * priority will be preferred to any other factory in the same
144:             * {@linkplain ServiceRegistry#getCategories category}.
145:             *
146:             * @see #priority
147:             * @see #onRegistration
148:             */
149:            public static final int MAXIMUM_PRIORITY = 100;
150:
151:            /**
152:             * The priority for this factory, as a number between {@link #MINIMUM_PRIORITY} and
153:             * {@link #MAXIMUM_PRIORITY} inclusive. Priorities are used by {@link FactoryRegistry}
154:             * for selecting a preferred factory when many are found for the same service.
155:             *
156:             * @see #getPriority
157:             *
158:             * @todo Consider deprecating this field. See
159:             * <A HREF="http://jira.codehaus.org/browse/GEOT-1100">GEOT-1100</A> for details.
160:             */
161:            protected final int priority;
162:
163:            /**
164:             * The {@linkplain Factory#getImplementationHints implementation hints}. This map should be
165:             * filled by subclasses at construction time. If possible, constructors should not copy blindly
166:             * all user-provided hints. They should select only the relevant hints and resolve them as of
167:             * {@linkplain Factory#getImplementationHints implementation hints} contract.
168:             * <p>
169:             * <b>Note:</b> This field is not an instance of {@link Hints} because:
170:             * <ul>
171:             *   <li>The primary use of this map is to check if this factory can be reused.
172:             *       It is not for creating new factories.</li>
173:             *   <li>This map needs to allow null values, as of
174:             *       {@linkplain Factory#getImplementationHints implementation hints} contract.</li>
175:             * </ul>
176:             */
177:            protected final Map hints = new LinkedHashMap();
178:
179:            /**
180:             * An unmodifiable view of {@link #hints}. This is the actual map to be returned
181:             * by {@link #getImplementationHints}. Its content reflects the {@link #hints}
182:             * map even if the later is modified.
183:             */
184:            private final Map/*<RenderingHints.Key,Object>*/unmodifiableHints = Collections
185:                    .unmodifiableMap(hints);
186:
187:            /**
188:             * Creates a new factory with the {@linkplain #NORMAL_PRIORITY default priority}.
189:             */
190:            protected AbstractFactory() {
191:                this (NORMAL_PRIORITY);
192:            }
193:
194:            /**
195:             * Constructs a factory with the specified priority.
196:             *
197:             * @param priority The priority for this factory, as a number between
198:             *        {@link #MINIMUM_PRIORITY} and {@link #MAXIMUM_PRIORITY} inclusive.
199:             */
200:            protected AbstractFactory(final int priority) {
201:                this .priority = priority;
202:                if (priority < MINIMUM_PRIORITY || priority > MAXIMUM_PRIORITY) {
203:                    throw new IllegalArgumentException(Errors.format(
204:                            ErrorKeys.ILLEGAL_ARGUMENT_$2, "priority",
205:                            new Integer(priority)));
206:                }
207:            }
208:
209:            /**
210:             * Returns the priority for this factory, as a number between {@link #MINIMUM_PRIORITY} and
211:             * {@link #MAXIMUM_PRIORITY} inclusive. Priorities are used by {@link FactoryRegistry} for
212:             * selecting a preferred factory when many are found for the same service. The default
213:             * implementation returns {@link #priority} with no change. Subclasses should override
214:             * this method if they want to return a higher or lower priority.
215:             *
216:             * @since 2.3
217:             */
218:            public int getPriority() {
219:                return priority;
220:            }
221:
222:            /**
223:             * Returns an {@linkplain Collections#unmodifiableMap unmodifiable} view of
224:             * {@linkplain #hints}.
225:             *
226:             * @return The map of hints, or an empty map if none.
227:             */
228:            public Map getImplementationHints() {
229:                return unmodifiableHints;
230:            }
231:
232:            /**
233:             * Called when this factory is added to the given {@code category} of the given
234:             * {@code registry}. The factory may already be registered under another category
235:             * or categories.
236:             * <p>
237:             * This method is invoked automatically when this factory is registered as a plugin,
238:             * and should not be invoked directly by the user. The default implementation iterates
239:             * through all services under the same category that extends the {@code AbstractFactory}
240:             * class, and set the ordering according the priority given at construction time.
241:             *
242:             * @param registry A service registry where this factory has been registered.
243:             * @param category The registry category under which this object has been registered.
244:             *
245:             * @see #MINIMUM_PRIORITY
246:             * @see #MAXIMUM_PRIORITY
247:             */
248:            public void onRegistration(final ServiceRegistry registry,
249:                    final Class category) {
250:                for (final Iterator it = registry.getServiceProviders(category,
251:                        false); it.hasNext();) {
252:                    final Object provider = it.next();
253:                    if (provider != this  && provider instanceof  AbstractFactory) {
254:                        final AbstractFactory factory = (AbstractFactory) provider;
255:                        final int priority = getPriority();
256:                        final int compare = factory.getPriority();
257:                        final Object first, second;
258:                        if (priority > compare) {
259:                            first = this ;
260:                            second = factory;
261:                        } else if (priority < compare) {
262:                            first = factory;
263:                            second = this ;
264:                        } else {
265:                            continue; // No ordering
266:                        }
267:                        registry.setOrdering(category, first, second);
268:                    }
269:                }
270:            }
271:
272:            /**
273:             * Called when this factory is removed from the given {@code category} of the given
274:             * {@code registry}. The object may still be registered under another category or categories.
275:             * <p>
276:             * This method is invoked automatically when this factory is no longer registered as a plugin,
277:             * and should not be invoked directly by the user.
278:             *
279:             * @param registry A service registry from which this object is being (wholly or partially)
280:             *                 deregistered.
281:             * @param category The registry category from which this object is being deregistered.
282:             */
283:            public void onDeregistration(final ServiceRegistry registry,
284:                    final Class category) {
285:                // No action needed.
286:            }
287:
288:            /**
289:             * Returns a hash value for this factory. The default implementation computes the hash
290:             * value using only immutable properties. This computation do <strong>not</strong> relies
291:             * on {@linkplain #getImplementationHints implementation hints}, since there is no garantee
292:             * that they will not change.
293:             *
294:             * @since 2.3
295:             */
296:            public final int hashCode() {
297:                return getClass().hashCode() + (37 * priority);
298:            }
299:
300:            /**
301:             * Compares this factory with the specified object for equality.
302:             * The default implementation returns {@code true} if and only if:
303:             * <p>
304:             * <ul>
305:             *   <li>Both objects are of the exact same class
306:             *       (a <cite>is instance of</cite> relationship is not enough).</li>
307:             *   <li>{@linkplain #getImplementationHints implementation hints} are
308:             *       {@linkplain Map#equals equal}.</li>
309:             * </ul>
310:             * <p>
311:             * The requirement for the <cite>exact same class</cite> is needed for consistency with the
312:             * {@linkplain FactoryRegistry factory registry} working, since at most one instance of a given
313:             * class {@linkplain FactoryRegistry#getServiceProviderByClass) is allowed} in a registry.
314:             *
315:             * @since 2.3
316:             */
317:            public final boolean equals(final Object object) {
318:                if (object == this ) {
319:                    return true;
320:                }
321:                if (object != null && object.getClass().equals(getClass())) {
322:                    final AbstractFactory that = (AbstractFactory) object;
323:                    return this .priority == that.priority
324:                            && new FactoryComparator(this , that)
325:                                    .compare(new HashSet());
326:                }
327:                return false;
328:            }
329:
330:            /**
331:             * Returns a string representation of this factory. This method is mostly for debugging purpose,
332:             * so the string format may vary across different implementations or versions. The default
333:             * implementation formats all {@linkplain #getImplementationHints implementation hints} as a
334:             * tree. If the implementation hints include some {@linkplain Factory factory} dependencies,
335:             * then the implementation hints for those dependencies will appears under a tree branch.
336:             *
337:             * @since 2.3
338:             */
339:            public String toString() {
340:                final String name = format(this );
341:                final Map done = new IdentityHashMap(); // We don't want to rely on Factory.equals(...)
342:                done.put(this , name);
343:                final String tree = format(getImplementationHints(), done);
344:                return name + System.getProperty("line.separator", "\n") + tree;
345:            }
346:
347:            /**
348:             * Returns a string representation of the specified hints. This is used by
349:             * {@link Hints#toString} in order to share the code provided in this class.
350:             */
351:            static String toString(final Map hints) {
352:                return format(hints, new IdentityHashMap());
353:            }
354:
355:            /**
356:             * Formats a name for the specified factory.
357:             */
358:            private static String format(final Factory factory) {
359:                String name = Utilities.getShortClassName(factory);
360:                if (factory instanceof  AuthorityFactory) {
361:                    name = name
362:                            + "[\""
363:                            + ((AuthorityFactory) factory).getAuthority()
364:                                    .getTitle() + "\"]";
365:                }
366:                return name;
367:            }
368:
369:            /**
370:             * Formats the specified hints. This method is just the starting
371:             * point for {@link #format(Writer, Map, String, Map)} below.
372:             */
373:            private static String format(final Map hints, final Map done) {
374:                final Writer table;
375:                try {
376:                    table = new TableWriter(null, " ");
377:                    format(table, hints, "  ", done);
378:                } catch (IOException e) {
379:                    // Should never happen, since we are writing in a buffer.
380:                    throw new AssertionError(e);
381:                }
382:                return table.toString();
383:            }
384:
385:            /**
386:             * Formats recursively the tree. This method invoke itself.
387:             */
388:            private static void format(final Writer table, final Map hints,
389:                    final String indent, final Map/*<Object,String>*/done)
390:                    throws IOException {
391:                final String[] keys = new String[hints.size()];
392:                final Object[] values = new Object[keys.length];
393:                for (final Iterator it = hints.entrySet().iterator(); it
394:                        .hasNext();) {
395:                    Map.Entry entry = (Map.Entry) it.next();
396:                    String key = String.valueOf(entry.getKey());
397:                    Object value = entry.getValue();
398:                    table.write(indent);
399:                    table.write(key);
400:                    table.write("\t= ");
401:                    Factory recursive = null;
402:                    if (value instanceof  Factory) {
403:                        recursive = (Factory) value;
404:                        value = format(recursive);
405:                        final String previous = (String) done.put(recursive,
406:                                key);
407:                        if (previous != null) {
408:                            done.put(recursive, previous);
409:                            table.write("(same as "); // TODO: localize
410:                            table.write(previous);
411:                            value = ")";
412:                            recursive = null;
413:                        }
414:                    }
415:                    table.write(String.valueOf(value));
416:                    table.write('\n');
417:                    if (recursive != null) {
418:                        final String nextIndent = Utilities.spaces(indent
419:                                .length() + 2);
420:                        format(table, recursive.getImplementationHints(),
421:                                nextIndent, done);
422:                    }
423:                }
424:            }
425:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.