Source Code Cross Referenced for UnitFormat.java in  » Science » jscience-4.3.1 » javax » measure » unit » 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 » jscience 4.3.1 » javax.measure.unit 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003:         * Copyright (C) 2006 - JScience (http://jscience.org/)
004:         * All rights reserved.
005:         * 
006:         * Permission to use, copy, modify, and distribute this software is
007:         * freely granted, provided that this notice is preserved.
008:         */
009:        package javax.measure.unit;
010:
011:        import java.io.IOException;
012:        import java.lang.CharSequence;
013:        import java.text.FieldPosition;
014:        import java.text.Format;
015:        import java.text.ParseException;
016:        import java.text.ParsePosition;
017:        import java.util.HashMap;
018:        import java.util.Locale; //@RETROWEAVER import javolution.text.Appendable;
019:        import javax.measure.converter.AddConverter;
020:        import javax.measure.converter.MultiplyConverter;
021:        import javax.measure.converter.RationalConverter;
022:        import javax.measure.converter.UnitConverter;
023:        import javax.measure.quantity.Quantity;
024:
025:        import static javax.measure.unit.SI.*;
026:
027:        /**
028:         * <p> This class provides the interface for formatting and parsing {@link 
029:         *     Unit units}.</p>
030:         *     
031:         * <p> For all {@link SI} units, the 20 SI prefixes used to form decimal
032:         *     multiples and sub-multiples of SI units are recognized.
033:         *     {@link NonSI} units are directly recognized. For example:[code]
034:         *        Unit.valueOf("m°C").equals(SI.MILLI(SI.CELSIUS))
035:         *        Unit.valueOf("kW").equals(SI.KILO(SI.WATT))
036:         *        Unit.valueOf("ft").equals(SI.METER.multiply(0.3048))[/code]</p>
037:         *
038:         * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
039:         * @author Eric Russell
040:         * @version 1.3, August 29, 2006
041:         */
042:        public abstract class UnitFormat extends Format {
043:
044:            /**
045:             * Holds the standard unit format.
046:             */
047:            private static final DefaultFormat DEFAULT = new DefaultFormat();
048:
049:            /**
050:             * Holds the ASCIIFormat unit format.
051:             */
052:            private static final ASCIIFormat ASCII = new ASCIIFormat();
053:
054:            /**
055:             * Returns the unit format for the default locale (format used by 
056:             * {@link Unit#valueOf(CharSequence) Unit.valueOf(CharSequence)} and 
057:             * {@link Unit#toString() Unit.toString()}).
058:             * 
059:             *  @return the default unit format (locale sensitive).
060:             */
061:            public static UnitFormat getInstance() {
062:                return UnitFormat.getInstance(Locale.getDefault());
063:            }
064:
065:            /**
066:             * Returns the unit format for the specified locale.
067:             * 
068:             * @return the unit format for the specified locale.
069:             */
070:            public static UnitFormat getInstance(Locale inLocale) {
071:                return DEFAULT; // TBD: Implement Locale Format. 
072:            }
073:
074:            /**
075:             * Returns the <a href="http://aurora.regenstrief.org/UCUM/ucum.html">UCUM
076:             * </a> international unit format; this format uses characters range
077:             * <code>0000-007F</code> exclusively and <b>is not</b> locale-sensitive.
078:             * For example: <code>kg.m/s2</code>
079:             * 
080:             * @return the UCUM international format.
081:             */
082:            public static UnitFormat getUCUMInstance() {
083:                return UnitFormat.ASCII; // TBD - Provide UCUM implementation.
084:            }
085:
086:            /**
087:             * Base constructor.
088:             */
089:            protected UnitFormat() {
090:            }
091:
092:            /**
093:             * Formats the specified unit.
094:             *
095:             * @param unit the unit to format.
096:             * @param appendable the appendable destination.
097:             * @throws IOException if an error occurs.
098:             */
099:            public abstract Appendable format(Unit<?> unit,
100:                    Appendable appendable) throws IOException;
101:
102:            /**
103:             * Parses a sequence of character to produce a unit or a rational product
104:             * of unit. 
105:             *
106:             * @param csq the <code>CharSequence</code> to parse.
107:             * @param pos an object holding the parsing index and error position.
108:             * @return an {@link Unit} parsed from the character sequence.
109:             * @throws IllegalArgumentException if the character sequence contains
110:             *         an illegal syntax.
111:             */
112:            public abstract Unit<? extends Quantity> parseProductUnit(
113:                    CharSequence csq, ParsePosition pos) throws ParseException;
114:
115:            /**
116:             * Parses a sequence of character to produce a single unit. 
117:             *
118:             * @param csq the <code>CharSequence</code> to parse.
119:             * @param pos an object holding the parsing index and error position.
120:             * @return an {@link Unit} parsed from the character sequence.
121:             * @throws IllegalArgumentException if the character sequence does not contain 
122:             *         a valid unit identifier.
123:             */
124:            public abstract Unit<? extends Quantity> parseSingleUnit(
125:                    CharSequence csq, ParsePosition pos) throws ParseException;
126:
127:            /**
128:             * Attaches a system-wide label to the specified unit. For example:
129:             * [code]
130:             *     UnitFormat.getInstance().label(DAY.multiply(365), "year");
131:             *     UnitFormat.getInstance().label(METER.multiply(0.3048), "ft");
132:             * [/code]
133:             * If the specified label is already associated to an unit the previous 
134:             * association is discarded or ignored.
135:             *  
136:             * @param  unit the unit being labelled. 
137:             * @param  label the new label for this unit.
138:             * @throws IllegalArgumentException if the label is not a 
139:             *         {@link UnitFormat#isValidIdentifier(String)} valid identifier.
140:             */
141:            public abstract void label(Unit<?> unit, String label);
142:
143:            /**
144:             * Attaches a system-wide alias to this unit. Multiple aliases may
145:             * be attached to the same unit. Aliases are used during parsing to
146:             * recognize different variants of the same unit. For example:
147:             * [code]
148:             *     UnitFormat.getLocaleInstance().alias(METER.multiply(0.3048), "foot");
149:             *     UnitFormat.getLocaleInstance().alias(METER.multiply(0.3048), "feet");
150:             *     UnitFormat.getLocaleInstance().alias(METER, "meter");
151:             *     UnitFormat.getLocaleInstance().alias(METER, "metre");
152:             * [/code]
153:             * If the specified label is already associated to an unit the previous 
154:             * association is discarded or ignored.
155:             *
156:             * @param  unit the unit being aliased.
157:             * @param  alias the alias attached to this unit.
158:             * @throws IllegalArgumentException if the label is not a 
159:             *         {@link UnitFormat#isValidIdentifier(String)} valid identifier.
160:             */
161:            public abstract void alias(Unit<?> unit, String alias);
162:
163:            /**
164:             * Indicates if the specified name can be used as unit identifier.
165:             *
166:             * @param  name the identifier to be tested.
167:             * @return <code>true</code> if the name specified can be used as 
168:             *         label or alias for this format;<code>false</code> otherwise.
169:             */
170:            public abstract boolean isValidIdentifier(String name);
171:
172:            /**
173:             * Formats an unit and appends the resulting text to a given string
174:             * buffer (implements <code>java.text.Format</code>).
175:             *
176:             * @param unit the unit to format.
177:             * @param toAppendTo where the text is to be appended
178:             * @param pos the field position (not used).
179:             * @return <code>toAppendTo</code>
180:             */
181:            public final StringBuffer format(Object unit,
182:                    final StringBuffer toAppendTo, FieldPosition pos) {
183:                try {
184:                    Object dest = toAppendTo;
185:                    if (dest instanceof  Appendable) {
186:                        format((Unit<?>) unit, (Appendable) dest);
187:                    } else { // When retroweaver is used to produce 1.4 binaries.
188:                        format((Unit<?>) unit, new Appendable() {
189:
190:                            public Appendable append(char arg0)
191:                                    throws IOException {
192:                                toAppendTo.append(arg0);
193:                                return null;
194:                            }
195:
196:                            public Appendable append(CharSequence arg0)
197:                                    throws IOException {
198:                                toAppendTo.append(arg0);
199:                                return null;
200:                            }
201:
202:                            public Appendable append(CharSequence arg0,
203:                                    int arg1, int arg2) throws IOException {
204:                                toAppendTo.append(arg0.subSequence(arg1, arg2));
205:                                return null;
206:                            }
207:                        });
208:                    }
209:                    return toAppendTo;
210:                } catch (IOException e) {
211:                    throw new Error(e); // Should never happen.
212:                }
213:            }
214:
215:            /**
216:             * Parses the text from a string to produce an object
217:             * (implements <code>java.text.Format</code>).
218:             * 
219:             * @param source the string source, part of which should be parsed.
220:             * @param pos the cursor position.
221:             * @return the corresponding unit or <code>null</code> if the string 
222:             *         cannot be parsed.
223:             */
224:            public final Unit<?> parseObject(String source, ParsePosition pos) {
225:                int start = pos.getIndex();
226:                try {
227:                    return parseProductUnit(source, pos);
228:                } catch (ParseException e) {
229:                    pos.setIndex(start);
230:                    pos.setErrorIndex(e.getErrorOffset());
231:                    return null;
232:                }
233:            }
234:
235:            /**
236:             * This class represents an exponent with both a power (numerator)
237:             * and a root (denominator).
238:             */
239:            private static class Exponent {
240:                public final int pow;
241:                public final int root;
242:
243:                public Exponent(int pow, int root) {
244:                    this .pow = pow;
245:                    this .root = root;
246:                }
247:            }
248:
249:            /**
250:             * This class represents the standard format.
251:             */
252:            protected static class DefaultFormat extends UnitFormat {
253:
254:                /**
255:                 * Holds the name to unit mapping.
256:                 */
257:                final HashMap<String, Unit<?>> _nameToUnit = new HashMap<String, Unit<?>>();
258:
259:                /**
260:                 * Holds the unit to name mapping.
261:                 */
262:                final HashMap<Unit<?>, String> _unitToName = new HashMap<Unit<?>, String>();
263:
264:                @Override
265:                public void label(Unit<?> unit, String label) {
266:                    if (!isValidIdentifier(label))
267:                        throw new IllegalArgumentException("Label: " + label
268:                                + " is not a valid identifier.");
269:                    synchronized (this ) {
270:                        _nameToUnit.put(label, unit);
271:                        _unitToName.put(unit, label);
272:                    }
273:                }
274:
275:                @Override
276:                public void alias(Unit<?> unit, String alias) {
277:                    if (!isValidIdentifier(alias))
278:                        throw new IllegalArgumentException("Alias: " + alias
279:                                + " is not a valid identifier.");
280:                    synchronized (this ) {
281:                        _nameToUnit.put(alias, unit);
282:                    }
283:                }
284:
285:                @Override
286:                public boolean isValidIdentifier(String name) {
287:                    if ((name == null) || (name.length() == 0))
288:                        return false;
289:                    for (int i = 0; i < name.length(); i++) {
290:                        if (!isUnitIdentifierPart(name.charAt(i)))
291:                            return false;
292:                    }
293:                    return true;
294:                }
295:
296:                static boolean isUnitIdentifierPart(char ch) {
297:            return Character.isLetter(ch) || 
298:               (!Character.isWhitespace(ch) && !Character.isDigit(ch)
299:                  && (ch != '·') && (ch != '*') && (ch != '/')
300:                  && (ch != '(') && (ch != ')') && (ch != '[') && (ch != ']')    
301:                  && (ch != '¹') && (ch != '²') && (ch != '³') 
302:                  && (ch != '^') && (ch != '+') && (ch != '-'));
303:        }
304:
305:                // Returns the name for the specified unit or null if product unit.
306:                public String nameFor(Unit<?> unit) {
307:            // Searches label database.
308:            String label = _unitToName.get(unit);
309:            if (label != null)
310:                return label;
311:            if (unit instanceof  BaseUnit)
312:                return ((BaseUnit<?>) unit).getSymbol();
313:            if (unit instanceof  AlternateUnit)
314:                return ((AlternateUnit<?>) unit).getSymbol();
315:            if (unit instanceof  TransformedUnit) {
316:                TransformedUnit<?> tfmUnit = (TransformedUnit<?>) unit;
317:                Unit<?> baseUnits = tfmUnit.getStandardUnit();
318:                UnitConverter cvtr = tfmUnit.toStandardUnit();
319:                StringBuffer result = new StringBuffer();
320:                String baseUnitName = baseUnits.toString();
321:                if ((baseUnitName.indexOf('·') >= 0) ||
322:                    (baseUnitName.indexOf('*') >= 0) ||
323:                    (baseUnitName.indexOf('/') >= 0)) {
324:                    // We could use parentheses whenever baseUnits is an
325:                    // instanceof ProductUnit, but most ProductUnits have aliases,
326:                    // so we'd end up with a lot of unnecessary parentheses.
327:                    result.append('(');
328:                    result.append(baseUnitName);
329:                    result.append(')');
330:                } else {
331:                    result.append(baseUnitName);
332:                }
333:                if (cvtr instanceof  AddConverter) {
334:                    result.append('+');
335:                    result.append(((AddConverter) cvtr).getOffset());
336:                } else if (cvtr instanceof  RationalConverter) {
337:                    long dividend = ((RationalConverter) cvtr).getDividend();
338:                    if (dividend != 1) {
339:                        result.append('*');
340:                        result.append(dividend);
341:                    }
342:                    long divisor = ((RationalConverter) cvtr).getDivisor();
343:                    if (divisor != 1) {
344:                        result.append('/');
345:                        result.append(divisor);
346:                    }          ;
347:                } else if (cvtr instanceof  MultiplyConverter) {
348:                    result.append('*');
349:                    result.append(((MultiplyConverter) cvtr).getFactor());
350:                } else { // Other converters.
351:                    return "[" + baseUnits + "?]";
352:                }
353:                return result.toString();
354:            }
355:            // Compound unit.
356:            if (unit instanceof  CompoundUnit) {
357:                CompoundUnit<?> cpdUnit = (CompoundUnit<?>) unit;
358:                return nameFor(cpdUnit.getHigher()).toString() + ":"
359:                        + nameFor(cpdUnit.getLower());
360:            }
361:            return null; // Product unit.
362:        }
363:
364:                // Returns the unit for the specified name.
365:                public Unit<?> unitFor(String name) {
366:                    Unit<?> unit = _nameToUnit.get(name);
367:                    if (unit != null)
368:                        return unit;
369:                    unit = Unit.SYMBOL_TO_UNIT.get(name);
370:                    return unit;
371:                }
372:
373:                ////////////////////////////
374:                // Parsing.
375:
376:                @SuppressWarnings("unchecked")
377:                public Unit<? extends Quantity> parseSingleUnit(
378:                        CharSequence csq, ParsePosition pos)
379:                        throws ParseException {
380:                    int startIndex = pos.getIndex();
381:                    String name = readIdentifier(csq, pos);
382:                    Unit unit = unitFor(name);
383:                    check(unit != null, name + " not recognized", csq,
384:                            startIndex);
385:                    return unit;
386:                }
387:
388:                @SuppressWarnings("unchecked")
389:                @Override
390:                public Unit<? extends Quantity> parseProductUnit(
391:                        CharSequence csq, ParsePosition pos)
392:                        throws ParseException {
393:                    Unit result = Unit.ONE;
394:                    int token = nextToken(csq, pos);
395:                    switch (token) {
396:                    case IDENTIFIER:
397:                        result = parseSingleUnit(csq, pos);
398:                        break;
399:                    case OPEN_PAREN:
400:                        pos.setIndex(pos.getIndex() + 1);
401:                        result = parseProductUnit(csq, pos);
402:                        token = nextToken(csq, pos);
403:                        check(token == CLOSE_PAREN, "')' expected", csq, pos
404:                                .getIndex());
405:                        pos.setIndex(pos.getIndex() + 1);
406:                        break;
407:                    }
408:                    token = nextToken(csq, pos);
409:                    while (true) {
410:                        switch (token) {
411:                        case EXPONENT:
412:                            Exponent e = readExponent(csq, pos);
413:                            if (e.pow != 1) {
414:                                result = result.pow(e.pow);
415:                            }
416:                            if (e.root != 1) {
417:                                result = result.root(e.root);
418:                            }
419:                            break;
420:                        case MULTIPLY:
421:                            pos.setIndex(pos.getIndex() + 1);
422:                            token = nextToken(csq, pos);
423:                            if (token == INTEGER) {
424:                                long n = readLong(csq, pos);
425:                                if (n != 1) {
426:                                    result = result.times(n);
427:                                }
428:                            } else if (token == FLOAT) {
429:                                double d = readDouble(csq, pos);
430:                                if (d != 1.0) {
431:                                    result = result.times(d);
432:                                }
433:                            } else {
434:                                result = result
435:                                        .times(parseProductUnit(csq, pos));
436:                            }
437:                            break;
438:                        case DIVIDE:
439:                            pos.setIndex(pos.getIndex() + 1);
440:                            token = nextToken(csq, pos);
441:                            if (token == INTEGER) {
442:                                long n = readLong(csq, pos);
443:                                if (n != 1) {
444:                                    result = result.divide(n);
445:                                }
446:                            } else if (token == FLOAT) {
447:                                double d = readDouble(csq, pos);
448:                                if (d != 1.0) {
449:                                    result = result.divide(d);
450:                                }
451:                            } else {
452:                                result = result.divide(parseProductUnit(csq,
453:                                        pos));
454:                            }
455:                            break;
456:                        case PLUS:
457:                            pos.setIndex(pos.getIndex() + 1);
458:                            token = nextToken(csq, pos);
459:                            if (token == INTEGER) {
460:                                long n = readLong(csq, pos);
461:                                if (n != 1) {
462:                                    result = result.plus(n);
463:                                }
464:                            } else if (token == FLOAT) {
465:                                double d = readDouble(csq, pos);
466:                                if (d != 1.0) {
467:                                    result = result.plus(d);
468:                                }
469:                            } else {
470:                                throw new ParseException("not a number", pos
471:                                        .getIndex());
472:                            }
473:                            break;
474:                        case EOF:
475:                        case CLOSE_PAREN:
476:                            return result;
477:                        default:
478:                            throw new ParseException("unexpected token "
479:                                    + token, pos.getIndex());
480:                        }
481:                        token = nextToken(csq, pos);
482:                    }
483:                }
484:
485:                private static final int EOF = 0;
486:                private static final int IDENTIFIER = 1;
487:                private static final int OPEN_PAREN = 2;
488:                private static final int CLOSE_PAREN = 3;
489:                private static final int EXPONENT = 4;
490:                private static final int MULTIPLY = 5;
491:                private static final int DIVIDE = 6;
492:                private static final int PLUS = 7;
493:                private static final int INTEGER = 8;
494:                private static final int FLOAT = 9;
495:
496:                private int nextToken(CharSequence csq, ParsePosition pos) {
497:            final int length = csq.length();
498:            while (pos.getIndex() < length) {
499:                char c = csq.charAt(pos.getIndex());
500:                if (isUnitIdentifierPart(c)) {
501:                    return IDENTIFIER;
502:                } else if (c == '(') {
503:                    return OPEN_PAREN;
504:                } else if (c == ')') {
505:                    return CLOSE_PAREN;
506:                } else if ((c == '^') || (c == '¹') || (c == '²') || (c == '³')) {
507:                    return EXPONENT;
508:                } else if (c == '*') {
509:                    char c2 = csq.charAt(pos.getIndex() + 1);
510:                    if (c2 == '*') {
511:                        return EXPONENT;
512:                    } else {
513:                        return MULTIPLY;
514:                    }
515:                } else if (c == '·') {
516:                    return MULTIPLY;
517:                } else if (c == '/') {
518:                    return DIVIDE;
519:                } else if (c == '+') {
520:                    return PLUS;
521:                } else if ((c == '-') || Character.isDigit(c)) {
522:                    int index = pos.getIndex()+1;
523:                    while ((index < length) && 
524:                           (Character.isDigit(c) || (c == '-') || (c == '.') || (c == 'E'))) {
525:                        c = csq.charAt(index++);
526:                        if (c == '.') {
527:                            return FLOAT;
528:                        }
529:                    }
530:                    return INTEGER;
531:                }
532:                pos.setIndex(pos.getIndex() + 1);
533:            }
534:            return EOF;
535:        }
536:
537:                private void check(boolean expr, String message,
538:                        CharSequence csq, int index) throws ParseException {
539:                    if (!expr) {
540:                        throw new ParseException(message + " (in " + csq
541:                                + " at index " + index + ")", index);
542:                    }
543:                }
544:
545:                private Exponent readExponent (CharSequence csq, ParsePosition pos) {
546:            char c = csq.charAt(pos.getIndex());
547:            if (c == '^') {
548:                pos.setIndex(pos.getIndex()+1);
549:            } else if (c == '*') {
550:                pos.setIndex(pos.getIndex()+2);
551:            }
552:            final int length = csq.length();
553:            int pow = 0;
554:            boolean isPowNegative = false;
555:            int root = 0;
556:            boolean isRootNegative = false;
557:            boolean isRoot = false;
558:            while (pos.getIndex() < length) {
559:                c = csq.charAt(pos.getIndex());
560:                if (c == '¹') {
561:                    if (isRoot) {
562:                        root = root * 10 + 1;
563:                    } else {
564:                        pow = pow * 10 + 1;
565:                    }
566:                } else if (c == '²') {
567:                    if (isRoot) {
568:                        root = root * 10 + 2;
569:                    } else {
570:                        pow = pow * 10 + 2;
571:                    }
572:                } else if (c == '³') {
573:                    if (isRoot) {
574:                        root = root * 10 + 3;
575:                    } else {
576:                        pow = pow * 10 + 3;
577:                    }
578:                } else if (c == '-') {
579:                    if (isRoot) {
580:                        isRootNegative = true;
581:                    } else {
582:                        isPowNegative = true;
583:                    }
584:                } else if ((c >= '0') && (c <= '9')) {
585:                    if (isRoot) {
586:                        root = root * 10 + (c - '0');
587:                    } else {
588:                        pow = pow * 10 + (c - '0');
589:                    }
590:                } else if (c == ':') {
591:                    isRoot = true;
592:                } else {
593:                    break;
594:                }
595:                pos.setIndex(pos.getIndex()+1);
596:            }
597:            if (pow == 0) pow = 1;
598:            if (root == 0) root = 1;
599:            return new Exponent(isPowNegative ? -pow : pow, 
600:                              isRootNegative ? -root : root);
601:        }
602:
603:                private long readLong(CharSequence csq, ParsePosition pos) {
604:                    final int length = csq.length();
605:                    int result = 0;
606:                    boolean isNegative = false;
607:                    while (pos.getIndex() < length) {
608:                        char c = csq.charAt(pos.getIndex());
609:                        if (c == '-') {
610:                            isNegative = true;
611:                        } else if ((c >= '0') && (c <= '9')) {
612:                            result = result * 10 + (c - '0');
613:                        } else {
614:                            break;
615:                        }
616:                        pos.setIndex(pos.getIndex() + 1);
617:                    }
618:                    return isNegative ? -result : result;
619:                }
620:
621:                private double readDouble(CharSequence csq, ParsePosition pos) {
622:                    final int length = csq.length();
623:                    int start = pos.getIndex();
624:                    int end = start + 1;
625:                    while (end < length) {
626:                        if ("012356789+-.E".indexOf(csq.charAt(end)) < 0) {
627:                            break;
628:                        }
629:                        end += 1;
630:                    }
631:                    pos.setIndex(end + 1);
632:                    return Double.parseDouble(csq.subSequence(start, end)
633:                            .toString());
634:                }
635:
636:                private String readIdentifier(CharSequence csq,
637:                        ParsePosition pos) {
638:                    final int length = csq.length();
639:                    int start = pos.getIndex();
640:                    int i = start;
641:                    while ((++i < length)
642:                            && isUnitIdentifierPart(csq.charAt(i))) {
643:                    }
644:                    pos.setIndex(i);
645:                    return csq.subSequence(start, i).toString();
646:                }
647:
648:                ////////////////////////////
649:                // Formatting.
650:
651:                @Override
652:        public Appendable format(Unit<?> unit, Appendable appendable)
653:                throws IOException {
654:            String name = nameFor(unit);
655:            if (name != null)
656:                return appendable.append(name);
657:            if (!(unit instanceof  ProductUnit))
658:                throw new IllegalArgumentException("Cannot format given Object as a Unit");
659:
660:            // Product unit.
661:            ProductUnit<?> productUnit = (ProductUnit<?>) unit;
662:            int invNbr = 0;
663:
664:            // Write positive exponents first.
665:            boolean start = true;
666:            for (int i = 0; i < productUnit.getUnitCount(); i++) {
667:                int pow = productUnit.getUnitPow(i);
668:                if (pow >= 0) {
669:                    if (!start) {
670:                        appendable.append('·'); // Separator.
671:                    }
672:                    name = nameFor(productUnit.getUnit(i));
673:                    int root = productUnit.getUnitRoot(i);
674:                    append(appendable, name, pow, root);
675:                    start = false;
676:                } else {
677:                    invNbr++;
678:                }
679:            }
680:
681:            // Write negative exponents.
682:            if (invNbr != 0) {
683:                if (start) {
684:                    appendable.append('1'); // e.g. 1/s
685:                }
686:                appendable.append('/');
687:                if (invNbr > 1) {
688:                    appendable.append('(');
689:                }
690:                start = true;
691:                for (int i = 0; i < productUnit.getUnitCount(); i++) {
692:                    int pow = productUnit.getUnitPow(i);
693:                    if (pow < 0) {
694:                        name = nameFor(productUnit.getUnit(i));
695:                        int root = productUnit.getUnitRoot(i);
696:                        if (!start) {
697:                            appendable.append('·'); // Separator.
698:                        }
699:                        append(appendable, name, -pow, root);
700:                        start = false;
701:                    }
702:                }
703:                if (invNbr > 1) {
704:                    appendable.append(')');
705:                }
706:            }
707:            return appendable;
708:        }
709:
710:                private void append(Appendable appendable, CharSequence symbol,
711:                int pow, int root) throws IOException {
712:            appendable.append(symbol);
713:            if ((pow != 1) || (root != 1)) {
714:                // Write exponent.
715:                if ((pow == 2) && (root == 1)) {
716:                    appendable.append('²'); // Square
717:                } else if ((pow == 3) && (root == 1)) {
718:                    appendable.append('³'); // Cubic
719:                } else {
720:                    // Use general exponent form.
721:                    appendable.append('^');
722:                    appendable.append(String.valueOf(pow));
723:                    if (root != 1) {
724:                        appendable.append(':');
725:                        appendable.append(String.valueOf(root));
726:                    }
727:                }
728:            }
729:        }
730:
731:                private static final long serialVersionUID = 1L;
732:            }
733:
734:            /**
735:             * This class represents the ASCIIFormat format.
736:             */
737:            protected static class ASCIIFormat extends DefaultFormat {
738:
739:                @Override
740:                public String nameFor(Unit<?> unit) {
741:                    // First search if specific ASCII name should be used.
742:                    String name = _unitToName.get(unit);
743:                    if (name != null)
744:                        return name;
745:                    // Else returns default name.
746:                    return DEFAULT.nameFor(unit);
747:                }
748:
749:                @Override
750:                public Unit<?> unitFor(String name) {
751:                    // First search if specific ASCII name.
752:                    Unit<?> unit = _nameToUnit.get(name);
753:                    if (unit != null)
754:                        return unit;
755:                    // Else returns default mapping.
756:                    return DEFAULT.unitFor(name);
757:                }
758:
759:                @Override
760:                public Appendable format(Unit<?> unit, Appendable appendable)
761:                        throws IOException {
762:                    String name = nameFor(unit);
763:                    if (name != null)
764:                        return appendable.append(name);
765:                    if (!(unit instanceof  ProductUnit))
766:                        throw new IllegalArgumentException(
767:                                "Cannot format given Object as a Unit");
768:
769:                    ProductUnit<?> productUnit = (ProductUnit<?>) unit;
770:                    for (int i = 0; i < productUnit.getUnitCount(); i++) {
771:                        if (i != 0) {
772:                            appendable.append('*'); // Separator.
773:                        }
774:                        name = nameFor(productUnit.getUnit(i));
775:                        int pow = productUnit.getUnitPow(i);
776:                        int root = productUnit.getUnitRoot(i);
777:                        appendable.append(name);
778:                        if ((pow != 1) || (root != 1)) {
779:                            // Use general exponent form.
780:                            appendable.append('^');
781:                            appendable.append(String.valueOf(pow));
782:                            if (root != 1) {
783:                                appendable.append(':');
784:                                appendable.append(String.valueOf(root));
785:                            }
786:                        }
787:                    }
788:                    return appendable;
789:                }
790:
791:                private static final long serialVersionUID = 1L;
792:            }
793:
794:            ////////////////////////////////////////////////////////////////////////////
795:            // Initializes the standard unit database for SI units.
796:
797:            private static final Unit<?>[] SI_UNITS = { SI.AMPERE,
798:                    SI.BECQUEREL, SI.CANDELA, SI.COULOMB, SI.FARAD, SI.GRAY,
799:                    SI.HENRY, SI.HERTZ, SI.JOULE, SI.KATAL, SI.KELVIN,
800:                    SI.LUMEN, SI.LUX, SI.METRE, SI.MOLE, SI.NEWTON, SI.OHM,
801:                    SI.PASCAL, SI.RADIAN, SI.SECOND, SI.SIEMENS, SI.SIEVERT,
802:                    SI.STERADIAN, SI.TESLA, SI.VOLT, SI.WATT, SI.WEBER };
803:
804:            private static final String[] PREFIXES = { "Y", "Z", "E", "P", "T",
805:                    "G", "M", "k", "h", "da", "d", "c", "m", "µ", "n", "p",
806:                    "f", "a", "z", "y" };
807:
808:            private static final UnitConverter[] CONVERTERS = { E24, E21, E18,
809:                    E15, E12, E9, E6, E3, E2, E1, Em1, Em2, Em3, Em6, Em9,
810:                    Em12, Em15, Em18, Em21, Em24 };
811:
812:            private static String asciiPrefix(String prefix) {
813:                return prefix == "µ" ? "micro" : prefix;
814:            }
815:
816:            static {
817:                for (int i = 0; i < SI_UNITS.length; i++) {
818:                    for (int j = 0; j < PREFIXES.length; j++) {
819:                        Unit<?> si = SI_UNITS[i];
820:                        Unit<?> u = si.transform(CONVERTERS[j]);
821:                        String symbol = (si instanceof  BaseUnit) ? ((BaseUnit<?>) si)
822:                                .getSymbol()
823:                                : ((AlternateUnit<?>) si).getSymbol();
824:                        DEFAULT.label(u, PREFIXES[j] + symbol);
825:                        if (PREFIXES[j] == "µ") {
826:                            ASCII.label(u, "micro" + symbol);
827:                        }
828:                    }
829:                }
830:                // Special case for KILOGRAM.
831:                DEFAULT.label(SI.GRAM, "g");
832:                for (int i = 0; i < PREFIXES.length; i++) {
833:                    if (CONVERTERS[i] == E3)
834:                        continue; // kg is already defined.
835:                    DEFAULT.label(SI.KILOGRAM.transform(CONVERTERS[i]
836:                            .concatenate(Em3)), PREFIXES[i] + "g");
837:                    if (PREFIXES[i] == "µ") {
838:                        ASCII.label(SI.KILOGRAM.transform(CONVERTERS[i]
839:                                .concatenate(Em3)), "microg");
840:                    }
841:                }
842:
843:                // Alias and ASCIIFormat for Ohm
844:                DEFAULT.alias(SI.OHM, "Ohm");
845:                ASCII.label(SI.OHM, "Ohm");
846:                for (int i = 0; i < PREFIXES.length; i++) {
847:                    DEFAULT.alias(SI.OHM.transform(CONVERTERS[i]), PREFIXES[i]
848:                            + "Ohm");
849:                    ASCII.label(SI.OHM.transform(CONVERTERS[i]),
850:                            asciiPrefix(PREFIXES[i]) + "Ohm");
851:                }
852:
853:                // Special case for DEGREE_CElSIUS.
854:                DEFAULT.label(SI.CELSIUS, "℃");
855:                DEFAULT.alias(SI.CELSIUS, "°C");
856:                ASCII.label(SI.CELSIUS, "Celsius");
857:                for (int i = 0; i < PREFIXES.length; i++) {
858:                    DEFAULT.label(SI.CELSIUS.transform(CONVERTERS[i]),
859:                            PREFIXES[i] + "℃");
860:                    DEFAULT.alias(SI.CELSIUS.transform(CONVERTERS[i]),
861:                            PREFIXES[i] + "°C");
862:                    ASCII.label(SI.CELSIUS.transform(CONVERTERS[i]),
863:                            asciiPrefix(PREFIXES[i]) + "Celsius");
864:                }
865:            }
866:
867:            ////////////////////////////////////////////////////////////////////////////
868:            // To be moved in resource bundle in future release (locale dependent). 
869:            static {
870:                DEFAULT.label(NonSI.PERCENT, "%");
871:                DEFAULT.label(NonSI.DECIBEL, "dB");
872:                DEFAULT.label(NonSI.G, "grav");
873:                DEFAULT.label(NonSI.ATOM, "atom");
874:                DEFAULT.label(NonSI.REVOLUTION, "rev");
875:                DEFAULT.label(NonSI.DEGREE_ANGLE, "°");
876:                ASCII.label(NonSI.DEGREE_ANGLE, "degree_angle");
877:                DEFAULT.label(NonSI.MINUTE_ANGLE, "'");
878:                DEFAULT.label(NonSI.SECOND_ANGLE, "\"");
879:                DEFAULT.label(NonSI.CENTIRADIAN, "centiradian");
880:                DEFAULT.label(NonSI.GRADE, "grade");
881:                DEFAULT.label(NonSI.ARE, "a");
882:                DEFAULT.label(NonSI.HECTARE, "ha");
883:                DEFAULT.label(NonSI.BYTE, "byte");
884:                DEFAULT.label(NonSI.MINUTE, "min");
885:                DEFAULT.label(NonSI.HOUR, "h");
886:                DEFAULT.label(NonSI.DAY, "day");
887:                DEFAULT.label(NonSI.WEEK, "week");
888:                DEFAULT.label(NonSI.YEAR, "year");
889:                DEFAULT.label(NonSI.MONTH, "month");
890:                DEFAULT.label(NonSI.DAY_SIDEREAL, "day_sidereal");
891:                DEFAULT.label(NonSI.YEAR_SIDEREAL, "year_sidereal");
892:                DEFAULT.label(NonSI.YEAR_CALENDAR, "year_calendar");
893:                DEFAULT.label(NonSI.E, "e");
894:                DEFAULT.label(NonSI.FARADAY, "Fd");
895:                DEFAULT.label(NonSI.FRANKLIN, "Fr");
896:                DEFAULT.label(NonSI.GILBERT, "Gi");
897:                DEFAULT.label(NonSI.ERG, "erg");
898:                DEFAULT.label(NonSI.ELECTRON_VOLT, "eV");
899:                DEFAULT.label(SI.KILO(NonSI.ELECTRON_VOLT), "keV");
900:                DEFAULT.label(SI.MEGA(NonSI.ELECTRON_VOLT), "MeV");
901:                DEFAULT.label(SI.GIGA(NonSI.ELECTRON_VOLT), "GeV");
902:                DEFAULT.label(NonSI.LAMBERT, "La");
903:                DEFAULT.label(NonSI.FOOT, "ft");
904:                DEFAULT.label(NonSI.FOOT_SURVEY_US, "foot_survey_us");
905:                DEFAULT.label(NonSI.YARD, "yd");
906:                DEFAULT.label(NonSI.INCH, "in");
907:                DEFAULT.label(NonSI.MILE, "mi");
908:                DEFAULT.label(NonSI.NAUTICAL_MILE, "nmi");
909:                DEFAULT.label(NonSI.MILES_PER_HOUR, "mph");
910:                DEFAULT.label(NonSI.ANGSTROM, "Å");
911:                ASCII.label(NonSI.ANGSTROM, "Angstrom");
912:                DEFAULT.label(NonSI.ASTRONOMICAL_UNIT, "ua");
913:                DEFAULT.label(NonSI.LIGHT_YEAR, "ly");
914:                DEFAULT.label(NonSI.PARSEC, "pc");
915:                DEFAULT.label(NonSI.POINT, "pt");
916:                DEFAULT.label(NonSI.PIXEL, "pixel");
917:                DEFAULT.label(NonSI.MAXWELL, "Mx");
918:                DEFAULT.label(NonSI.GAUSS, "G");
919:                DEFAULT.label(NonSI.ATOMIC_MASS, "u");
920:                DEFAULT.label(NonSI.ELECTRON_MASS, "me");
921:                DEFAULT.label(NonSI.POUND, "lb");
922:                DEFAULT.label(NonSI.OUNCE, "oz");
923:                DEFAULT.label(NonSI.TON_US, "ton_us");
924:                DEFAULT.label(NonSI.TON_UK, "ton_uk");
925:                DEFAULT.label(NonSI.METRIC_TON, "t");
926:                DEFAULT.label(NonSI.DYNE, "dyn");
927:                DEFAULT.label(NonSI.KILOGRAM_FORCE, "kgf");
928:                DEFAULT.label(NonSI.POUND_FORCE, "lbf");
929:                DEFAULT.label(NonSI.HORSEPOWER, "hp");
930:                DEFAULT.label(NonSI.ATMOSPHERE, "atm");
931:                DEFAULT.label(NonSI.BAR, "bar");
932:                DEFAULT.label(NonSI.MILLIMETER_OF_MERCURY, "mmHg");
933:                DEFAULT.label(NonSI.INCH_OF_MERCURY, "inHg");
934:                DEFAULT.label(NonSI.RAD, "rd");
935:                DEFAULT.label(NonSI.REM, "rem");
936:                DEFAULT.label(NonSI.CURIE, "Ci");
937:                DEFAULT.label(NonSI.RUTHERFORD, "Rd");
938:                DEFAULT.label(NonSI.SPHERE, "sphere");
939:                DEFAULT.label(NonSI.RANKINE, "°R");
940:                ASCII.label(NonSI.RANKINE, "degree_rankine");
941:                DEFAULT.label(NonSI.FAHRENHEIT, "°F");
942:                ASCII.label(NonSI.FAHRENHEIT, "degree_fahrenheit");
943:                DEFAULT.label(NonSI.KNOT, "kn");
944:                DEFAULT.label(NonSI.MACH, "Mach");
945:                DEFAULT.label(NonSI.C, "c");
946:                DEFAULT.label(NonSI.LITRE, "L");
947:                DEFAULT.label(SI.MICRO(NonSI.LITRE), "µL");
948:                ASCII.label(SI.MICRO(NonSI.LITRE), "microL");
949:                DEFAULT.label(SI.MILLI(NonSI.LITRE), "mL");
950:                DEFAULT.label(SI.CENTI(NonSI.LITRE), "cL");
951:                DEFAULT.label(SI.DECI(NonSI.LITRE), "dL");
952:                DEFAULT.label(NonSI.GALLON_LIQUID_US, "gal");
953:                DEFAULT.label(NonSI.OUNCE_LIQUID_US, "oz");
954:                DEFAULT.label(NonSI.GALLON_DRY_US, "gallon_dry_us");
955:                DEFAULT.label(NonSI.GALLON_UK, "gallon_uk");
956:                DEFAULT.label(NonSI.OUNCE_LIQUID_UK, "oz_uk");
957:                DEFAULT.label(NonSI.ROENTGEN, "Roentgen");
958:                if (Locale.getDefault().getCountry().equals("GB")) {
959:                    DEFAULT.label(NonSI.GALLON_UK, "gal");
960:                    DEFAULT.label(NonSI.OUNCE_LIQUID_UK, "oz");
961:                }
962:            }
963:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.