Source Code Cross Referenced for Arguments.java in  » Science » Cougaar12_4 » org » cougaar » util » 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 » Science » Cougaar12_4 » org.cougaar.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * <copyright>
0003:         *  
0004:         *  Copyright 2002-2007 BBNT Solutions, LLC
0005:         *  under sponsorship of the Defense Advanced Research Projects
0006:         *  Agency (DARPA).
0007:         * 
0008:         *  You can redistribute this software and/or modify it under the
0009:         *  terms of the Cougaar Open Source License as published on the
0010:         *  Cougaar Open Source Website (www.cougaar.org).
0011:         * 
0012:         *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0013:         *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0014:         *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0015:         *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0016:         *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0017:         *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0018:         *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0019:         *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0020:         *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0021:         *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0022:         *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023:         *  
0024:         * </copyright>
0025:         */
0026:
0027:        package org.cougaar.util;
0028:
0029:        import java.io.Serializable;
0030:        import java.lang.reflect.Field;
0031:        import java.lang.reflect.Method;
0032:        import java.lang.reflect.Modifier;
0033:        import java.util.AbstractMap;
0034:        import java.util.AbstractSet;
0035:        import java.util.ArrayList;
0036:        import java.util.Arrays;
0037:        import java.util.Collection;
0038:        import java.util.Collections;
0039:        import java.util.Enumeration;
0040:        import java.util.HashSet;
0041:        import java.util.Iterator;
0042:        import java.util.LinkedHashMap;
0043:        import java.util.LinkedHashSet;
0044:        import java.util.List;
0045:        import java.util.Map;
0046:        import java.util.Properties;
0047:        import java.util.Set;
0048:        import java.util.regex.Matcher;
0049:        import java.util.regex.Pattern;
0050:
0051:        import org.cougaar.bootstrap.SystemProperties;
0052:
0053:        /**
0054:         * A "name=value" parser.
0055:         * <p>
0056:         * Note that Arguments instances are unmodifiable, like Strings.
0057:         * <p>
0058:         * Example use:
0059:         * 
0060:         * <pre>
0061:         *   Arguments args = new Arguments("x=y, q=one, q=two, z=99");
0062:         *   String x = args.getString("x");
0063:         *   assert "y".equals(x);
0064:         *   int z = args.getInt("z", 1234);
0065:         *   assert z == 99;
0066:         *   List&lt;String&gt; q = args.getStrings("q");
0067:         *   assert q != null &amp;&amp; q.size() == 2;
0068:         * </pre>
0069:         * 
0070:         * <p>
0071:         * The Cougaar component model includes built-in support to invoke an optional
0072:         * "setArguments" method. Here's an example:
0073:         * 
0074:         * <pre>
0075:         *   package org;
0076:         *   public class MyPlugin ... {
0077:         *     private Arguments args;
0078:         *     // The "setArguments" method is special -- it's an optional method
0079:         *     // that's found by the component model via reflection.  The passed-in
0080:         *     // arguments instance is created via:
0081:         *     //    new Arguments(listOfStrings, classname);
0082:         *     public void setArguments(Arguments args) { this.args = args; }
0083:         *     public void load() {
0084:         *       super.load();
0085:         *       // Get the value of our "foo" argument
0086:         *       //
0087:         *       // First looks for a plugin XML argument named "foo",
0088:         *       // next looks for a "-Dorg.MyPlugin.foo=" system property,
0089:         *       // otherwise the value will be the 1234 default.
0090:         *       int foo = args.getInt("foo", 1234);
0091:         *       System.out.println("foo is "+foo);
0092:         *     }
0093:         *   }
0094:         * </pre>
0095:         * 
0096:         * <p>
0097:         * The {@link #callSetters} method supports "setter" reflection, for example:
0098:         * 
0099:         * <pre>
0100:         *   package org;
0101:         *   public class MyPlugin ... {
0102:         *     private int foo = 1234;
0103:         *     public void setArguments(Arguments args) { args.callSetters(this); }
0104:         *     // This "set<i>NAME</i>(<i>TYPE</i>)" method is found by reflection.
0105:         *     // The args class will only invoke the setters for which it has values.
0106:         *     public void setFoo(int i) { this.foo = i; }
0107:         *     public void load() {
0108:         *       super.load();
0109:         *       System.out.println("foo is "+foo);
0110:         *     }
0111:         *   }
0112:         * </pre>
0113:         */
0114:        public final class Arguments extends AbstractMap<String, List<String>>
0115:                implements  Serializable {
0116:
0117:            /** A singleton instance for an empty arguments */
0118:            public static final Arguments EMPTY_INSTANCE = new Arguments(null);
0119:
0120:            /** @see toString(String,String) */
0121:            private static final Pattern PATTERN = Pattern
0122:                    .compile("\\$(key|value|vals|veach|vlist)");
0123:
0124:            private static final int OPTIMIZE_SIZE = 5;
0125:
0126:            private final Map<String, List<String>> m;
0127:
0128:            public Arguments(Object o) {
0129:                this (o, null);
0130:            }
0131:
0132:            public Arguments(Object o, Object propertyPrefix) {
0133:                this (o, propertyPrefix, null);
0134:            }
0135:
0136:            public Arguments(Object o, Object propertyPrefix, Object deflt) {
0137:                this (o, propertyPrefix, deflt, null);
0138:            }
0139:
0140:            /**
0141:             * @param o the optional input object, e.g. a List of name=value Strings, or
0142:             *            another Arguments instance.
0143:             * @param propertyPrefix the optional SystemProperties property prefix, e.g.
0144:             *            "org.MyPlugin.", for "-Dorg.MyPlugin.name=value" lookups. If a
0145:             *            class is specified, that class's name+. and its parent's
0146:             *            names+. will be used.
0147:             * @param deflt the optional default values, e.g. a List of name=value
0148:             *            Strings, or another Arguments instance.
0149:             * @param keys the optional filter on which keys are allowed, e.g. only
0150:             *            allow (A, B, C)
0151:             */
0152:            public Arguments(Object o, Object propertyPrefix, Object deflt,
0153:                    Object keys) {
0154:                try {
0155:                    Map<String, List<String>> m2 = parseMap(o);
0156:                    List<String> prefixes = parsePrefixes(propertyPrefix);
0157:                    Map<String, List<String>> def = parseMap(deflt);
0158:                    Set<String> ks = parseSet(keys);
0159:                    this .m = parse(m2, prefixes, def, ks);
0160:                } catch (Exception e) {
0161:                    throw new IllegalArgumentException(
0162:                            "Unable to create new Arguments(" + "\n  o = " + o
0163:                                    + argString(propertyPrefix, deflt, keys)
0164:                                    + ")", e);
0165:                }
0166:            }
0167:
0168:            private String argString(Object propertyPrefix, Object deflt,
0169:                    Object keys) {
0170:                if (propertyPrefix == null && deflt == null && keys == null) {
0171:                    return "";
0172:                }
0173:                return ",\n  propertyPrefix = "
0174:                        + propertyPrefix
0175:                        + (deflt == null && keys == null ? ""
0176:                                : (",\n  deflt = " + deflt + (keys == null ? ""
0177:                                        : ",\n  keys = " + keys)));
0178:            }
0179:
0180:            /**
0181:             * All the other "get*" methods call this method.
0182:             * <p>
0183:             * Equivalent to:
0184:             * 
0185:             * <pre>
0186:             * List&lt;String&gt; l = get(key);
0187:             * return (l == null ? deflt : l);
0188:             * </pre>
0189:             * 
0190:             * @return the non-empty values or the deflt
0191:             */
0192:            public List<String> getStrings(String key, List<String> deflt) {
0193:                if (m instanceof  OptimizedMap) {
0194:                    return ((OptimizedMap) m).getStrings(key, deflt);
0195:                }
0196:                List<String> l = m.get(key);
0197:                return (l == null ? deflt : l);
0198:            }
0199:
0200:            //
0201:            // Helper methods:
0202:            //
0203:
0204:            /** @return the value, or null if not set */
0205:            public String getString(String key) {
0206:                return getString(key, null);
0207:            }
0208:
0209:            /**
0210:             * Get the first value, or the specified default if there is no value.
0211:             * <p>
0212:             * Equivalent to:
0213:             * 
0214:             * <pre>
0215:             * List&lt;String&gt; l = get(key);
0216:             * return (l == null ? deflt : l.get(0));
0217:             * </pre>
0218:             * 
0219:             * @return the first value, or the deflt if not set
0220:             */
0221:            public String getString(String key, String deflt) {
0222:                if (m instanceof  OptimizedMap) {
0223:                    return ((OptimizedMap) m).getString(key, deflt);
0224:                }
0225:                List<String> l = m.get(key);
0226:                return (l == null ? deflt : l.get(0));
0227:            }
0228:
0229:            /** @return same as {@link #get(String)} */
0230:            public List<String> getStrings(String key) {
0231:                return getStrings(key, null);
0232:            }
0233:
0234:            /** @return the value, or false if not set */
0235:            public boolean getBoolean(String key) {
0236:                return getBoolean(key, false);
0237:            }
0238:
0239:            /** @return the first value, or the deflt if not set */
0240:            public boolean getBoolean(String key, boolean deflt) {
0241:                String value = getString(key);
0242:                return (value == null ? deflt : "true".equals(value));
0243:            }
0244:
0245:            /** @return the values, or null if not set */
0246:            public List<Boolean> getBooleans(String key) {
0247:                return getBooleans(key, null);
0248:            }
0249:
0250:            /** @return the values, or the deflt if not set */
0251:            public List<Boolean> getBooleans(String key, List<Boolean> deflt) {
0252:                List<String> l = getStrings(key, null);
0253:                if (l == null) {
0254:                    return deflt;
0255:                }
0256:                int n = l.size();
0257:                if (n == 1) {
0258:                    Boolean value = Boolean.valueOf(l.get(0));
0259:                    return Collections.singletonList(value);
0260:                }
0261:                List<Boolean> ret = new ArrayList<Boolean>(n);
0262:                for (String s : l) {
0263:                    ret.add(Boolean.valueOf(s));
0264:                }
0265:                return Collections.unmodifiableList(ret);
0266:            }
0267:
0268:            /** @return the value, or -1 if not set */
0269:            public int getInt(String key) {
0270:                return getInt(key, -1);
0271:            }
0272:
0273:            /** @return the first value, or the deflt if not set */
0274:            public int getInt(String key, int deflt) {
0275:                String value = getString(key);
0276:                return (value == null ? deflt : Integer.parseInt(value));
0277:            }
0278:
0279:            /** @return the values, or null if not set */
0280:            public List<Integer> getInts(String key) {
0281:                return getInts(key, null);
0282:            }
0283:
0284:            /** @return the values, or the deflt if not set */
0285:            public List<Integer> getInts(String key, List<Integer> deflt) {
0286:                List<String> l = getStrings(key, null);
0287:                if (l == null) {
0288:                    return deflt;
0289:                }
0290:                int n = l.size();
0291:                if (n == 1) {
0292:                    Integer value = Integer.valueOf(l.get(0));
0293:                    return Collections.singletonList(value);
0294:                }
0295:                List<Integer> ret = new ArrayList<Integer>(n);
0296:                for (String s : l) {
0297:                    ret.add(Integer.valueOf(s));
0298:                }
0299:                return Collections.unmodifiableList(ret);
0300:            }
0301:
0302:            /** @return the value, or -1 if not set */
0303:            public long getLong(String key) {
0304:                return getLong(key, -1);
0305:            }
0306:
0307:            /** @return the first value, or the deflt if not set */
0308:            public long getLong(String key, long deflt) {
0309:                String value = getString(key);
0310:                return (value == null ? deflt : Long.parseLong(value));
0311:            }
0312:
0313:            /** @return the value, or null if not set */
0314:            public List<Long> getLongs(String key) {
0315:                return getLongs(key, null);
0316:            }
0317:
0318:            /** @return the values, or the deflt if not set */
0319:            public List<Long> getLongs(String key, List<Long> deflt) {
0320:                List<String> l = getStrings(key, null);
0321:                if (l == null) {
0322:                    return deflt;
0323:                }
0324:                int n = l.size();
0325:                if (n == 1) {
0326:                    Long value = Long.valueOf(l.get(0));
0327:                    return Collections.singletonList(value);
0328:                }
0329:                List<Long> ret = new ArrayList<Long>(n);
0330:                for (String s : l) {
0331:                    ret.add(Long.valueOf(s));
0332:                }
0333:                return Collections.unmodifiableList(ret);
0334:            }
0335:
0336:            /** @return the value, or Double.NaN if not set */
0337:            public double getDouble(String key) {
0338:                return getDouble(key, Double.NaN);
0339:            }
0340:
0341:            /** @return the first value, or the deflt if not set */
0342:            public double getDouble(String key, double deflt) {
0343:                String value = getString(key);
0344:                return (value == null ? deflt : Double.parseDouble(value));
0345:            }
0346:
0347:            /** @return the value, or null if not set */
0348:            public List<Double> getDoubles(String key) {
0349:                return getDoubles(key, null);
0350:            }
0351:
0352:            /** @return the values, or the deflt if not set */
0353:            public List<Double> getDoubles(String key, List<Double> deflt) {
0354:                List<String> l = getStrings(key, null);
0355:                if (l == null) {
0356:                    return deflt;
0357:                }
0358:                int n = l.size();
0359:                if (n == 1) {
0360:                    Double value = Double.valueOf(l.get(0));
0361:                    return Collections.singletonList(value);
0362:                }
0363:                List<Double> ret = new ArrayList<Double>(n);
0364:                for (String s : l) {
0365:                    ret.add(Double.valueOf(s));
0366:                }
0367:                return Collections.unmodifiableList(ret);
0368:            }
0369:
0370:            /**
0371:             * Split this arguments instance of String-to-List[N] pairs into a List of
0372:             * "flattened" Arguments with String-to-List[1] pairs.
0373:             * <p>
0374:             * This is useful to group together same-named arguments.
0375:             * 
0376:             * <pre>
0377:             * For example, the constructor input:
0378:             *   "foo=f1, bar=b1, qux=q1,
0379:             *    foo=f2, bar=b2, qux=q2,
0380:             *    foo=f3, bar=b3, qux=q3"
0381:             * will be parsed as:
0382:             *   {foo=[f1,f2,f3], bar=[b1,b2,b3], qux=[q1,q2,q3]}
0383:             * and can be split into:
0384:             *   [{foo=[f1], bar=[b1], qux=[q1]},
0385:             *    {foo=[f2], bar=[b2], qux=[q2]},
0386:             *    {foo=[f3], bar=[b3], qux=[q3]}}
0387:             * This simplifies iteration:
0388:             *   for (Arguments a : args.split()) {
0389:             *     System.out.println("foo is "+a.getString("foo"));
0390:             *   }
0391:             * which will print:
0392:             *   foo is f1
0393:             *   foo is f2
0394:             *   foo is f3
0395:             * </pre>
0396:             * 
0397:             * @return a List of Arguments.
0398:             */
0399:            public List<Arguments> split() {
0400:                int n = 1;
0401:                if (!(m instanceof  OptimizedMap)) {
0402:                    for (List<String> l : m.values()) {
0403:                        n = Math.max(n, l.size());
0404:                    }
0405:                }
0406:                if (n == 1) {
0407:                    return Collections.singletonList(this );
0408:                }
0409:                List<Map<String, String>> ma = new ArrayList<Map<String, String>>(
0410:                        n);
0411:                for (int i = 0; i < n; i++) {
0412:                    ma.add(new LinkedHashMap<String, String>());
0413:                }
0414:
0415:                for (Map.Entry<String, List<String>> me : m.entrySet()) {
0416:                    String key = me.getKey();
0417:                    List<String> l = me.getValue();
0418:                    for (int i = 0; i < l.size(); i++) {
0419:                        ma.get(i).put(key, l.get(i));
0420:                    }
0421:                }
0422:
0423:                List<Arguments> ret = new ArrayList<Arguments>(n);
0424:                for (Map<String, String> mi : ma) {
0425:                    ret.add(new Arguments(mi));
0426:                }
0427:                return Collections.unmodifiableList(ret);
0428:            }
0429:
0430:            //
0431:            // Modifiers
0432:            //
0433:
0434:            /**
0435:             * Return an Arguments instance where the values for key1 and key2 are
0436:             * swapped.
0437:             * <p>
0438:             * In other words:
0439:             * 
0440:             * <pre>
0441:             * // given:
0442:             * List&lt;String&gt; v1 = args.getStrings(key1);
0443:             * List&lt;String&gt; v2 = args.getStrings(key2);
0444:             * // do swap:
0445:             * Arguments ret = args.swap(key1, key2);
0446:             * // validate:
0447:             * assert(ret.size() == args.size());
0448:             * List&lt;String&gt; x1 = ret.getStrings(key1);
0449:             * List&lt;String&gt; x2 = ret.getStrings(key2);
0450:             * assert(v1 == null ? x2 == null : v1.equals(x2));
0451:             * assert(v2 == null ? x1 == null : v2.equals(x1));
0452:             * </pre>
0453:             * 
0454:             * @return returns a new Arguments instance
0455:             */
0456:            public Arguments swap(String key1, String key2) {
0457:                // could optimize this...
0458:                List<String> v1 = getStrings(key1);
0459:                List<String> v2 = getStrings(key2);
0460:                Arguments ret = setStrings(key1, v2);
0461:                ret = ret.setStrings(key2, v1);
0462:                return ret;
0463:            }
0464:
0465:            /** @see #setStrings */
0466:            public Arguments setString(String key, String value) {
0467:                List<String> l = (value == null ? null : Collections
0468:                        .singletonList(value));
0469:                return setStrings(key, l);
0470:            }
0471:
0472:            /**
0473:             * @param key the non-null key
0474:             * @param values the values, which can be null or empty to remove the
0475:             *            specified key's entry
0476:             * @return returns a possibly new Arguments instance (like
0477:             *         {@link String#trim} and similar copy-on-modify classes) where
0478:             *         "getStrings(key)" will be equal to the specified "values"
0479:             */
0480:            public Arguments setStrings(String key, List<String> values) {
0481:                // could optimize this...
0482:                List<String> old = getStrings(key);
0483:                if (values == null || values.isEmpty()) {
0484:                    if (old == null) {
0485:                        return this ;
0486:                    }
0487:                    if (size() == 1) {
0488:                        return EMPTY_INSTANCE;
0489:                    }
0490:                    Set<String> filter = new HashSet<String>(keySet());
0491:                    filter.remove(key);
0492:                    return new Arguments(this , null, null, filter);
0493:                } else {
0494:                    Map<String, List<String>> add = Collections.singletonMap(
0495:                            key, values);
0496:                    return new Arguments(add, null, this );
0497:                }
0498:            }
0499:
0500:            //
0501:            // Required base class methods:
0502:            //
0503:
0504:            public Set<Map.Entry<String, List<String>>> entrySet() {
0505:                return m.entrySet();
0506:            }
0507:
0508:            // avoid linear scan through our "entrySet()":
0509:            public int size() {
0510:                return m.size();
0511:            }
0512:
0513:            public boolean containsKey(Object key) {
0514:                return (get(key) != null);
0515:            }
0516:
0517:            public List<String> get(String key) {
0518:                return m.get(key);
0519:            }
0520:
0521:            //
0522:            // Reflection methods:
0523:            //
0524:
0525:            /**
0526:             * Call the given object's setter methods or fields for every name=value
0527:             * pair in the {@link #entrySet}, return the Set of unknown String keys.
0528:             * <p>
0529:             * For example, the name=value pair "x=y" will look for:
0530:             * 
0531:             * <pre>
0532:             *   public void setX(<i>type</i>) {..}
0533:             * </pre>
0534:             * 
0535:             * and field:
0536:             * 
0537:             * <pre>
0538:             *   public <i>type</i> x;
0539:             * </pre>
0540:             * 
0541:             * If neither are found then "x" will be included in the returned Set.
0542:             * 
0543:             * @param o Object that has the setter methods &amp; fields
0544:             * @return Subset of the {@link #keySet} that could not be set
0545:             */
0546:            public Set<String> callSetters(Object o) {
0547:                if (isEmpty()) {
0548:                    return Collections.emptySet();
0549:                }
0550:                Class cl = o.getClass();
0551:                if (!Modifier.isPublic(cl.getModifiers())) {
0552:                    return keySet();
0553:                }
0554:                Set<String> ret = null;
0555:                Method[] methods = cl.getMethods();
0556:                for (Map.Entry<String, List<String>> me : entrySet()) {
0557:                    String key = me.getKey();
0558:                    List<String> l = me.getValue();
0559:
0560:                    boolean found = false;
0561:
0562:                    // look for setter method(s)
0563:                    String setter_name = "set"
0564:                            + Character.toUpperCase(key.charAt(0))
0565:                            + key.substring(1);
0566:                    for (int i = 0; i < methods.length; i++) {
0567:                        Method mi = methods[i];
0568:                        if (!Modifier.isPublic(mi.getModifiers())) {
0569:                            continue;
0570:                        }
0571:                        if (!setter_name.equals(mi.getName())) {
0572:                            continue;
0573:                        }
0574:                        Class[] p = mi.getParameterTypes();
0575:                        if (p.length != 1) {
0576:                            continue;
0577:                        }
0578:                        try {
0579:                            Object arg = cast(l, p[0]);
0580:                            mi.invoke(o, new Object[] { arg });
0581:                            found = true;
0582:                        } catch (Exception e) {
0583:                            throw new RuntimeException("Unable to set " + key
0584:                                    + "=" + l + " on " + mi, e);
0585:                        }
0586:                    }
0587:
0588:                    // look for field
0589:                    Field field = null;
0590:                    try {
0591:                        field = cl.getField(key);
0592:                        if (!Modifier.isPublic(field.getModifiers())) {
0593:                            field = null;
0594:                        }
0595:                    } catch (Exception e) {
0596:                    }
0597:                    if (field != null) {
0598:                        try {
0599:                            Object arg = cast(l, field.getType());
0600:                            field.set(o, arg);
0601:                            found = true;
0602:                        } catch (Exception e) {
0603:                            throw new RuntimeException("Unable to set " + key
0604:                                    + "=" + l + " on " + field, e);
0605:                        }
0606:                    }
0607:
0608:                    if (!found) {
0609:                        if (ret == null) {
0610:                            ret = new LinkedHashSet<String>();
0611:                        }
0612:                        ret.add(key);
0613:                    }
0614:                }
0615:                if (ret == null) {
0616:                    return Collections.emptySet();
0617:                }
0618:                return ret;
0619:            }
0620:
0621:            private static Object cast(List<String> l, Class type) {
0622:                if (String.class.isAssignableFrom(type)) {
0623:                    return l.get(0);
0624:                }
0625:                if (type.isPrimitive()) {
0626:                    String value = l.get(0);
0627:                    if (type == Boolean.TYPE) {
0628:                        return Boolean.valueOf(value);
0629:                    } else if (type == Character.TYPE) {
0630:                        return Character.valueOf(value.charAt(0));
0631:                    } else if (type == Byte.TYPE) {
0632:                        return Byte.valueOf(value);
0633:                    } else if (type == Short.TYPE) {
0634:                        return Short.valueOf(value);
0635:                    } else if (type == Integer.TYPE) {
0636:                        return Integer.valueOf(value);
0637:                    } else if (type == Long.TYPE) {
0638:                        return Long.valueOf(value);
0639:                    } else if (type == Float.TYPE) {
0640:                        return Float.valueOf(value);
0641:                    } else if (type == Double.TYPE) {
0642:                        return Double.valueOf(value);
0643:                    }
0644:                }
0645:                if (Collection.class.isAssignableFrom(type)) {
0646:                    return l;
0647:                }
0648:                // RFE support primitive wrappers, e.g. Integer? Boolean?
0649:                // RFE support arrays, e.g. double[]? String[]?
0650:                throw new UnsupportedOperationException("Unknown type " + type
0651:                        + " for " + l);
0652:            }
0653:
0654:            //
0655:            // toString methods:
0656:            //
0657:
0658:            /**
0659:             * @see #toString(String) Same as "{"+toString(null)+"}"
0660:             */
0661:            public String toString() {
0662:                // return "{" + toString(null, null) + "}";
0663:                return super .toString();
0664:            }
0665:
0666:            /** @see #toString(String,String) Same as "toString(format, null)" */
0667:            public String toString(String format) {
0668:                return toString(format, null);
0669:            }
0670:
0671:            /**
0672:             * Create a string representation of this map using the given format.
0673:             * 
0674:             * <pre>
0675:             * For example, if our map contains:
0676:             *   A=B
0677:             *   X=V0,V1,V2
0678:             * then:
0679:             *   toString("the_$key is the_$value", " * ");
0680:             * would return:
0681:             *   the_A is the_B * the_X is the_V0
0682:             * and:
0683:             *   toString("($key eq $vals)", " +\n");
0684:             * would return:
0685:             *   (A eq B) +
0686:             *   (X eq [V0, V1, V2])
0687:             * and:
0688:             *   toString("$key=$veach", "&amp;");
0689:             * would return a URL-like string:
0690:             *   A=B&amp;X=V0&amp;X=V1&amp;X=V2
0691:             * and:
0692:             *   "{" + toString("$key=$vlist", ", ") + "}";
0693:             * would return the standard {@link Map#toString} format:
0694:             *   {A=[B], X=[V0, V1, V2]}
0695:             * </pre>
0696:             * 
0697:             * The supported variables are:
0698:             * <ul>
0699:             * <li>"$key" is the string key name (e.g. "X")</li>
0700:             * <li>"$value" is the first value (e.g. "V0"), as defined in
0701:             * {@link #getString(String)}</li>
0702:             * <li>"$vals" is the first value if there is only one value (e.g. "B"),
0703:             * otherwise the list of values prefixed with "[" and "]" if there are
0704:             * multiple values (e.g. "[V0, V1, V2]").</li>
0705:             * <li>"$veach" is current value in the list (e.g. "V1")</li>
0706:             * <li>"$vlist" is the "[]" wrapped list (e.g. "[B]" or "[V0, V1, V2]")</li>
0707:             * </ul>
0708:             * 
0709:             * @param format optional format, defaults to "$key=$vlist"
0710:             * @param separator optional separator, defaults to ", "
0711:             * 
0712:             * @return a string with each entry in the given format, where every "$key"
0713:             *         is replaced with the map key and every "$value" is replaced with
0714:             *         the map value.
0715:             */
0716:            public String toString(String format, String separator) {
0717:                String form = format;
0718:                if (form == null) {
0719:                    form = "$key=$vlist";
0720:                }
0721:
0722:                String sep = separator;
0723:                if (sep == null) {
0724:                    sep = ", ";
0725:                }
0726:                if (sep.length() == 0) {
0727:                    sep = null;
0728:                }
0729:
0730:                Matcher x = PATTERN.matcher(form);
0731:
0732:                boolean firstTime = true;
0733:                StringBuffer buf = new StringBuffer();
0734:                for (Map.Entry<String, List<String>> me : entrySet()) {
0735:                    String k = me.getKey();
0736:                    List<String> l = me.getValue();
0737:
0738:                    boolean hasEach = false;
0739:                    int eachIndex = 0;
0740:                    while (true) {
0741:                        if (firstTime) {
0742:                            firstTime = false;
0743:                        } else {
0744:                            if (sep != null) {
0745:                                buf.append(sep);
0746:                            }
0747:                        }
0748:
0749:                        x.reset();
0750:                        while (x.find()) {
0751:                            String tag = x.group(1);
0752:                            String value;
0753:                            if ("veach".equals(tag)) {
0754:                                hasEach = true;
0755:                                value = l.get(eachIndex);
0756:                            } else {
0757:                                value = entryString(k, l, tag);
0758:                            }
0759:                            x.appendReplacement(buf, value);
0760:                        }
0761:                        x.appendTail(buf);
0762:
0763:                        if (!hasEach || ++eachIndex >= l.size())
0764:                            break;
0765:                    }
0766:                }
0767:                return buf.toString();
0768:            }
0769:
0770:            private String entryString(String k, List<String> l, String tag) {
0771:                if ("key".equals(tag)) {
0772:                    return k;
0773:                } else if ("value".equals(tag)) {
0774:                    return l.get(0);
0775:                } else if ("vals".equals(tag)) {
0776:                    if (l.size() == 1) {
0777:                        return l.get(0);
0778:                    } else {
0779:                        return l.toString();
0780:                    }
0781:                } else if ("vlist".equals(tag)) {
0782:                    return l.toString();
0783:                } else {
0784:                    return "InternalError!";
0785:                }
0786:            }
0787:
0788:            //
0789:            // Internal parsing:
0790:            //
0791:
0792:            /**
0793:             * @return null or a modifiable, non-empty, ordered map of unmodifiable,
0794:             *         non-empty, lists
0795:             */
0796:            private static final Map<String, List<String>> parseMap(
0797:                    Object object) {
0798:                Object o = object;
0799:                if (o == null) {
0800:                    return null;
0801:                }
0802:                if (o instanceof  Arguments) {
0803:                    return ((Arguments) o).m;
0804:                }
0805:                if (o instanceof  Map) {
0806:                    Map m2 = (Map) o;
0807:                    if (m2.isEmpty()) {
0808:                        return null;
0809:                    }
0810:                    Map<String, List<String>> ret = new LinkedHashMap<String, List<String>>();
0811:                    for (Object x : m2.entrySet()) {
0812:                        Map.Entry me = (Map.Entry) x;
0813:                        String key = parseString(me.getKey(), "Map key");
0814:                        List<String> value = parseList(me.getValue());
0815:                        if (value == null) {
0816:                            continue;
0817:                        }
0818:                        ret.put(key, value);
0819:                    }
0820:                    return ret;
0821:                }
0822:                if (o instanceof  String) {
0823:                    o = ((String) o).split("\\s*,\\s*");
0824:                }
0825:                if (o instanceof  Object[]) {
0826:                    o = Arrays.asList((Object[]) o);
0827:                }
0828:                if (!(o instanceof  Collection)) {
0829:                    throw new IllegalArgumentException(
0830:                            "Expecting null, Arguments, Map, Object[], or Collection, not "
0831:                                    + (o == null ? "null" : o.getClass()
0832:                                            .getName()));
0833:                }
0834:                Collection c = (Collection) o;
0835:                int n = c.size();
0836:                if (n == 0) {
0837:                    return null;
0838:                }
0839:                Map<String, List<String>> ret = null;
0840:                boolean hasMulti = false;
0841:                Iterator iter = c.iterator();
0842:                for (int i = 0; i < n; i++) {
0843:                    Object oi = iter.next();
0844:                    if (!(oi instanceof  String)) {
0845:                        throw new IllegalArgumentException(
0846:                                "Expecting a Collection of Strings, not "
0847:                                        + (oi == null ? "null" : (oi.getClass()
0848:                                                .getName()
0849:                                                + " " + oi)));
0850:                    }
0851:                    String s = (String) oi;
0852:                    int sep = s.indexOf('=');
0853:                    if (sep < 0) {
0854:                        throw new IllegalArgumentException(
0855:                                "Missing a \"=\" separator for \"" + s + "\"");
0856:                    }
0857:                    String key = s.substring(0, sep).trim();
0858:                    String value = s.substring(sep + 1).trim();
0859:                    if (key.length() <= 0) {
0860:                        throw new IllegalArgumentException(
0861:                                "Key length is zero for \"" + s + "\"");
0862:                    }
0863:                    if (ret == null) {
0864:                        ret = new LinkedHashMap<String, List<String>>();
0865:                    }
0866:                    List<String> prev = ret.get(key);
0867:                    if (prev == null) {
0868:                        ret.put(key, Collections.singletonList(value));
0869:                        continue;
0870:                    }
0871:                    hasMulti = true;
0872:                    if (prev.size() == 1) {
0873:                        String s0 = prev.get(0);
0874:                        prev = new ArrayList<String>(2);
0875:                        prev.add(s0);
0876:                        ret.put(key, prev);
0877:                    }
0878:                    prev.add(value);
0879:                }
0880:                if (hasMulti) {
0881:                    // make values unmodifiable
0882:                    for (Map.Entry<String, List<String>> me : ret.entrySet()) {
0883:                        List<String> prev = me.getValue();
0884:                        if (prev.size() == 1) {
0885:                            continue;
0886:                        }
0887:                        prev = Collections.unmodifiableList(prev);
0888:                        me.setValue(prev);
0889:                    }
0890:                }
0891:                // don't need to make ret unmodifiable
0892:                return ret;
0893:            }
0894:
0895:            private static final Set<String> parseSet(Object object) {
0896:                Object o = object;
0897:                if (o == null) {
0898:                    return null;
0899:                }
0900:                if (o instanceof  String) {
0901:                    o = ((String) o).split("\\s*,\\s*");
0902:                }
0903:                if (o instanceof  Object[]) {
0904:                    o = Arrays.asList((Object[]) o);
0905:                }
0906:                if (!(o instanceof  Collection)) {
0907:                    throw new IllegalArgumentException(
0908:                            "Expecting null, String, Object[], or Collection, not "
0909:                                    + (o == null ? "null" : o.getClass()
0910:                                            .getName()));
0911:                }
0912:                Collection c = (Collection) o;
0913:                int n = c.size();
0914:                if (n == 0) {
0915:                    return null;
0916:                }
0917:                Set<String> ret = new HashSet<String>(c.size());
0918:                for (Object oi : c) {
0919:                    ret.add(parseString(oi, "Set filter value"));
0920:                }
0921:                return ret;
0922:            }
0923:
0924:            private static final List<String> parseList(Object object) {
0925:                Object o = object;
0926:                if (o instanceof  String) {
0927:                    return Collections.singletonList((String) o);
0928:                }
0929:                if (o instanceof  Object[]) {
0930:                    o = Arrays.asList((Object[]) o);
0931:                }
0932:                if (!(o instanceof  Collection)) {
0933:                    throw new IllegalArgumentException(
0934:                            "Expecting a String, Object[], or Collection value, not "
0935:                                    + (o == null ? "null" : (o.getClass()
0936:                                            .getName())
0937:                                            + " " + o));
0938:                }
0939:                Collection c = (Collection) o;
0940:                int n = c.size();
0941:                if (n == 0) {
0942:                    return null;
0943:                }
0944:                Iterator iter = c.iterator();
0945:                if (n == 1) {
0946:                    String s = parseString(iter.next(), "Collection value");
0947:                    return Collections.singletonList(s);
0948:                }
0949:                List<String> ret = new ArrayList<String>(n);
0950:                for (int i = 0; i < n; i++) {
0951:                    String s = parseString(iter.next(), "Collection value");
0952:                    ret.add(s);
0953:                }
0954:                return Collections.unmodifiableList(ret);
0955:            }
0956:
0957:            private static final String parseString(Object o, String desc) {
0958:                if (!(o instanceof  String)) {
0959:                    throw new IllegalArgumentException("Expecting a "
0960:                            + desc
0961:                            + " String, not "
0962:                            + (o == null ? "null" : (o.getClass().getName())
0963:                                    + " " + o));
0964:                }
0965:                return (String) o;
0966:            }
0967:
0968:            private static final List<String> parsePrefixes(Object o) {
0969:                if (o == null) {
0970:                    return Collections.emptyList();
0971:                }
0972:                if (o instanceof  String) {
0973:                    return Collections.singletonList((String) o);
0974:                }
0975:                if (!(o instanceof  Class)) {
0976:                    throw new IllegalArgumentException(
0977:                            "Expecting null, a String, or a Class, not "
0978:                                    + (o == null ? "null" : (o.getClass()
0979:                                            .getName())
0980:                                            + " " + o));
0981:                }
0982:                List<String> ret = new ArrayList<String>();
0983:                for (Class cl = (Class) o; cl != null; cl = cl.getSuperclass()) {
0984:                    ret.add(cl.getName() + ".");
0985:                }
0986:                return ret;
0987:            }
0988:
0989:            /**
0990:             * @param m a map created by "parseMap()"
0991:             * @param prefixes a list created by "parsePrefixes()"
0992:             * @param deflt a map created by "parseMap()"
0993:             * @param keys a set created by "parseSet()"
0994:             * @return a non-null, unmodifiable, ordered map
0995:             */
0996:            private static final Map<String, List<String>> parse(
0997:                    Map<String, List<String>> m, List<String> prefixes,
0998:                    Map<String, List<String>> deflt, Set<String> keys) {
0999:                Map<String, List<String>> ret = new LinkedHashMap<String, List<String>>();
1000:                if (m != null && !m.isEmpty()) {
1001:                    if (keys == null) {
1002:                        ret.putAll(m);
1003:                    } else {
1004:                        for (String key : keys) {
1005:                            List<String> l = m.get(key);
1006:                            if (l == null) {
1007:                                continue;
1008:                            }
1009:                            ret.put(key, l);
1010:                        }
1011:                    }
1012:                }
1013:                if ((prefixes != null && !prefixes.isEmpty())
1014:                        && (keys == null || (ret.size() < keys.size()))) {
1015:                    for (String s : prefixes) {
1016:                        Properties props = SystemProperties
1017:                                .getSystemPropertiesWithPrefix(s);
1018:                        if (props == null || props.isEmpty()) {
1019:                            continue;
1020:                        }
1021:                        for (Enumeration en = props.propertyNames(); en
1022:                                .hasMoreElements();) {
1023:                            String name = (String) en.nextElement();
1024:                            if (!name.startsWith(s)) {
1025:                                continue;
1026:                            }
1027:                            String key = name.substring(s.length());
1028:                            if (key.length() <= 0) {
1029:                                continue;
1030:                            }
1031:                            if (ret.containsKey(key)) {
1032:                                continue;
1033:                            }
1034:                            if (keys != null && !keys.contains(key)) {
1035:                                continue;
1036:                            }
1037:                            String value = props.getProperty(name);
1038:                            // RFE split by commas, but not if quoted?
1039:                            List<String> l = Collections.singletonList(value);
1040:                            ret.put(key, l);
1041:                        }
1042:                    }
1043:                }
1044:                if ((deflt != null && !deflt.isEmpty())
1045:                        && (keys == null || (ret.size() < keys.size()))) {
1046:                    for (Map.Entry<String, List<String>> me : deflt.entrySet()) {
1047:                        String key = me.getKey();
1048:                        if (ret.containsKey(key)) {
1049:                            continue;
1050:                        }
1051:                        if (keys != null && !keys.contains(key)) {
1052:                            continue;
1053:                        }
1054:                        ret.put(key, me.getValue());
1055:                    }
1056:                }
1057:                int n = ret.size();
1058:                if (n == 0) {
1059:                    return Collections.emptyMap();
1060:                }
1061:                if (n == 1) {
1062:                    Map.Entry<String, List<String>> me = ret.entrySet()
1063:                            .iterator().next();
1064:                    return Collections.singletonMap(me.getKey(), me.getValue());
1065:                }
1066:                if (n <= OPTIMIZE_SIZE) {
1067:                    boolean hasMulti = false;
1068:                    for (List<String> l : ret.values()) {
1069:                        if (l.size() > 1) {
1070:                            hasMulti = true;
1071:                            break;
1072:                        }
1073:                    }
1074:                    if (!hasMulti) {
1075:                        return new OptimizedMapImpl(ret);
1076:                    }
1077:                }
1078:                return Collections.unmodifiableMap(ret);
1079:            }
1080:
1081:            interface OptimizedMap extends Map<String, List<String>> {
1082:                List<String> getStrings(String key, List<String> deflt);
1083:
1084:                String getString(String key, String deflt);
1085:            }
1086:
1087:            /**
1088:             * Nearly all of our expected uses will have only a handleful of entries,
1089:             * where every value is a single-element List&lt;String&gt;, so we optimize
1090:             * this case.
1091:             * <p>
1092:             * We keep two String arrays; one for the keys, and one for the values.
1093:             * <p>
1094:             * Contrast this with the general case, where we keep an unmodifiableMap
1095:             * wrapper around a LinkedHashMap of String-to-List entries, where the value
1096:             * Lists would be a mix of<br>
1097:             * &nbsp; (1) singletonList wrappers around strings, and<br>
1098:             * &nbsp; (2) unmodifiableList wrappers around ArrayLists of strings.<br>
1099:             */
1100:            private static final class OptimizedMapImpl extends
1101:                    AbstractMap<String, List<String>> implements  OptimizedMap,
1102:                    Serializable {
1103:                private final String[] keys;
1104:                private final String[] values;
1105:
1106:                public OptimizedMapImpl(Map<String, List<String>> m) {
1107:                    keys = new String[m.size()];
1108:                    values = new String[m.size()];
1109:                    int i = 0;
1110:                    for (Map.Entry<String, List<String>> me : m.entrySet()) {
1111:                        keys[i] = me.getKey();
1112:                        values[i] = me.getValue().get(0);
1113:                        i++;
1114:                    }
1115:                }
1116:
1117:                public List<String> getStrings(String key, List<String> deflt) {
1118:                    String s = getString(key, null);
1119:                    return (s == null ? deflt : Collections.singletonList(s));
1120:                }
1121:
1122:                public String getString(String key, String deflt) {
1123:                    for (int i = 0; i < keys.length; i++) {
1124:                        if (key.equals(keys[i])) {
1125:                            return values[i];
1126:                        }
1127:                    }
1128:                    return deflt;
1129:                }
1130:
1131:                // required by our AbstractMap base class:
1132:                public Set<Map.Entry<String, List<String>>> entrySet() {
1133:                    return new AbstractSet<Map.Entry<String, List<String>>>() {
1134:                        public int size() {
1135:                            return keys.length;
1136:                        }
1137:
1138:                        public Iterator<Map.Entry<String, List<String>>> iterator() {
1139:                            return new Iterator<Map.Entry<String, List<String>>>() {
1140:                                private int i = 0;
1141:
1142:                                public boolean hasNext() {
1143:                                    return i < keys.length;
1144:                                }
1145:
1146:                                public Map.Entry<String, List<String>> next() {
1147:                                    if (i >= keys.length) {
1148:                                        throw new ArrayIndexOutOfBoundsException(
1149:                                                i);
1150:                                    }
1151:                                    final int j = i++;
1152:                                    return new Map.Entry<String, List<String>>() {
1153:                                        public String getKey() {
1154:                                            return keys[j];
1155:                                        }
1156:
1157:                                        public List<String> getValue() {
1158:                                            return Collections
1159:                                                    .singletonList(values[j]);
1160:                                        }
1161:
1162:                                        public List<String> setValue(
1163:                                                List<String> value) {
1164:                                            throw new UnsupportedOperationException();
1165:                                        }
1166:                                    };
1167:                                }
1168:
1169:                                public void remove() {
1170:                                    throw new UnsupportedOperationException();
1171:                                }
1172:                            };
1173:                        }
1174:                    };
1175:                }
1176:
1177:                public boolean containsKey(Object key) {
1178:                    for (int i = 0; i < keys.length; i++) {
1179:                        if (key.equals(keys[i])) {
1180:                            return true;
1181:                        }
1182:                    }
1183:                    return false;
1184:                }
1185:
1186:                public List<String> get(String key) {
1187:                    for (int i = 0; i < keys.length; i++) {
1188:                        if (key.equals(keys[i])) {
1189:                            return Collections.singletonList(values[i]);
1190:                        }
1191:                    }
1192:                    return null;
1193:                }
1194:            }
1195:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.