Source Code Cross Referenced for Casting.java in  » Database-ORM » MMBase » org » mmbase » 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 » Database ORM » MMBase » org.mmbase.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:        This software is OSI Certified Open Source Software.
0004:        OSI Certified is a certification mark of the Open Source Initiative.
0005:
0006:        The license (Mozilla version 1.0) can be read at the MMBase site.
0007:        See http://www.MMBase.org/license
0008:
0009:         */
0010:
0011:        package org.mmbase.util;
0012:
0013:        /**
0014:         * Collects MMBase specific 'cast' information, as static to... functions. This is used (and used to
0015:         * be implemented) in MMObjectNode. But this functionality is more generic to MMbase.
0016:         *
0017:         * @author Michiel Meeuwissen
0018:         * @since  MMBase-1.6
0019:         * @version $Id: Casting.java,v 1.108 2007/12/11 14:47:19 michiel Exp $
0020:         */
0021:
0022:        import java.util.*;
0023:        import java.text.*;
0024:        import java.io.*;
0025:        import javax.xml.parsers.*;
0026:        import org.mmbase.bridge.*;
0027:        import org.mmbase.bridge.Node;
0028:        import org.mmbase.bridge.util.NodeWrapper;
0029:        import org.mmbase.bridge.util.NodeMap;
0030:        import org.mmbase.bridge.util.MapNode;
0031:        import org.mmbase.util.transformers.CharTransformer;
0032:        import org.mmbase.util.logging.*;
0033:        import org.mmbase.util.xml.XMLWriter;
0034:
0035:        import org.w3c.dom.*;
0036:
0037:        public class Casting {
0038:
0039:            private static final Logger log = Logging
0040:                    .getLoggerInstance(Casting.class);
0041:
0042:            /**
0043:             * A Date formatter that creates a date based on a ISO 8601 date and a ISO 8601 time.
0044:             * I.e. 2004-12-01 14:30:00.
0045:             * It is NOT 100% ISO 8601, as opposed to {@link #ISO_8601_UTC}, as the standard actually requires
0046:             * a 'T' to be placed between the date and the time.
0047:             * The date given is the date for the local (server) time. Use this formatter if you want to display
0048:             * user-friendly dates in local time.
0049:
0050:             * XXX: According to http://en.wikipedia.org/wiki/ISO_8601, the standard allows ' ' in stead of
0051:             * 'T' if no misunderstanding arises, which is the case here. So I don't think this is 'loose'.
0052:             */
0053:            public final static ThreadLocal<DateFormat> ISO_8601_LOOSE = new ThreadLocal<DateFormat>() {
0054:                protected synchronized DateFormat initialValue() {
0055:                    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
0056:                            Locale.US);
0057:                }
0058:            };
0059:
0060:            /**
0061:             * A Date formatter that creates a ISO 8601 datetime according to UTC/GMT.
0062:             * I.e. 2004-12-01T14:30:00Z.
0063:             * This is 100% ISO 8601, as opposed to {@link #ISO_8601_LOOSE}.
0064:             * Use this formatter if you want to export dates.
0065:             *
0066:             * XXX: Hmm, we parse with UTC now, while we don't store them as such.
0067:             */
0068:            public final static ThreadLocal<DateFormat> ISO_8601_UTC = new ThreadLocal<DateFormat>() {
0069:                protected synchronized DateFormat initialValue() {
0070:                    DateFormat df = new SimpleDateFormat(
0071:                            "yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
0072:                    try {
0073:                        df.setTimeZone(TimeZone.getTimeZone("UTC"));
0074:                    } catch (Throwable t) {
0075:                        log.warn(t.getMessage(), t);
0076:                    }
0077:                    return df;
0078:                }
0079:            };
0080:
0081:            public final static ThreadLocal<DateFormat> ISO_8601_DATE = new ThreadLocal<DateFormat>() {
0082:                protected synchronized DateFormat initialValue() {
0083:                    return new SimpleDateFormat("yyyy-MM-dd", Locale.US);
0084:                }
0085:            };
0086:            public final static ThreadLocal<DateFormat> ISO_8601_TIME = new ThreadLocal<DateFormat>() {
0087:                protected synchronized DateFormat initialValue() {
0088:                    return new SimpleDateFormat("HH:mm:ss", Locale.US);
0089:                }
0090:            };
0091:
0092:            /**
0093:             * Returns whether the passed object is of the given class.
0094:             * Unlike Class instanceof this also includes Object Types that
0095:             * are representative for primitive types (i.e. Integer for int).
0096:             * @param type the type (class) to check
0097:             * @param value the value whose type to check
0098:             * @return <code>true</code> if compatible
0099:             * @since MMBase-1.8
0100:             */
0101:            public static boolean isType(Class type, Object value) {
0102:                if (type.isPrimitive()) {
0103:                    return (type.equals(Boolean.TYPE) && value instanceof  Boolean)
0104:                            || (type.equals(Byte.TYPE) && value instanceof  Byte)
0105:                            || (type.equals(Character.TYPE) && value instanceof  Character)
0106:                            || (type.equals(Short.TYPE) && value instanceof  Short)
0107:                            || (type.equals(Integer.TYPE) && value instanceof  Integer)
0108:                            || (type.equals(Long.TYPE) && value instanceof  Long)
0109:                            || (type.equals(Float.TYPE) && value instanceof  Float)
0110:                            || (type.equals(Double.TYPE) && value instanceof  Double);
0111:                } else {
0112:                    return value == null || type.isInstance(value);
0113:                }
0114:            }
0115:
0116:            /**
0117:             * Tries to 'cast' an object for use with the provided class. E.g. if value is a String, but the
0118:             * type passed is Integer, then the string is act to an Integer.
0119:             * If the type passed is a primitive type, the object is cast to an Object Types that is representative
0120:             * for that type (i.e. Integer for int).
0121:             * @param type the type (class)
0122:             * @param value The value to be converted
0123:             * @return value the converted value
0124:             * @since MMBase-1.8
0125:             */
0126:            public static <C> C toType(Class<C> type, Object value) {
0127:                return toType(type, null, value);
0128:            }
0129:
0130:            private static Cloud anonymousCloud = null;
0131:
0132:            /**
0133:             * Tries to 'cast' an object for use with the provided class. E.g. if value is a String, but the
0134:             * type passed is Integer, then the string is act to an Integer.
0135:             * If the type passed is a primitive type, the object is cast to an Object Types that is representative
0136:             * for that type (i.e. Integer for int).
0137:             * @param type the type (class)
0138:             * @param cloud When casting to Node, a cloud may be needed. May be <code>null</code>, for an anonymous cloud to be tried.
0139:             * @param value The value to be converted
0140:             * @return value the converted value
0141:             * @since MMBase-1.8
0142:             */
0143:            public static <C> C toType(Class<C> type, Cloud cloud, Object value) {
0144:                if (value != null && isType(type, value)) {
0145:                    return (C) value;
0146:                } else {
0147:                    if (type.equals(Boolean.TYPE) || type.equals(Boolean.class)) {
0148:                        return (C) Boolean.valueOf(toBoolean(value));
0149:                    } else if (type.equals(Byte.TYPE)
0150:                            || type.equals(Byte.class)) {
0151:                        return (C) Byte.valueOf(toInteger(value).byteValue());
0152:                    } else if (type.equals(Character.TYPE)
0153:                            || type.equals(Character.class)) {
0154:                        String chars = toString(value);
0155:                        if (chars.length() > 0) {
0156:                            return (C) Character.valueOf(chars.charAt(0));
0157:                        } else {
0158:                            return (C) Character.valueOf(Character.MIN_VALUE);
0159:                        }
0160:                    } else if (type.equals(Short.TYPE)
0161:                            || type.equals(Short.class)) {
0162:                        return (C) Short.valueOf(toInteger(value).shortValue());
0163:                    } else if (type.equals(Integer.TYPE)
0164:                            || type.equals(Integer.class)) {
0165:                        return (C) toInteger(value);
0166:                    } else if (type.equals(Long.TYPE)
0167:                            || type.equals(Long.class)) {
0168:                        return (C) Long.valueOf(toLong(value));
0169:                    } else if (type.equals(Float.TYPE)
0170:                            || type.equals(Float.class)) {
0171:                        return (C) Float.valueOf(toFloat(value));
0172:                    } else if (type.equals(Double.TYPE)
0173:                            || type.equals(Double.class)) {
0174:                        return (C) Double.valueOf(toDouble(value));
0175:                    } else if (type.equals(Number.class)) {
0176:                        Number res;
0177:                        try {
0178:                            res = Long.valueOf("" + value);
0179:                        } catch (NumberFormatException nfe) {
0180:                            try {
0181:                                res = Double.valueOf("" + value);
0182:                            } catch (NumberFormatException nfe1) {
0183:                                res = Integer.valueOf(-1);
0184:                            }
0185:                        }
0186:                        return (C) res;
0187:                    } else if (type.equals(byte[].class)) {
0188:                        return (C) toByte(value);
0189:                    } else if (type.equals(String.class)) {
0190:                        return (C) toString(value);
0191:                    } else if (type.equals(Date.class)) {
0192:                        return (C) toDate(value);
0193:                    } else if (type.equals(Node.class)) {
0194:                        try {
0195:                            if (cloud == null) {
0196:                                if (anonymousCloud == null)
0197:                                    anonymousCloud = ContextProvider
0198:                                            .getDefaultCloudContext().getCloud(
0199:                                                    "mmbase");
0200:                                cloud = anonymousCloud;
0201:                            }
0202:                            return (C) toNode(value, cloud);
0203:                        } catch (Exception e) {
0204:                            // suppose that that was because mmbase not running
0205:                            return (C) (value instanceof  Node ? value : null);
0206:                        }
0207:                    } else if (type.equals(Document.class)) {
0208:                        return (C) toXML(value);
0209:                    } else if (type.equals(List.class)) {
0210:                        return (C) toList(value);
0211:                    } else if (type.equals(Map.class)) {
0212:                        return (C) toMap(value);
0213:                    } else if (type.equals(Collection.class)) {
0214:                        return (C) toCollection(value);
0215:                    } else {
0216:                        if (value == null || "".equals(value)) {
0217:                            // just to avoid the error
0218:                            return null;
0219:                        }
0220:                        log.error("Dont now how to convert to " + type);
0221:                        // don't know
0222:                        return (C) value;
0223:                    }
0224:                }
0225:            }
0226:
0227:            /**
0228:             * Whether or not Casting can more or less reliably cast a certain type to String and back.
0229:             * For collection types also the entries of the collection must be string representable.
0230:             * @since MMBase-1.8
0231:             */
0232:            public static boolean isStringRepresentable(Class type) {
0233:                return CharSequence.class.isAssignableFrom(type)
0234:                        || Number.class.isAssignableFrom(type)
0235:                        || Boolean.TYPE.isAssignableFrom(type)
0236:                        || Boolean.class.isAssignableFrom(type)
0237:                        || Character.class.isAssignableFrom(type)
0238:                        || Node.class.isAssignableFrom(type)
0239:                        || Document.class.isAssignableFrom(type)
0240:                        || Collection.class.isAssignableFrom(type)
0241:                        || Date.class.isAssignableFrom(type)
0242:                        || Map.class.isAssignableFrom(type);
0243:            }
0244:
0245:            /**
0246:             * Convert an object to a String.
0247:             * <code>null</code> is converted to an empty string.
0248:             * @param o the object to convert
0249:             * @return the converted value as a <code>String</code>
0250:             */
0251:            public static String toString(Object o) {
0252:                if (o instanceof  String) {
0253:                    return (String) o;
0254:                }
0255:                if (o == null || "".equals(o)) {
0256:                    return "";
0257:                }
0258:
0259:                return toStringBuilder(new StringBuilder(), o).toString();
0260:            }
0261:
0262:            /**
0263:             * Convert an object to a string, using a StringBuffer.
0264:             * @param buffer The StringBuffer with which to create the string
0265:             * @param o the object to convert
0266:             * @return the StringBuffer used for conversion (same as the buffer parameter)
0267:             * @since MMBase-1.7
0268:             */
0269:            public static StringBuffer toStringBuffer(StringBuffer buffer,
0270:                    Object o) {
0271:                if (o == null) {
0272:                    return buffer;
0273:                }
0274:                try {
0275:                    toWriter(new StringBufferWriter(buffer), o);
0276:                } catch (java.io.IOException e) {
0277:                }
0278:                return buffer;
0279:            }
0280:
0281:            /**
0282:             * Convert an object to a string, using a StringBuilder
0283:             * @param buffer The StringBuilder with which to create the string
0284:             * @param o the object to convert
0285:             * @return the StringBuilder used for conversion (same as the buffer parameter)
0286:             * @since MMBase-1.9
0287:             */
0288:            public static StringBuilder toStringBuilder(StringBuilder buffer,
0289:                    Object o) {
0290:                if (o == null) {
0291:                    return buffer;
0292:                }
0293:                try {
0294:                    toWriter(new StringBuilderWriter(buffer), o);
0295:                } catch (java.io.IOException e) {
0296:                }
0297:                return buffer;
0298:            }
0299:
0300:            private static org.mmbase.storage.search.implementation.database.BasicSqlHandler sqlHandler = new org.mmbase.storage.search.implementation.database.BasicSqlHandler();
0301:
0302:            /**
0303:             * Convert an object to a string, using a Writer.
0304:             * @param writer The Writer with which to create (write) the string
0305:             * @param o the object to convert
0306:             * @return the Writer used for conversion (same as the writer parameter)
0307:             * @since MMBase-1.7
0308:             */
0309:            public static Writer toWriter(Writer writer, Object o)
0310:                    throws java.io.IOException {
0311:                if (o instanceof  Writer) {
0312:                    return writer;
0313:                }
0314:                Object s = wrap(o, null);
0315:                if (s instanceof  org.mmbase.storage.search.SearchQuery) {
0316:                    try {
0317:                        s = sqlHandler.toSql(
0318:                                (org.mmbase.storage.search.SearchQuery) s,
0319:                                sqlHandler);
0320:                    } catch (org.mmbase.storage.search.SearchQueryException sqe) {
0321:                    }
0322:                }
0323:                writer.write(s.toString());
0324:                return writer;
0325:            }
0326:
0327:            /**
0328:             * Wraps an object in another object with a toString as we desire. Casting can now be done with
0329:             * toString() on the resulting object.
0330:             *
0331:             * This is used to make JSTL en EL behave similarly as mmbase taglib when writing objects to the
0332:             * page (taglib calls Casting, but JSTL of course doesn't).
0333:             *
0334:             * @todo  Not everything is wrapped (and can be unwrapped) already.
0335:             * @param o        The object to be wrapped
0336:             * @param escaper  <code>null</code> or a CharTransformer to pipe the strings through
0337:             * @since MMBase-1.8
0338:             */
0339:
0340:            public static Object wrap(final Object o,
0341:                    final CharTransformer escaper) {
0342:                if (o == null) {
0343:                    return escape(escaper, "");
0344:                } else if (o instanceof  Unwrappable) {
0345:                    return o;
0346:                } else if (o instanceof  Node) {
0347:                    return new NodeMap((Node) o) {
0348:
0349:                        public Object getValue(String fieldName) {
0350:                            NodeManager nm = getNodeManager();
0351:                            if (nm.hasField(fieldName)) {
0352:                                switch (nm.getField(fieldName).getType()) {
0353:                                case org.mmbase.bridge.Field.TYPE_NODE:
0354:                                    return wrap(getNodeValue(fieldName),
0355:                                            escaper);
0356:                                case org.mmbase.bridge.Field.TYPE_DATETIME:
0357:                                    return wrap(getDateValue(fieldName),
0358:                                            escaper);
0359:                                case org.mmbase.bridge.Field.TYPE_XML:
0360:                                    return wrap(getXMLValue(fieldName), escaper);
0361:                                default:
0362:                                    return escape(escaper, super 
0363:                                            .getStringValue(fieldName));
0364:                                }
0365:                            } else {
0366:                                return escape(escaper, super 
0367:                                        .getStringValue(fieldName));
0368:                            }
0369:                        }
0370:
0371:                        public String toString() {
0372:                            return escape(escaper, "" + node.getNumber());
0373:                        }
0374:                    };
0375:                } else if (o instanceof  Date) {
0376:                    return new java.util.Date(((Date) o).getTime()) {
0377:                        private static final long serialVersionUID = 1L; // increase this if object chages.
0378:
0379:                        public String toString() {
0380:                            long time = getTime();
0381:                            return time == -1 ? "-1" : ("" + time / 1000);
0382:                        }
0383:                    };
0384:                } else if (o instanceof  org.w3c.dom.Node) {
0385:                    // don't know how to wrap
0386:                    return escape(escaper, XMLWriter.write(
0387:                            (org.w3c.dom.Node) o, false, true));
0388:                } else if (o instanceof  org.mmbase.bridge.NodeList) {
0389:                    return new NodeListWrapper((org.mmbase.bridge.NodeList) o,
0390:                            escaper);
0391:                } else if (o instanceof  List) {
0392:                    return new ListWrapper((List) o, escaper);
0393:                } else if (o instanceof  byte[]) {
0394:                    return escape(escaper, new String((byte[]) o));
0395:                } else if (o instanceof  String) {
0396:                    return escape(escaper, (String) o);
0397:                } else if (o instanceof  CharSequence) {
0398:                    return new StringWrapper((CharSequence) o, escaper);
0399:                } else {
0400:                    return o;
0401:                }
0402:
0403:            }
0404:
0405:            private static String escape(CharTransformer escaper,
0406:                    CharSequence string) {
0407:                if (escaper != null) {
0408:                    return escaper.transform(string.toString());
0409:                } else {
0410:                    return string.toString();
0411:                }
0412:            }
0413:
0414:            /**
0415:             * When you want to undo the wrapping, this method can be used.
0416:             * @since MMBase-1.8
0417:             */
0418:            public static Object unWrap(final Object o) {
0419:                if (o instanceof  NodeWrapper) {
0420:                    return ((NodeWrapper) o).getNode();
0421:                } else if (o instanceof  NodeListWrapper) {
0422:                    return ((NodeListWrapper) o).getCollection();
0423:                } else if (o instanceof  ListWrapper) {
0424:                    return ((ListWrapper) o).getList();
0425:                } else if (o instanceof  StringWrapper) {
0426:                    return ((StringWrapper) o).getString();
0427:                } else {
0428:                    return o;
0429:                }
0430:            }
0431:
0432:            /**
0433:             * Convert an object to a List.
0434:             * A String is split up (as if it was a comma-separated String).
0435:             * Individual objects are wrapped and returned as Lists with one item.
0436:             * <code>null</code> and the empty string are  returned as an empty list.
0437:             * @param o the object to convert
0438:             * @return the converted value as a <code>List</code>
0439:             * @since MMBase-1.7
0440:             */
0441:            public static List toList(Object o) {
0442:                return toList(o, ",");
0443:            }
0444:
0445:            /**
0446:             * As {@link #toList(Object)} but with one extra argument.
0447:             *
0448:             * @param delimiter Regexp to use when splitting up the string if the object is a String. <code>null</code> or the empty string mean the default, which is a comma.
0449:             * @since MMBase-1.8
0450:             */
0451:            public static List toList(Object o, String delimiter) {
0452:                if (o instanceof  List) {
0453:                    return (List) o;
0454:                } else if (o instanceof  Collection) {
0455:                    return new ArrayList((Collection) o);
0456:                } else if (o instanceof  String) {
0457:                    if ("".equals(delimiter) || delimiter == null)
0458:                        delimiter = ",";
0459:                    return StringSplitter.split((String) o, delimiter);
0460:                } else if (o instanceof  Map) {
0461:                    return new ArrayList(((Map) o).entrySet());
0462:                } else {
0463:                    if (o == null) {
0464:                        return Collections.emptyList();
0465:                    }
0466:                    return Collections.singletonList(o);
0467:                }
0468:            }
0469:
0470:            /**
0471:             * @since MMBase-1.8
0472:             */
0473:            public static Map toMap(Object o) {
0474:                if (o instanceof  Map) {
0475:                    return (Map) o;
0476:                } else if (o instanceof  org.mmbase.util.functions.Parameters) {
0477:                    return ((org.mmbase.util.functions.Parameters) o).toMap();
0478:                } else if (o instanceof  Collection) {
0479:                    Map result = new HashMap();
0480:                    Iterator i = ((Collection) o).iterator();
0481:                    while (i.hasNext()) {
0482:                        Object n = i.next();
0483:                        if (n instanceof  Map.Entry) {
0484:                            Map.Entry entry = (Map.Entry) n;
0485:                            result.put(entry.getKey(), entry.getValue());
0486:                        } else {
0487:                            result.put(n, n);
0488:                        }
0489:                    }
0490:                    return result;
0491:                } else if (o instanceof  Node) {
0492:                    return new NodeMap((Node) o);
0493:                } else {
0494:                    return Collections.singletonMap(o, o);
0495:                }
0496:            }
0497:
0498:            /**
0499:             * Transforms an object to a collection. If the object is a collection already, then nothing
0500:             * happens. If it is a Map, then the 'entry set' is returned. A string is interpreted as a
0501:             * comma-separated list of strings. Other objects are wrapped in an ArrayList with one element.
0502:             *
0503:             * @since MMBase-1.8.5
0504:             */
0505:            public static Collection toCollection(Object o, String delimiter) {
0506:                if (o instanceof  Collection) {
0507:                    return (Collection) o;
0508:                } else if (o instanceof  Map) {
0509:                    return ((Map) o).entrySet();
0510:                } else if (o instanceof  String) {
0511:                    if ("".equals(delimiter) || delimiter == null)
0512:                        delimiter = ",";
0513:                    return StringSplitter.split((String) o, delimiter);
0514:                } else if (o instanceof  Object[]) {
0515:                    return Arrays.asList((Object[]) o);
0516:                } else {
0517:                    if (o == null) {
0518:                        return Collections.emptyList();
0519:                    }
0520:                    return Collections.singletonList(o);
0521:                }
0522:            }
0523:
0524:            /**
0525:             * @since MMBase-1.8
0526:             */
0527:            public static Collection toCollection(Object o) {
0528:                return toCollection(o, ",");
0529:            }
0530:
0531:            /**
0532:             * Convert the value to a <code>Document</code> object.
0533:             * If the value is not itself a Document, the method attempts to
0534:             * attempts to convert the String value into an XML.
0535:             * A <code>null</code> value is returned as <code>null</code>.
0536:             * If the value cannot be converted, this method throws an IllegalArgumentException.
0537:             * @param o the object to be converted to an XML document
0538:             * @return  the value as a DOM Element or <code>null</code>
0539:             * @throws  IllegalArgumentException if the value could not be converted
0540:             * @since MMBase-1.6
0541:             */
0542:            static public Document toXML(Object o) {
0543:                if (o == null)
0544:                    return null;
0545:                if (!(o instanceof  Document)) {
0546:                    //do conversion from String to Document...
0547:                    // This is a laborous action, so we log it on debug.
0548:                    // It will happen often if the nodes are not cached and so on.
0549:                    String xmltext = toString(o);
0550:                    if (log.isDebugEnabled()) {
0551:                        String msg = xmltext;
0552:                        if (msg.length() > 84) {
0553:                            msg = msg.substring(0, 80) + "...";
0554:                        }
0555:                        log.debug("Object '" + msg
0556:                                + "' is not a Document, but a "
0557:                                + o.getClass().getName() + "");
0558:                    }
0559:                    return convertStringToXML(xmltext);
0560:                }
0561:                return (Document) o;
0562:            }
0563:
0564:            /**
0565:             * Convert an object to a byte array.
0566:             * @param obj The object to be converted
0567:             * @return the value as an <code>byte[]</code> (binary/blob field)
0568:             */
0569:            static public byte[] toByte(Object obj) {
0570:                if (obj == null) {
0571:                    return new byte[] {};
0572:                } else if (obj instanceof  byte[]) {
0573:                    // was allready unmapped so return the value
0574:                    return (byte[]) obj;
0575:                } else if (obj instanceof  org.apache.commons.fileupload.FileItem) {
0576:                    return ((org.apache.commons.fileupload.FileItem) obj).get();
0577:                } else if (obj instanceof  InputStream) {
0578:                    InputStream in = (InputStream) obj;
0579:                    ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
0580:                    byte[] buf = new byte[1024];
0581:                    try {
0582:                        int tot;
0583:                        do {
0584:                            tot = in.read(buf, 0, 1024);
0585:                            out.write(buf, 0, tot);
0586:                        } while (tot > 0);
0587:                    } catch (IOException ioe) {
0588:                        log.error(ioe);
0589:                    } finally {
0590:                        try {
0591:                            in.close();
0592:                        } catch (IOException ioe) {
0593:                        }
0594:                    }
0595:                    return out.toByteArray();
0596:                } else {
0597:                    return toString(obj).getBytes();
0598:                }
0599:            }
0600:
0601:            static public InputStream toInputStream(Object obj) {
0602:                if (obj instanceof  InputStream) {
0603:                    return (InputStream) obj;
0604:                } else {
0605:                    byte[] bytes = toByte(obj);
0606:                    return new ByteArrayInputStream(bytes, 0, bytes.length);
0607:                }
0608:            }
0609:
0610:            /**
0611:             * Convert an object to an Node.
0612:             * If the value is Numeric, the method
0613:             * tries to obtain the mmbase object with that number.
0614:             * A <code>Map</code> returns a virtual <code>Node</code> representing the map, (a
0615:             * {@link MapNode}).
0616:             * All remaining situations return the node with the alias <code>i.toString()</code>, which can
0617:             * be <code>null</code> if no node which such an alias.
0618:             * @param i the object to convert
0619:             * @param cloud the Cloud to use for loading a node
0620:             * @return the value as a <code>Node</code>
0621:             * @since MMBase-1.7
0622:             */
0623:            public static Node toNode(Object i, Cloud cloud) {
0624:                Node res = null;
0625:                if (i instanceof  Node) {
0626:                    res = (Node) i;
0627:                } else if (i instanceof  Number) {
0628:                    int nodenumber = ((Number) i).intValue();
0629:                    if (nodenumber != -1) {
0630:                        res = cloud.getNode(nodenumber);
0631:                    }
0632:                } else if (i instanceof  Map) {
0633:                    res = new MapNode((Map) i, cloud);
0634:                } else if (i != null && !i.equals("")) {
0635:                    res = cloud.getNode(i.toString());
0636:                }
0637:                return res;
0638:            }
0639:
0640:            /**
0641:             * Convert an object to an <code>int</code>.
0642:             * Boolean values return 0 for false, 1 for true.
0643:             * String values are parsed to a number, if possible.
0644:             * If a value is an Node, it's number field is returned.
0645:             * All remaining values return the provided default value.
0646:             * @param i the object to convert
0647:             * @param def the default value if conversion is impossible
0648:             * @return the converted value as an <code>int</code>
0649:             * @since MMBase-1.7
0650:             */
0651:            static public int toInt(Object i, int def) {
0652:                int res = def;
0653:                if (i instanceof  Node) {
0654:                    res = ((Node) i).getNumber();
0655:                } else if (i instanceof  Boolean) {
0656:                    res = ((Boolean) i).booleanValue() ? 1 : 0;
0657:                } else if (i instanceof  Date) {
0658:                    long timeValue = ((Date) i).getTime();
0659:
0660:                    if (timeValue != -1)
0661:                        timeValue /= 1000;
0662:
0663:                    if (timeValue > Integer.MAX_VALUE) {
0664:                        res = Integer.MAX_VALUE;
0665:                    } else if (timeValue < Integer.MIN_VALUE) {
0666:                        res = Integer.MIN_VALUE;
0667:                    } else {
0668:                        res = (int) timeValue;
0669:                    }
0670:                } else if (i instanceof  Number) {
0671:                    long l = ((Number) i).longValue();
0672:                    if (l > Integer.MAX_VALUE) {
0673:                        res = Integer.MAX_VALUE;
0674:                    } else if (l < Integer.MIN_VALUE) {
0675:                        res = Integer.MIN_VALUE;
0676:                    } else {
0677:                        res = (int) l;
0678:                    }
0679:                } else if (i != null) {
0680:                    try {
0681:                        res = Integer.parseInt("" + i);
0682:                    } catch (NumberFormatException e) {
0683:                        // not an integer? perhaps it is a float or double represented as String.
0684:                        try {
0685:                            res = toInt(Double.valueOf("" + i), def); // recursive to hit the check on MAX_VALUE/MIN_VALUE also here.
0686:                        } catch (NumberFormatException ex) {
0687:                            // try if the value is a string representing a boolean.
0688:                            if (i instanceof  String) {
0689:                                String s = ((String) i).toLowerCase();
0690:                                if (s.equals("true") || s.equals("yes")) {
0691:                                    res = 1;
0692:                                } else if (s.equals("false") || s.equals("no")) {
0693:                                    res = 0;
0694:                                }
0695:                            }
0696:                        }
0697:                    }
0698:                }
0699:                return res;
0700:            }
0701:
0702:            /**
0703:             * Convert an object to an <code>int</code>.
0704:             * Boolean values return 0 for false, 1 for true.
0705:             * String values are parsed to a number, if possible.
0706:             * If a value is a Node, it's number field is returned.
0707:             * All remaining values return -1.
0708:             * @param i the object to convert
0709:             * @return the converted value as an <code>int</code>
0710:             */
0711:            static public int toInt(Object i) {
0712:                return toInt(i, -1);
0713:            }
0714:
0715:            /**
0716:             * Convert an object to a <code>boolean</code>.
0717:             * If the value is numeric, this call returns <code>true</code>
0718:             * if the value is a positive, non-zero, value. In other words, values '0'
0719:             * and '-1' are considered <code>false</code>.
0720:             * If the value is a string, this call returns <code>true</code> if
0721:             * the value is "true" or "yes" (case-insensitive).
0722:             * In all other cases (including calling byte fields), <code>false</code>
0723:             * is returned.
0724:             * @param b the object to convert
0725:             * @return the converted value as a <code>boolean</code>
0726:             */
0727:            static public boolean toBoolean(Object b) {
0728:                if (b == null) {
0729:                    return false;
0730:                } else if (b instanceof  Boolean) {
0731:                    return ((Boolean) b).booleanValue();
0732:                } else if (b instanceof  Number) {
0733:                    return ((Number) b).doubleValue() > 0;
0734:                } else if (b instanceof  Node) {
0735:                    return true; // return true if a NODE is filled
0736:                } else if (b instanceof  Date) {
0737:                    return ((Date) b).getTime() != -1;
0738:                } else if (b instanceof  Document) {
0739:                    return false; // undefined
0740:                } else if (b instanceof  String) {
0741:                    // note: we don't use Boolean.valueOf() because that only captures
0742:                    // the value "true"
0743:                    String s = ((String) b).toLowerCase();
0744:                    return s.equals("true") || s.equals("yes") || s.equals("1");
0745:                } else {
0746:                    return false;
0747:                }
0748:            }
0749:
0750:            /**
0751:             * Convert an object to an Integer.
0752:             * Boolean values return 0 for false, 1 for true.
0753:             * String values are parsed to a number, if possible.
0754:             * All remaining values return -1.
0755:             * @param i the object to convert
0756:             * @return the converted value as a <code>Integer</code>
0757:             */
0758:            static public Integer toInteger(Object i) {
0759:                if (i instanceof  Integer) {
0760:                    return (Integer) i;
0761:                } else {
0762:                    return Integer.valueOf(toInt(i));
0763:                }
0764:            }
0765:
0766:            /**
0767:             * Convert an object to a <code>long</code>.
0768:             * Boolean values return 0 for false, 1 for true.
0769:             * String values are parsed to a number, if possible.
0770:             * All remaining values return the provided default value.
0771:             * @param i the object to convert
0772:             * @param def the default value if conversion is impossible
0773:             * @return the converted value as a <code>long</code>
0774:             * @since MMBase-1.7
0775:             */
0776:            static public long toLong(Object i, long def) {
0777:                long res = def;
0778:                if (i instanceof  Boolean) {
0779:                    res = ((Boolean) i).booleanValue() ? 1 : 0;
0780:                } else if (i instanceof  Number) {
0781:                    res = ((Number) i).longValue();
0782:                } else if (i instanceof  Date) {
0783:                    res = ((Date) i).getTime();
0784:                    if (res != -1)
0785:                        res /= 1000;
0786:                } else if (i instanceof  Node) {
0787:                    res = ((Node) i).getNumber();
0788:                } else if (i != null) {
0789:                    if (i instanceof  String) {
0790:                        String s = ((String) i).toLowerCase();
0791:                        if (s.equals("true") || s.equals("yes")) {
0792:                            return 1;
0793:                        } else if (s.equals("false") || s.equals("no")) {
0794:                            return 0;
0795:                        }
0796:                    }
0797:                    try {
0798:                        res = Long.parseLong("" + i);
0799:                    } catch (NumberFormatException e) {
0800:                        // not an integer? perhaps it is a float or double represented as String.
0801:                        try {
0802:                            res = Double.valueOf("" + i).longValue();
0803:                        } catch (NumberFormatException ex) {
0804:                            // give up, fall back to default.
0805:                        }
0806:                    }
0807:                }
0808:                return res;
0809:            }
0810:
0811:            /**
0812:             * Convert an object to a <code>long</code>.
0813:             * Boolean values return 0 for false, 1 for true.
0814:             * String values are parsed to a number, if possible.
0815:             * All remaining values return -1.
0816:             * @param i the object to convert
0817:             * @return the converted value as a <code>long</code>
0818:             * @since MMBase-1.7
0819:             */
0820:            static public long toLong(Object i) {
0821:                return toLong(i, -1);
0822:            }
0823:
0824:            /**
0825:             * Convert an object to an <code>float</code>.
0826:             * Boolean values return 0 for false, 1 for true.
0827:             * String values are parsed to a number, if possible.
0828:             * All remaining values return the default value.
0829:             * @param i the object to convert
0830:             * @param def the default value if conversion is impossible
0831:             * @return the converted value as a <code>float</code>
0832:             */
0833:            static public float toFloat(Object i, float def) {
0834:                float res = def;
0835:                if (i instanceof  Boolean) {
0836:                    res = ((Boolean) i).booleanValue() ? 1 : 0;
0837:                } else if (i instanceof  Number) {
0838:                    res = ((Number) i).floatValue();
0839:                } else if (i instanceof  Date) {
0840:                    res = ((Date) i).getTime();
0841:                    if (res != -1)
0842:                        res = res / 1000;
0843:                } else if (i instanceof  Node) {
0844:                    res = ((Node) i).getNumber();
0845:                } else if (i != null) {
0846:                    if (i instanceof  String) {
0847:                        String s = ((String) i).toLowerCase();
0848:                        if (s.equals("true") || s.equals("yes")) {
0849:                            res = 1;
0850:                        } else if (s.equals("false") || s.equals("no")) {
0851:                            res = 0;
0852:                        }
0853:                    }
0854:                    try {
0855:                        res = Float.parseFloat("" + i);
0856:                    } catch (NumberFormatException e) {
0857:                        // use default
0858:                    }
0859:                }
0860:                return res;
0861:            }
0862:
0863:            /**
0864:             * Convert an object to an <code>float</code>.
0865:             * Boolean values return 0 for false, 1 for true.
0866:             * String values are parsed to a number, if possible.
0867:             * All remaining values return -1.
0868:             * @param i the object to convert
0869:             * @return the converted value as a <code>float</code>
0870:             */
0871:            static public float toFloat(Object i) {
0872:                return toFloat(i, -1);
0873:            }
0874:
0875:            /**
0876:             * Convert an object to an <code>double</code>.
0877:             * Boolean values return 0 for false, 1 for true.
0878:             * String values are parsed to a number, if possible.
0879:             * All remaining values return the default value.
0880:             * @param i the object to convert
0881:             * @param def the default value if conversion is impossible
0882:             * @return the converted value as a <code>double</code>
0883:             */
0884:            static public double toDouble(Object i, double def) {
0885:                double res = def;
0886:                if (i instanceof  Boolean) {
0887:                    res = ((Boolean) i).booleanValue() ? 1 : 0;
0888:                } else if (i instanceof  Number) {
0889:                    res = ((Number) i).doubleValue();
0890:                } else if (i instanceof  Date) {
0891:                    res = ((Date) i).getTime();
0892:                    if (res != -1)
0893:                        res = res / 1000;
0894:                } else if (i instanceof  Node) {
0895:                    res = ((Node) i).getNumber();
0896:                } else if (i != null) {
0897:                    try {
0898:                        res = Double.parseDouble("" + i);
0899:                    } catch (NumberFormatException e) {
0900:                        //              try if the value is a string representing a boolean.
0901:                        if (i instanceof  String) {
0902:                            String s = ((String) i).toLowerCase();
0903:                            if (s.equals("true") || s.equals("yes")) {
0904:                                res = 1;
0905:                            } else if (s.equals("false") || s.equals("no")) {
0906:                                res = 0;
0907:                            }
0908:                        }
0909:                    }
0910:                }
0911:                return res;
0912:            }
0913:
0914:            /**
0915:             * Convert an object to an <code>double</code>.
0916:             * Boolean values return 0 for false, 1 for true.
0917:             * String values are parsed to a number, if possible.
0918:             * All remaining values return -1.
0919:             * @param i the object to convert
0920:             * @return the converted value as a <code>double</code>
0921:             */
0922:            static public double toDouble(Object i) {
0923:                return toDouble(i, -1);
0924:            }
0925:
0926:            /**
0927:             * Convert an object to a <code>Date</code>.
0928:             * String values are parsed to a date, if possible.
0929:             * Numeric values are assumed to represent number of seconds since 1970.
0930:             * All remaining values return 1969-12-31 23:59 GMT.
0931:             * @param d the object to convert
0932:             * @return the converted value as a <code>Date</code>, never <code>null</code>
0933:             * @since MMBase-1.7
0934:             */
0935:            static public Date toDate(Object d) {
0936:                if (d == null)
0937:                    return new Date(-1);
0938:                Date date = null;
0939:
0940:                if (d instanceof  Date) {
0941:                    date = (Date) d;
0942:                } else {
0943:                    try {
0944:                        long dateInSeconds = -1;
0945:                        if (d instanceof  Number) {
0946:                            dateInSeconds = ((Number) d).longValue();
0947:                        } else if (d instanceof  Document) {
0948:                            // impossible
0949:                            dateInSeconds = -1;
0950:                        } else if (d instanceof  Boolean) {
0951:                            dateInSeconds = -1;
0952:                        } else if (d instanceof  Collection) {
0953:                            // impossible
0954:                            dateInSeconds = -1;
0955:                        } else if (d instanceof  Node) {
0956:                            // impossible
0957:                            dateInSeconds = -1;
0958:                        } else if (d != null) {
0959:                            d = toString(d);
0960:                            if (d.equals("")) {
0961:                                return new Date(-1);
0962:                            }
0963:                            dateInSeconds = Long.parseLong((String) d);
0964:                        } else {
0965:                            dateInSeconds = -1;
0966:                        }
0967:                        if (dateInSeconds == -1) {
0968:                            date = new Date(-1);
0969:                        } else if (dateInSeconds > Long.MAX_VALUE / 1000) {
0970:                            date = new Date(Long.MAX_VALUE); // or should this throw an exception?
0971:                        } else if (dateInSeconds < Long.MIN_VALUE / 1000) {
0972:                            date = new Date(Long.MIN_VALUE); // or should this throw an exception?
0973:                        } else {
0974:                            date = new Date(dateInSeconds * 1000);
0975:                        }
0976:                    } catch (NumberFormatException e) {
0977:                        try {
0978:                            date = DynamicDate.getInstance((String) d);
0979:                        } catch (org.mmbase.util.dateparser.ParseException pe) {
0980:                            log.error("Parser exception in " + d, pe);
0981:                            return new Date(-1);
0982:                        } catch (Error per) {
0983:                            throw new Error("Parser error in " + d, per);
0984:                        }
0985:                    }
0986:                }
0987:                return date;
0988:            }
0989:
0990:            static DocumentBuilder DOCUMENTBUILDER;
0991:            static {
0992:                try {
0993:                    DocumentBuilderFactory dfactory = DocumentBuilderFactory
0994:                            .newInstance();
0995:                    dfactory.setValidating(false);
0996:                    dfactory.setNamespaceAware(true);
0997:                    DOCUMENTBUILDER = dfactory.newDocumentBuilder();
0998:                    DOCUMENTBUILDER.setEntityResolver(new XMLEntityResolver(
0999:                            false));
1000:                } catch (ParserConfigurationException pce) {
1001:                    log.error("[sax parser]: " + pce.toString(), pce);
1002:                }
1003:            }
1004:
1005:            /**
1006:             * Convert a String value to a Document
1007:             * @param value The current value (can be null)
1008:             * @return  the value as a DOM Element or <code>null</code>
1009:             * @throws  IllegalArgumentException if the value could not be converted
1010:             */
1011:            static private Document convertStringToXML(String value) {
1012:                if (value == null) {
1013:                    return null;
1014:                }
1015:                if (log.isTraceEnabled()) {
1016:                    log.trace("using xml string:\n" + value);
1017:                }
1018:                try {
1019:                    Document doc;
1020:                    final XMLErrorHandler errorHandler = new XMLErrorHandler(
1021:                            false, org.mmbase.util.XMLErrorHandler.NEVER);
1022:                    synchronized (DOCUMENTBUILDER) {
1023:                        // dont log errors, and try to process as much as possible...
1024:                        DOCUMENTBUILDER.setErrorHandler(errorHandler);
1025:                        // ByteArrayInputStream?
1026:                        // Yes, in contradiction to what one would think, XML are bytes, rather then characters.
1027:                        doc = DOCUMENTBUILDER
1028:                                .parse(new java.io.ByteArrayInputStream(value
1029:                                        .getBytes("UTF-8")));
1030:                    }
1031:                    if (log.isTraceEnabled()) {
1032:                        log.trace("parsed: "
1033:                                + XMLWriter.write(doc, false, true));
1034:                    }
1035:                    if (!errorHandler.foundNothing()) {
1036:                        throw new IllegalArgumentException("xml invalid:\n"
1037:                                + errorHandler.getMessageBuffer()
1038:                                + "for xml:\n" + value);
1039:                    }
1040:                    return doc;
1041:                } catch (org.xml.sax.SAXException se) {
1042:                    if (log.isDebugEnabled()) {
1043:                        log.debug("[sax] not well formed xml: " + se.toString()
1044:                                + "(" + se.getMessage() + ")\n"
1045:                                + Logging.stackTrace(se));
1046:                    }
1047:                    return convertStringToXML("<p>"
1048:                            + Encode.encode("ESCAPE_XML", value) + "</p>"); // Should _always_ be sax-compliant.
1049:                } catch (java.io.IOException ioe) {
1050:                    String msg = "[io] not well formed xml: " + ioe.toString()
1051:                            + "\n" + Logging.stackTrace(ioe);
1052:                    throw new IllegalArgumentException(msg);
1053:                }
1054:            }
1055:
1056:            /*
1057:             * Wraps a List with an 'Escaper'.
1058:             * @since MMBase-1.8
1059:             */
1060:            public static class ListWrapper extends AbstractList {
1061:                private final List list;
1062:                private final CharTransformer escaper;
1063:
1064:                ListWrapper(List l, CharTransformer e) {
1065:                    list = l;
1066:                    escaper = e;
1067:                }
1068:
1069:                public Object get(int index) {
1070:                    return Casting.wrap(list.get(index), escaper);
1071:                }
1072:
1073:                public int size() {
1074:                    return list.size();
1075:                }
1076:
1077:                public Object set(int index, Object value) {
1078:                    return list.set(index, value);
1079:                }
1080:
1081:                public void add(int index, Object value) {
1082:                    list.add(index, value);
1083:                }
1084:
1085:                public Object remove(int index) {
1086:                    return list.remove(index);
1087:                }
1088:
1089:                public boolean isEmpty() {
1090:                    return list.isEmpty();
1091:                }
1092:
1093:                public boolean contains(Object o) {
1094:                    return list.contains(o);
1095:                }
1096:
1097:                public Object[] toArray() {
1098:                    return list.toArray();
1099:                }
1100:
1101:                public Object[] toArray(Object[] a) {
1102:                    return list.toArray(a);
1103:                }
1104:
1105:                public Iterator iterator() {
1106:                    return list.iterator();
1107:                }
1108:
1109:                public ListIterator listIterator() {
1110:                    return list.listIterator();
1111:                }
1112:
1113:                public String toString() {
1114:                    StringBuilder buf = new StringBuilder();
1115:                    Iterator i = list.iterator();
1116:                    boolean hasNext = i.hasNext();
1117:                    while (hasNext) {
1118:                        Casting.toStringBuilder(buf, i.next());
1119:                        hasNext = i.hasNext();
1120:                        if (hasNext) {
1121:                            buf.append(',');
1122:                        }
1123:                    }
1124:                    return buf.toString();
1125:                }
1126:
1127:                public List getList() {
1128:                    return list;
1129:                }
1130:            }
1131:
1132:            /**
1133:             * @since MMBase-1.9
1134:             */
1135:            public static class NodeListWrapper extends
1136:                    org.mmbase.bridge.util.CollectionNodeList {
1137:                private final CharTransformer escaper;
1138:
1139:                NodeListWrapper(org.mmbase.bridge.NodeList list,
1140:                        CharTransformer e) {
1141:                    super (list);
1142:                    escaper = e;
1143:                }
1144:
1145:                public Node get(int index) {
1146:                    return (Node) Casting.wrap(super .get(index), escaper);
1147:                }
1148:
1149:                public String toString() {
1150:                    StringBuilder buf = new StringBuilder();
1151:                    Iterator<Node> i = iterator();
1152:                    boolean hasNext = i.hasNext();
1153:                    while (hasNext) {
1154:                        Casting.toStringBuilder(buf, i.next());
1155:                        hasNext = i.hasNext();
1156:                        if (hasNext) {
1157:                            buf.append(',');
1158:                        }
1159:                    }
1160:                    return buf.toString();
1161:                }
1162:
1163:            }
1164:
1165:            /**
1166:             * Wraps a String with an 'Escaper'.
1167:             * @since MMBase-1.8
1168:             */
1169:            public static class StringWrapper implements  CharSequence {
1170:                private final CharTransformer escaper;
1171:                private final CharSequence string;
1172:                private String escaped = null;
1173:
1174:                StringWrapper(CharSequence s, CharTransformer e) {
1175:                    escaper = e;
1176:                    string = s;
1177:
1178:                }
1179:
1180:                public char charAt(int index) {
1181:                    toString();
1182:                    return escaped.charAt(index);
1183:                }
1184:
1185:                public int length() {
1186:                    toString();
1187:                    return escaped.length();
1188:                }
1189:
1190:                public CharSequence subSequence(int start, int end) {
1191:                    toString();
1192:                    return escaped.subSequence(start, end);
1193:                }
1194:
1195:                public String toString() {
1196:                    if (escaped == null)
1197:                        escaped = escape(escaper, string);
1198:                    return escaped;
1199:                }
1200:
1201:                public CharSequence getString() {
1202:                    return string;
1203:                }
1204:            }
1205:
1206:            /**
1207:             * Clases implementint this will not be wrapped by {@link #wrap}, even if the e.g. are CharSequence.
1208:             * @since MMBase-1.9
1209:             */
1210:            public static interface Unwrappable {
1211:            }
1212:
1213:            /**
1214:             * @since MMBase-1.9
1215:             */
1216:            public static boolean equals(Object o1, Object o2) {
1217:                if (o1 == null)
1218:                    return o2 == null;
1219:
1220:                if (o1 instanceof  org.w3c.dom.Node) {
1221:                    return (o2 instanceof  org.w3c.dom.Node && ((org.w3c.dom.Node) o1)
1222:                            .isEqualNode((org.w3c.dom.Node) o2));
1223:                } else {
1224:                    return o1.equals(o2);
1225:                }
1226:            }
1227:
1228:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.