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


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2007, 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.metadata;
017:
018:        // J2SE dependencies
019:        import java.lang.reflect.Constructor;
020:        import java.text.DateFormat;
021:        import java.text.NumberFormat;
022:        import java.util.Collection;
023:        import java.util.Date;
024:        import java.util.Map;
025:        import java.util.Iterator;
026:        import java.util.Locale;
027:        import javax.swing.tree.DefaultMutableTreeNode;
028:        import javax.swing.tree.MutableTreeNode;
029:        import javax.swing.tree.TreeNode;
030:
031:        // OpenGIS dependencies
032:        import org.opengis.util.CodeList;
033:        import org.opengis.util.InternationalString;
034:
035:        // Geotools dependencies
036:        import org.geotools.resources.XMath;
037:        import org.geotools.resources.Utilities;
038:        import org.geotools.resources.OptionalDependencies;
039:
040:        /**
041:         * Represents the metadata property as a tree made from {@linkplain TreeNode tree nodes}.
042:         * Note that while {@link TreeNode} is defined in the {@link javax.swing.tree} package,
043:         * it can be seen as a data structure independent of Swing.
044:         * <p>
045:         * Note: this method is called {@code PropertyTree} because it may implements
046:         * {@link javax.swing.tree.TreeModel} in some future Geotools implementation.
047:         *
048:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/metadata/PropertyTree.java $
049:         * @version $Id: PropertyTree.java 25476 2007-05-09 17:24:32Z desruisseaux $
050:         * @author Martin Desruisseaux (Geomatys)
051:         */
052:        final class PropertyTree {
053:            /**
054:             * The default number of significant digits (may or may not be fraction digits).
055:             */
056:            private static final int PRECISION = 12;
057:
058:            /**
059:             * The expected standard implemented by the metadata.
060:             */
061:            private final MetadataStandard standard;
062:
063:            /**
064:             * The locale to use for {@linkplain Date date}, {@linkplain Number number}
065:             * and {@linkplain InternationalString international string} formatting.
066:             */
067:            private final Locale locale;
068:
069:            /**
070:             * The object to use for formatting numbers.
071:             * Will be created only when first needed.
072:             */
073:            private transient NumberFormat numberFormat;
074:
075:            /**
076:             * The object to use for formatting dates.
077:             * Will be created only when first needed.
078:             */
079:            private transient DateFormat dateFormat;
080:
081:            /**
082:             * Creates a new tree builder using the default locale.
083:             *
084:             * @param standard The expected standard implemented by the metadata.
085:             */
086:            public PropertyTree(final MetadataStandard standard) {
087:                this (standard, Locale.getDefault());
088:            }
089:
090:            /**
091:             * Creates a new tree builder.
092:             *
093:             * @param standard The expected standard implemented by the metadata.
094:             * @param locale   The locale to use for {@linkplain Date date}, {@linkplain Number number}
095:             *                 and {@linkplain InternationalString international string} formatting.
096:             */
097:            public PropertyTree(final MetadataStandard standard,
098:                    final Locale locale) {
099:                this .standard = standard;
100:                this .locale = locale;
101:            }
102:
103:            /**
104:             * Creates a tree for the specified metadata.
105:             */
106:            public MutableTreeNode asTree(final Object metadata) {
107:                final String name = Utilities.getShortName(standard
108:                        .getInterface(metadata.getClass()));
109:                final DefaultMutableTreeNode root = OptionalDependencies
110:                        .createTreeNode(localize(name), metadata, true);
111:                append(root, metadata);
112:                return root;
113:            }
114:
115:            /**
116:             * Appends the specified value to a branch. The value may be a metadata
117:             * (treated {@linkplain AbstractMetadata#asMap as a Map} - see below),
118:             * a collection or a singleton.
119:             * <p>
120:             * Map or metadata are constructed as a sub tree where every nodes is a
121:             * property name, and the childs are the value(s) for that property.
122:             */
123:            private void append(final DefaultMutableTreeNode branch,
124:                    final Object value) {
125:                if (value instanceof  Map) {
126:                    appendMap(branch, (Map) value);
127:                    return;
128:                }
129:                if (value instanceof  AbstractMetadata) {
130:                    appendMap(branch, ((AbstractMetadata) value).asMap());
131:                    return;
132:                }
133:                if (value != null) {
134:                    final PropertyAccessor accessor = standard
135:                            .getAccessorOptional(value.getClass());
136:                    if (accessor != null) {
137:                        appendMap(branch, new PropertyMap(value, accessor));
138:                        return;
139:                    }
140:                }
141:                if (value instanceof  Collection) {
142:                    for (final Iterator it = ((Collection) value).iterator(); it
143:                            .hasNext();) {
144:                        final Object element = it.next();
145:                        if (!PropertyAccessor.isEmpty(element)) {
146:                            append(branch, element);
147:                        }
148:                    }
149:                    return;
150:                }
151:                final String asText;
152:                if (value instanceof  CodeList) {
153:                    asText = localize((CodeList) value);
154:                } else if (value instanceof  Date) {
155:                    asText = format((Date) value);
156:                } else if (value instanceof  Number) {
157:                    asText = format((Number) value);
158:                } else if (value instanceof  InternationalString) {
159:                    asText = ((InternationalString) value).toString(locale);
160:                } else {
161:                    asText = String.valueOf(value);
162:                }
163:                branch.add(OptionalDependencies.createTreeNode(asText, value,
164:                        false));
165:            }
166:
167:            /**
168:             * Appends the specified map (usually a metadata) to a branch. Each map keys
169:             * is a child in the specified {@code branch}, and each value is a child of
170:             * the map key. There is often only one value for a map key, but not always;
171:             * some are collections, which are formatted as many childs for the same key.
172:             */
173:            private void appendMap(final DefaultMutableTreeNode branch,
174:                    final Map asMap) {
175:                for (final Iterator it = asMap.entrySet().iterator(); it
176:                        .hasNext();) {
177:                    final Map.Entry entry = (Map.Entry) it.next();
178:                    final Object value = entry.getValue();
179:                    if (!PropertyAccessor.isEmpty(value)) {
180:                        final String name = localize((String) entry.getKey());
181:                        final DefaultMutableTreeNode child = OptionalDependencies
182:                                .createTreeNode(name, value, true);
183:                        append(child, value);
184:                        branch.add(child);
185:                    }
186:                }
187:            }
188:
189:            /**
190:             * Formats the specified number.
191:             */
192:            private String format(final Number value) {
193:                if (numberFormat == null) {
194:                    numberFormat = NumberFormat.getNumberInstance(locale);
195:                    numberFormat.setMinimumFractionDigits(0);
196:                }
197:                int precision = 0;
198:                if (!XMath.isInteger(value.getClass())) {
199:                    precision = PRECISION;
200:                    final double v = Math.abs(value.doubleValue());
201:                    if (v > 0) {
202:                        final int digits = (int) XMath.log10(v);
203:                        if (Math.abs(digits) >= PRECISION) {
204:                            // TODO: Switch to exponential notation when a convenient API will be available in J2SE.
205:                            return value.toString();
206:                        }
207:                        if (digits >= 0) {
208:                            precision -= digits;
209:                        }
210:                        precision = Math.max(0, PRECISION - precision);
211:                    }
212:                }
213:                numberFormat.setMaximumFractionDigits(precision);
214:                return numberFormat.format(value);
215:            }
216:
217:            /**
218:             * Formats the specified date.
219:             */
220:            private String format(final Date value) {
221:                if (dateFormat == null) {
222:                    dateFormat = DateFormat.getDateTimeInstance(
223:                            DateFormat.LONG, DateFormat.LONG, locale);
224:                }
225:                return dateFormat.format(value);
226:            }
227:
228:            /**
229:             * Localize the specified property name. In current version, this is merely
230:             * a hook for future development. For now we reformat the programatic name.
231:             */
232:            private String localize(String name) {
233:                name = name.trim();
234:                final int length = name.length();
235:                if (length != 0) {
236:                    final StringBuffer buffer = new StringBuffer();
237:                    buffer.append(Character.toUpperCase(name.charAt(0)));
238:                    boolean previousIsUpper = true;
239:                    int base = 1;
240:                    for (int i = 1; i < length; i++) {
241:                        final boolean currentIsUpper = Character
242:                                .isUpperCase(name.charAt(i));
243:                        if (currentIsUpper != previousIsUpper) {
244:                            /*
245:                             * When a case change is detected (lower case to upper case as in "someName",
246:                             * or "someURL", or upper case to lower case as in "HTTPProxy"), then insert
247:                             * a space just before the upper case letter.
248:                             */
249:                            int split = i;
250:                            if (previousIsUpper) {
251:                                split--;
252:                            }
253:                            if (split > base) {
254:                                buffer.append(name.substring(base, split))
255:                                        .append(' ');
256:                                base = split;
257:                            }
258:                        }
259:                        previousIsUpper = currentIsUpper;
260:                    }
261:                    final String candidate = buffer
262:                            .append(name.substring(base)).toString();
263:                    if (!candidate.equals(name)) {
264:                        // Holds a reference to this new String object only if it worth it.
265:                        name = candidate;
266:                    }
267:                }
268:                return name;
269:            }
270:
271:            /**
272:             * Localize the specified property name. In current version, this is merely
273:             * a hook for future development.  For now we reformat the programatic name.
274:             */
275:            private String localize(final CodeList code) {
276:                return code.name().trim().replace('_', ' ').toLowerCase(locale);
277:            }
278:
279:            /**
280:             * Returns a string representation of the specified tree node.
281:             */
282:            public static String toString(final TreeNode node) {
283:                final StringBuffer buffer = new StringBuffer();
284:                toString(node, buffer, 0, System.getProperty("line.separator",
285:                        "\n"));
286:                return buffer.toString();
287:            }
288:
289:            /**
290:             * Append a string representation of the specified node to the specified buffer.
291:             */
292:            private static void toString(final TreeNode node,
293:                    final StringBuffer buffer, final int indent,
294:                    final String lineSeparator) {
295:                final int count = node.getChildCount();
296:                if (count == 0) {
297:                    if (node.isLeaf()) {
298:                        /*
299:                         * If the node has no child and is a leaf, then it is some value like a number,
300:                         * a date or a string.  We just display this value, which is usually part of a
301:                         * collection. If the node has no child and is NOT a leaf, then it is an empty
302:                         * metadata and we just ommit it.
303:                         */
304:                        buffer.append(Utilities.spaces(indent)).append(node)
305:                                .append(lineSeparator);
306:                    }
307:                    return;
308:                }
309:                buffer.append(Utilities.spaces(indent)).append(node)
310:                        .append(':');
311:                if (count == 1) {
312:                    final TreeNode child = node.getChildAt(0);
313:                    if (child.isLeaf()) {
314:                        buffer.append(' ').append(child).append(lineSeparator);
315:                        return;
316:                    }
317:                }
318:                for (int i = 0; i < count; i++) {
319:                    final TreeNode child = node.getChildAt(i);
320:                    if (i == 0) {
321:                        buffer.append(lineSeparator);
322:                    }
323:                    toString(child, buffer, indent + 2, lineSeparator);
324:                }
325:            }
326:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.