Source Code Cross Referenced for SimpleTypeBuilder.java in  » 6.0-JDK-Modules-com.sun » tools » com » sun » tools » internal » xjc » reader » xmlschema » 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 » 6.0 JDK Modules com.sun » tools » com.sun.tools.internal.xjc.reader.xmlschema 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004:         *
005:         * This code is free software; you can redistribute it and/or modify it
006:         * under the terms of the GNU General Public License version 2 only, as
007:         * published by the Free Software Foundation.  Sun designates this
008:         * particular file as subject to the "Classpath" exception as provided
009:         * by Sun in the LICENSE file that accompanied this code.
010:         *
011:         * This code is distributed in the hope that it will be useful, but WITHOUT
012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014:         * version 2 for more details (a copy is included in the LICENSE file that
015:         * accompanied this code).
016:         *
017:         * You should have received a copy of the GNU General Public License version
018:         * 2 along with this work; if not, write to the Free Software Foundation,
019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020:         *
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022:         * CA 95054 USA or visit www.sun.com if you need additional information or
023:         * have any questions.
024:         */
025:
026:        package com.sun.tools.internal.xjc.reader.xmlschema;
027:
028:        import java.io.StringWriter;
029:        import java.math.BigInteger;
030:        import java.text.ParseException;
031:        import java.util.ArrayList;
032:        import java.util.Collections;
033:        import java.util.HashMap;
034:        import java.util.HashSet;
035:        import java.util.List;
036:        import java.util.Map;
037:        import java.util.Set;
038:        import java.util.Stack;
039:
040:        import javax.activation.MimeTypeParseException;
041:        import javax.xml.namespace.QName;
042:
043:        import com.sun.codemodel.internal.JJavaName;
044:        import com.sun.codemodel.internal.util.JavadocEscapeWriter;
045:        import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
046:        import com.sun.tools.internal.xjc.model.CClassInfo;
047:        import com.sun.tools.internal.xjc.model.CClassInfoParent;
048:        import com.sun.tools.internal.xjc.model.CEnumConstant;
049:        import com.sun.tools.internal.xjc.model.CEnumLeafInfo;
050:        import com.sun.tools.internal.xjc.model.CNonElement;
051:        import com.sun.tools.internal.xjc.model.Model;
052:        import com.sun.tools.internal.xjc.model.TypeUse;
053:        import com.sun.tools.internal.xjc.model.TypeUseFactory;
054:        import com.sun.tools.internal.xjc.reader.Ring;
055:        import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;
056:        import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIEnum;
057:        import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIEnumMember;
058:        import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
059:        import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
060:        import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.EnumMemberMode;
061:        import com.sun.tools.internal.xjc.util.MimeTypeRange;
062:        import com.sun.xml.internal.bind.DatatypeConverterImpl;
063:        import com.sun.xml.internal.bind.v2.WellKnownNamespace;
064:        import static com.sun.xml.internal.bind.v2.WellKnownNamespace.XML_MIME_URI;
065:        import com.sun.xml.internal.bind.v2.runtime.SwaRefAdapter;
066:        import com.sun.xml.internal.xsom.XSAttributeDecl;
067:        import com.sun.xml.internal.xsom.XSComplexType;
068:        import com.sun.xml.internal.xsom.XSComponent;
069:        import com.sun.xml.internal.xsom.XSElementDecl;
070:        import com.sun.xml.internal.xsom.XSFacet;
071:        import com.sun.xml.internal.xsom.XSListSimpleType;
072:        import com.sun.xml.internal.xsom.XSRestrictionSimpleType;
073:        import com.sun.xml.internal.xsom.XSSimpleType;
074:        import com.sun.xml.internal.xsom.XSUnionSimpleType;
075:        import com.sun.xml.internal.xsom.XSVariety;
076:        import com.sun.xml.internal.xsom.impl.util.SchemaWriter;
077:        import com.sun.xml.internal.xsom.visitor.XSSimpleTypeFunction;
078:        import com.sun.xml.internal.xsom.visitor.XSVisitor;
079:
080:        import org.xml.sax.Locator;
081:
082:        /**
083:         * Builds {@link TypeUse} from simple types.
084:         *
085:         * <p>
086:         * This code consists of two main portions. The {@link #compose(XSSimpleType)} method
087:         * and {@link #composer} forms an outer cycle, which gradually ascends the type
088:         * inheritance chain until it finds the suitable binding. When it does this
089:         * {@link #initiatingType} is set to the type which started binding, so that we can refer
090:         * to the actual constraint facets and such that are applicable on the type.
091:         *
092:         * <p>
093:         * For each intermediate type in the chain, the {@link #find(XSSimpleType)} method
094:         * is used to find the binding on that type, sine the outer loop is doing the ascending,
095:         * this method only sees if the current type has some binding available.
096:         *
097:         * <p>
098:         * There is at least one ugly code that you need to aware of
099:         * when you are modifying the code. See the documentation
100:         * about <a href="package.html#stref_cust">
101:         * "simple type customization at the point of reference."</a>
102:         *
103:         *
104:         * @author
105:         *     Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
106:         */
107:        public final class SimpleTypeBuilder extends BindingComponent {
108:
109:            protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
110:
111:            private final Model model = Ring.get(Model.class);
112:
113:            /**
114:             * The component that is refering to the simple type
115:             * which we are building. This is ugly but necessary
116:             * to support the customization of simple types at
117:             * its point of reference. See my comment at the header
118:             * of this class for details.
119:             *
120:             * UGLY: Implemented as a Stack of XSComponent to fix a bug
121:             */
122:            public final Stack<XSComponent> refererStack = new Stack<XSComponent>();
123:
124:            /**
125:             * The type that was originally passed to this {@link SimpleTypeBuilder#build(XSSimpleType)}.
126:             * Never null.
127:             */
128:            private XSSimpleType initiatingType;
129:
130:            /** {@link TypeUse}s for the built-in types. Read-only. */
131:            public static final Map<String, TypeUse> builtinConversions = new HashMap<String, TypeUse>();
132:
133:            /**
134:             * Entry point from outside. Builds a BGM type expression
135:             * from a simple type schema component.
136:             *
137:             * @param type
138:             *      the simple type to be bound.
139:             */
140:            public TypeUse build(XSSimpleType type) {
141:                XSSimpleType oldi = initiatingType;
142:                this .initiatingType = type;
143:
144:                TypeUse e = checkRefererCustomization(type);
145:                if (e == null)
146:                    e = compose(type);
147:
148:                initiatingType = oldi;
149:
150:                return e;
151:            }
152:
153:            /**
154:             * A version of the {@link #build(XSSimpleType)} method
155:             * used to bind the definition of a class generated from
156:             * the given simple type.
157:             */
158:            public TypeUse buildDef(XSSimpleType type) {
159:                XSSimpleType oldi = initiatingType;
160:                this .initiatingType = type;
161:
162:                TypeUse e = type.apply(composer);
163:
164:                initiatingType = oldi;
165:
166:                return e;
167:            }
168:
169:            /**
170:             * Returns a javaType customization specified to the referer, if present.
171:             * @return can be null.
172:             */
173:            private BIConversion getRefererCustomization() {
174:                BindInfo info = builder.getBindInfo(getReferer());
175:                BIProperty prop = info.get(BIProperty.class);
176:                if (prop == null)
177:                    return null;
178:                return prop.getConv();
179:            }
180:
181:            public XSComponent getReferer() {
182:                return refererStack.peek();
183:            }
184:
185:            /**
186:             * Checks if the referer has a conversion customization or not.
187:             * If it does, use it to bind this simple type. Otherwise
188:             * return null;
189:             */
190:            private TypeUse checkRefererCustomization(XSSimpleType type) {
191:
192:                // assertion check. referer must be set properly
193:                // before the build method is called.
194:                // since the handling of the simple type point-of-reference
195:                // customization is very error prone, it deserves a strict
196:                // assertion check.
197:                // UGLY CODE WARNING
198:                XSComponent top = getReferer();
199:
200:                if (top instanceof  XSElementDecl) {
201:                    // if the parent is element type, its content type must be us.
202:                    XSElementDecl eref = (XSElementDecl) top;
203:                    assert eref.getType() == type;
204:
205:                    // for elements, you can't use <property>,
206:                    // so we allow javaType to appear directly.
207:                    BindInfo info = builder.getBindInfo(top);
208:                    BIConversion conv = info.get(BIConversion.class);
209:                    if (conv != null) {
210:                        conv.markAsAcknowledged();
211:                        // the conversion is given.
212:                        return conv.getTypeUse(type);
213:                    }
214:                    detectJavaTypeCustomization();
215:                } else if (top instanceof  XSAttributeDecl) {
216:                    XSAttributeDecl aref = (XSAttributeDecl) top;
217:                    assert aref.getType() == type;
218:                    detectJavaTypeCustomization();
219:                } else if (top instanceof  XSComplexType) {
220:                    XSComplexType tref = (XSComplexType) top;
221:                    assert tref.getBaseType() == type
222:                            || tref.getContentType() == type;
223:                    detectJavaTypeCustomization();
224:                } else if (top == type) {
225:                    // this means the simple type is built by itself and
226:                    // not because it's referenced by something.
227:                } else
228:                    // unexpected referer type.
229:                    assert false;
230:
231:                // now we are certain that the referer is OK.
232:                // see if it has a conversion customization.
233:                BIConversion conv = getRefererCustomization();
234:                if (conv != null) {
235:                    conv.markAsAcknowledged();
236:                    // the conversion is given.
237:                    return conv.getTypeUse(type);
238:                } else
239:                    // not found
240:                    return null;
241:            }
242:
243:            /**
244:             * Detect "javaType" customizations placed directly on simple types, rather
245:             * than being enclosed by "property" and "baseType" customizations (see
246:             * sec 6.8.1 of the spec).
247:             *
248:             * Report an error if any exist.
249:             */
250:            private void detectJavaTypeCustomization() {
251:                BindInfo info = builder.getBindInfo(getReferer());
252:                BIConversion conv = info.get(BIConversion.class);
253:
254:                if (conv != null) {
255:                    // ack this conversion to prevent further error messages
256:                    conv.markAsAcknowledged();
257:
258:                    // report the error
259:                    getErrorReporter()
260:                            .error(
261:                                    conv.getLocation(),
262:                                    Messages.ERR_UNNESTED_JAVATYPE_CUSTOMIZATION_ON_SIMPLETYPE);
263:                }
264:            }
265:
266:            /**
267:             * Recursively decend the type inheritance chain to find a binding.
268:             */
269:            TypeUse compose(XSSimpleType t) {
270:                TypeUse e = find(t);
271:                if (e != null)
272:                    return e;
273:                return t.apply(composer);
274:            }
275:
276:            public final XSSimpleTypeFunction<TypeUse> composer = new XSSimpleTypeFunction<TypeUse>() {
277:
278:                public TypeUse listSimpleType(XSListSimpleType type) {
279:                    // bind item type individually and then compose them into a list
280:                    // facets on the list shouldn't be taken account when binding item types,
281:                    // so weed to call build(), not compose().
282:                    XSSimpleType itemType = type.getItemType();
283:                    refererStack.push(itemType);
284:                    TypeUse tu = TypeUseFactory.makeCollection(build(type
285:                            .getItemType()));
286:                    refererStack.pop();
287:                    return tu;
288:                }
289:
290:                public TypeUse unionSimpleType(XSUnionSimpleType type) {
291:                    boolean isCollection = false;
292:                    for (int i = 0; i < type.getMemberSize(); i++)
293:                        if (type.getMember(i).getVariety() == XSVariety.LIST) {
294:                            isCollection = true;
295:                            break;
296:                        }
297:
298:                    TypeUse r = CBuiltinLeafInfo.STRING;
299:                    if (isCollection)
300:                        r = TypeUseFactory.makeCollection(r);
301:                    return r;
302:                }
303:
304:                public TypeUse restrictionSimpleType(
305:                        XSRestrictionSimpleType type) {
306:                    // just process the base type.
307:                    return compose(type.getSimpleBaseType());
308:                }
309:            };
310:
311:            /**
312:             * Checks if there's any binding available on the given type.
313:             *
314:             * @return
315:             *      null if not (which causes the {@link #compose(XSSimpleType)} method
316:             *      to do ascending.
317:             */
318:            private TypeUse find(XSSimpleType type) {
319:                TypeUse r;
320:                boolean noAutoEnum = false;
321:
322:                // check for user specified conversion
323:                BindInfo info = builder.getBindInfo(type);
324:                BIConversion conv = info.get(BIConversion.class);
325:
326:                if (conv != null) {
327:                    // a conversion was found
328:                    conv.markAsAcknowledged();
329:                    return conv.getTypeUse(type);
330:                }
331:
332:                // look for enum customization, which is noather user specified conversion
333:                BIEnum en = info.get(BIEnum.class);
334:                if (en != null) {
335:                    en.markAsAcknowledged();
336:
337:                    if (!en.isMapped()) {
338:                        noAutoEnum = true;
339:                    } else {
340:                        // if an enum customization is specified, make sure
341:                        // the type is OK
342:                        if (!canBeMappedToTypeSafeEnum(type)) {
343:                            getErrorReporter().error(en.getLocation(),
344:                                    Messages.ERR_CANNOT_BE_TYPE_SAFE_ENUM);
345:                            getErrorReporter()
346:                                    .error(
347:                                            type.getLocator(),
348:                                            Messages.ERR_CANNOT_BE_TYPE_SAFE_ENUM_LOCATION);
349:                            // recover by ignoring this customization
350:                            return null;
351:                        }
352:                        // list and union cannot be mapped to a type-safe enum,
353:                        // so in this stage we can safely cast it to XSRestrictionSimpleType
354:                        return bindToTypeSafeEnum(
355:                                (XSRestrictionSimpleType) type, en.className,
356:                                en.javadoc, en.members, getEnumMemberMode()
357:                                        .getModeWithEnum(), en.getLocation());
358:                    }
359:                }
360:
361:                // if the type is built in, look for the default binding
362:                if (type.getTargetNamespace().equals(
363:                        WellKnownNamespace.XML_SCHEMA)) {
364:                    String name = type.getName();
365:                    if (name != null) {
366:                        r = lookupBuiltin(name);
367:                        if (r != null)
368:                            return r;
369:                    }
370:                }
371:
372:                // also check for swaRef
373:                if (type.getTargetNamespace()
374:                        .equals(WellKnownNamespace.SWA_URI)) {
375:                    String name = type.getName();
376:                    if (name != null && name.equals("swaRef"))
377:                        return CBuiltinLeafInfo.STRING.makeAdapted(
378:                                SwaRefAdapter.class, false);
379:                }
380:
381:                // see if this type should be mapped to a type-safe enumeration by default.
382:                // if so, built a EnumXDucer from it and return it.
383:                if (type.isRestriction() && !noAutoEnum) {
384:                    XSRestrictionSimpleType rst = type.asRestriction();
385:                    if (shouldBeMappedToTypeSafeEnumByDefault(rst)) {
386:                        r = bindToTypeSafeEnum(rst, null, null, Collections
387:                                .<String, BIEnumMember> emptyMap(),
388:                                getEnumMemberMode(), null);
389:                        if (r != null)
390:                            return r;
391:                    }
392:                }
393:
394:                return getClassSelector()._bindToClass(type, false);
395:            }
396:
397:            /**
398:             * Returns true if a type-safe enum should be created from
399:             * the given simple type by default without an explicit &lt;jaxb:enum> customization.
400:             */
401:            private boolean shouldBeMappedToTypeSafeEnumByDefault(
402:                    XSRestrictionSimpleType type) {
403:
404:                // if not, there will be a problem wrt the class name of this type safe enum type.
405:                if (type.isLocal())
406:                    return false;
407:
408:                // if redefined, we should map the new definition, not the old one.
409:                if (type.getRedefinedBy() != null)
410:                    return false;
411:
412:                List<XSFacet> facets = type
413:                        .getDeclaredFacets(XSFacet.FACET_ENUMERATION);
414:                if (facets.isEmpty()
415:                        || facets.size() > builder.getGlobalBinding()
416:                                .getDefaultEnumMemberSizeCap())
417:                    // if the type itself doesn't have the enumeration facet,
418:                    // it won't be mapped to a type-safe enum.
419:                    //
420:                    // if there are too many facets, it's not very useful
421:                    return false;
422:
423:                if (!canBeMappedToTypeSafeEnum(type))
424:                    // we simply can't map this to an enumeration
425:                    return false;
426:
427:                // check for collisions among constant names. if a collision will happen,
428:                // don't try to bind it to an enum.
429:
430:                // return true only when this type is derived from one of the "enum base type".
431:                for (XSSimpleType t = type; t != null; t = t
432:                        .getSimpleBaseType())
433:                    if (t.isGlobal()
434:                            && builder.getGlobalBinding()
435:                                    .canBeMappedToTypeSafeEnum(t))
436:                        return true;
437:
438:                return false;
439:            }
440:
441:            private static final Set<String> builtinTypeSafeEnumCapableTypes;
442:
443:            static {
444:                Set<String> s = new HashSet<String>();
445:
446:                // see a bullet of 6.5.1 of the spec.
447:                String[] typeNames = new String[] { "string", "boolean",
448:                        "float", "decimal", "double", "anyURI" };
449:
450:                for (String type : typeNames)
451:                    s.add(type);
452:
453:                builtinTypeSafeEnumCapableTypes = Collections
454:                        .unmodifiableSet(s);
455:            }
456:
457:            /**
458:             * Returns true if the given simple type can be mapped to a
459:             * type-safe enum class.
460:             *
461:             * <p>
462:             * JAXB spec places a restrictrion as to what type can be
463:             * mapped to a type-safe enum. This method enforces this
464:             * constraint.
465:             */
466:            public static boolean canBeMappedToTypeSafeEnum(XSSimpleType type) {
467:                do {
468:                    if (WellKnownNamespace.XML_SCHEMA.equals(type
469:                            .getTargetNamespace())) {
470:                        // type must be derived from one of these types
471:                        String localName = type.getName();
472:                        if (localName != null) {
473:                            if (localName.equals("anySimpleType"))
474:                                return false; // catch all case
475:                            if (localName.equals("ID")
476:                                    || localName.equals("IDREF"))
477:                                return false; // not ID/IDREF
478:
479:                            // other allowed list
480:                            if (builtinTypeSafeEnumCapableTypes
481:                                    .contains(localName))
482:                                return true;
483:                        }
484:                    }
485:
486:                    type = type.getSimpleBaseType();
487:                } while (type != null);
488:
489:                return false;
490:            }
491:
492:            /**
493:             * Builds a type-safe enum conversion from a simple type
494:             * with enumeration facets.
495:             *
496:             * @param className
497:             *      The class name of the type-safe enum. Or null to
498:             *      create a default name.
499:             * @param javadoc
500:             *      Additional javadoc that will be added at the beginning of the
501:             *      class, or null if none is necessary.
502:             * @param members
503:             *      A map from enumeration values (as String) to BIEnumMember objects.
504:             *      if some of the value names need to be overrided.
505:             *      Cannot be null, but the map may not contain entries
506:             *      for all enumeration values.
507:             * @param loc
508:             *      The source location where the above customizations are
509:             *      specified, or null if none is available.
510:             */
511:            private TypeUse bindToTypeSafeEnum(XSRestrictionSimpleType type,
512:                    String className, String javadoc,
513:                    Map<String, BIEnumMember> members, EnumMemberMode mode,
514:                    Locator loc) {
515:
516:                if (loc == null) // use the location of the simple type as the default
517:                    loc = type.getLocator();
518:
519:                if (className == null) {
520:                    // infer the class name. For this to be possible,
521:                    // the simple type must be a global one.
522:                    if (!type.isGlobal()) {
523:                        getErrorReporter().error(loc,
524:                                Messages.ERR_NO_ENUM_NAME_AVAILABLE);
525:                        // recover by returning a meaningless conversion
526:                        return CBuiltinLeafInfo.STRING;
527:                    }
528:                    className = type.getName();
529:                }
530:                // we apply name conversion in any case
531:                className = builder.getNameConverter().toClassName(className);
532:
533:                {// compute Javadoc
534:                    StringWriter out = new StringWriter();
535:                    SchemaWriter sw = new SchemaWriter(new JavadocEscapeWriter(
536:                            out));
537:                    type.visit((XSVisitor) sw);
538:
539:                    if (javadoc != null)
540:                        javadoc += "\n\n";
541:                    else
542:                        javadoc = "";
543:
544:                    javadoc += Messages.format(Messages.JAVADOC_HEADING, type
545:                            .getName())
546:                            + "\n<p>\n<pre>\n" + out.getBuffer() + "</pre>";
547:
548:                }
549:
550:                // build base type
551:                refererStack.push(type.getSimpleBaseType());
552:                TypeUse use = build(type.getSimpleBaseType());
553:                refererStack.pop();
554:
555:                if (use.isCollection())
556:                    return null; // can't bind a list to enum constant
557:
558:                CNonElement baseDt = (CNonElement) use.getInfo(); // for now just ignore that case
559:
560:                if (baseDt instanceof  CClassInfo)
561:                    return null; // can't bind to an enum if the base is a class, since we don't have the value constrctor
562:
563:                // if the member names collide, re-generate numbered constant names.
564:                XSFacet[] errorRef = new XSFacet[1];
565:                List<CEnumConstant> memberList = buildCEnumConstants(type,
566:                        false, members, errorRef);
567:                if (memberList == null
568:                        || checkMemberNameCollision(memberList) != null) {
569:                    switch (mode) {
570:                    case SKIP:
571:                        // abort
572:                        return null;
573:                    case ERROR:
574:                        // error
575:                        if (memberList == null) {
576:                            getErrorReporter().error(errorRef[0].getLocator(),
577:                                    Messages.ERR_CANNOT_GENERATE_ENUM_NAME,
578:                                    errorRef[0].getValue());
579:                        } else {
580:                            CEnumConstant[] collision = checkMemberNameCollision(memberList);
581:                            getErrorReporter().error(collision[0].getLocator(),
582:                                    Messages.ERR_ENUM_MEMBER_NAME_COLLISION,
583:                                    collision[0].getName());
584:                            getErrorReporter()
585:                                    .error(
586:                                            collision[1].getLocator(),
587:                                            Messages.ERR_ENUM_MEMBER_NAME_COLLISION_RELATED);
588:                        }
589:                        return null; // recover from error
590:                    case GENERATE:
591:                        // generate
592:                        memberList = buildCEnumConstants(type, true, members,
593:                                null);
594:                        break;
595:                    }
596:                }
597:
598:                QName typeName = null;
599:                if (type.isGlobal())
600:                    typeName = new QName(type.getTargetNamespace(), type
601:                            .getName());
602:
603:                // use the name of the simple type as the name of the class.
604:                CClassInfoParent scope;
605:                if (type.isGlobal())
606:                    scope = new CClassInfoParent.Package(getClassSelector()
607:                            .getPackage(type.getTargetNamespace()));
608:                else
609:                    scope = getClassSelector().getClassScope();
610:                CEnumLeafInfo xducer = new CEnumLeafInfo(model, typeName,
611:                        scope, className, baseDt, memberList, type, builder
612:                                .getBindInfo(type).toCustomizationList(), loc);
613:                xducer.javadoc = javadoc;
614:
615:                BIConversion conv = new BIConversion.Static(type.getLocator(),
616:                        xducer);
617:                conv.markAsAcknowledged();
618:
619:                // attach this new conversion object to this simple type
620:                // so that successive look up will use the same object.
621:                builder.getOrCreateBindInfo(type).addDecl(conv);
622:
623:                return conv.getTypeUse(type);
624:            }
625:
626:            /**
627:             *
628:             * @param errorRef
629:             *      if constant names couldn't be generated, return a reference to that enum facet.
630:             * @return
631:             *      null if unable to generate names for some of the constants.
632:             */
633:            private List<CEnumConstant> buildCEnumConstants(
634:                    XSRestrictionSimpleType type,
635:                    boolean needsToGenerateMemberName,
636:                    Map<String, BIEnumMember> members, XSFacet[] errorRef) {
637:                List<CEnumConstant> memberList = new ArrayList<CEnumConstant>();
638:                int idx = 1;
639:                for (XSFacet facet : type
640:                        .getDeclaredFacets(XSFacet.FACET_ENUMERATION)) {
641:                    String name = null;
642:                    String mdoc = null;
643:
644:                    if (needsToGenerateMemberName) {
645:                        // generate names for all member names.
646:                        // this will even override names specified by the user. that's crazy.
647:                        name = "VALUE_" + (idx++);
648:                    } else {
649:                        String facetValue = facet.getValue().value;
650:                        BIEnumMember mem = members.get(facetValue);
651:                        if (mem == null)
652:                            // look at the one attached to the facet object
653:                            mem = builder.getBindInfo(facet).get(
654:                                    BIEnumMember.class);
655:
656:                        if (mem != null) {
657:                            name = mem.name;
658:                            mdoc = mem.javadoc;
659:                        }
660:
661:                        if (name == null) {
662:                            StringBuilder sb = new StringBuilder();
663:                            for (int i = 0; i < facetValue.length(); i++) {
664:                                char ch = facetValue.charAt(i);
665:                                if (Character.isJavaIdentifierPart(ch))
666:                                    sb.append(ch);
667:                                else
668:                                    sb.append('_');
669:                            }
670:                            name = model.getNameConverter().toConstantName(
671:                                    sb.toString());
672:                        }
673:                    }
674:
675:                    if (!JJavaName.isJavaIdentifier(name)) {
676:                        if (errorRef != null)
677:                            errorRef[0] = facet;
678:                        return null; // unable to generate a name
679:                    }
680:
681:                    memberList.add(new CEnumConstant(name, mdoc, facet
682:                            .getValue().value, facet.getLocator()));
683:                }
684:                return memberList;
685:            }
686:
687:            /**
688:             * Returns non-null if {@link CEnumConstant}s have name collisions among them.
689:             *
690:             * @return
691:             *      if there's a collision, return two {@link CEnumConstant}s that collided.
692:             *      otherwise return null.
693:             */
694:            private CEnumConstant[] checkMemberNameCollision(
695:                    List<CEnumConstant> memberList) {
696:                Map<String, CEnumConstant> names = new HashMap<String, CEnumConstant>();
697:                for (CEnumConstant c : memberList) {
698:                    CEnumConstant old = names.put(c.getName(), c);
699:                    if (old != null)
700:                        // collision detected
701:                        return new CEnumConstant[] { old, c };
702:                }
703:                return null;
704:            }
705:
706:            private EnumMemberMode getEnumMemberMode() {
707:                return builder.getGlobalBinding().getEnumMemberMode();
708:            }
709:
710:            private TypeUse lookupBuiltin(String typeLocalName) {
711:                if (typeLocalName.equals("integer")
712:                        || typeLocalName.equals("long")) {
713:                    /*
714:                        attempt an optimization so that we can
715:                        improve the binding for types like this:
716:
717:                        <simpleType>
718:                          <restriciton baseType="integer">
719:                            <maxInclusive value="100" />
720:                          </
721:                        </
722:
723:                        ... to int, not BigInteger.
724:                     */
725:
726:                    BigInteger xe = readFacet(XSFacet.FACET_MAXEXCLUSIVE, -1);
727:                    BigInteger xi = readFacet(XSFacet.FACET_MAXINCLUSIVE, 0);
728:                    BigInteger max = min(xe, xi); // most restrictive one takes precedence
729:
730:                    if (max != null) {
731:                        BigInteger ne = readFacet(XSFacet.FACET_MINEXCLUSIVE,
732:                                +1);
733:                        BigInteger ni = readFacet(XSFacet.FACET_MININCLUSIVE, 0);
734:                        BigInteger min = max(ne, ni);
735:
736:                        if (min != null) {
737:                            if (min.compareTo(INT_MIN) >= 0
738:                                    && max.compareTo(INT_MAX) <= 0)
739:                                typeLocalName = "int";
740:                            else if (min.compareTo(LONG_MIN) >= 0
741:                                    && max.compareTo(LONG_MAX) <= 0)
742:                                typeLocalName = "long";
743:                        }
744:                    }
745:                } else if (typeLocalName.equals("boolean")
746:                        && isRestrictedTo0And1()) {
747:                    // this is seen in the SOAP schema and too common to ignore
748:                    return CBuiltinLeafInfo.BOOLEAN_ZERO_OR_ONE;
749:                } else if (typeLocalName.equals("base64Binary")) {
750:                    return lookupBinaryTypeBinding();
751:                } else if (typeLocalName.equals("anySimpleType")) {
752:                    if (getReferer() instanceof  XSAttributeDecl
753:                            || getReferer() instanceof  XSSimpleType)
754:                        return CBuiltinLeafInfo.STRING;
755:                    else
756:                        return CBuiltinLeafInfo.ANYTYPE;
757:                }
758:                return builtinConversions.get(typeLocalName);
759:            }
760:
761:            /**
762:             * Decides the way xs:base64Binary binds.
763:             *
764:             * This method checks the expected media type.
765:             */
766:            private TypeUse lookupBinaryTypeBinding() {
767:                XSComponent referer = getReferer();
768:                String emt = referer.getForeignAttribute(XML_MIME_URI,
769:                        "expectedContentTypes");
770:                if (emt != null) {
771:                    try {
772:                        // see http://www.xml.com/lpt/a/2004/07/21/dive.html
773:                        List<MimeTypeRange> types = MimeTypeRange
774:                                .parseRanges(emt);
775:                        MimeTypeRange mt = MimeTypeRange.merge(types);
776:
777:                        // see spec table I-1 in appendix I section 2.1.1 for bindings
778:                        if (mt.majorType.equals("image"))
779:                            return CBuiltinLeafInfo.IMAGE.makeMimeTyped(mt
780:                                    .toMimeType());
781:
782:                        if ((mt.majorType.equals("application") || mt.majorType
783:                                .equals("text"))
784:                                && isXml(mt.subType))
785:                            return CBuiltinLeafInfo.XML_SOURCE.makeMimeTyped(mt
786:                                    .toMimeType());
787:
788:                        if ((mt.majorType.equals("text") && (mt.subType
789:                                .equals("plain")))) {
790:                            return CBuiltinLeafInfo.STRING.makeMimeTyped(mt
791:                                    .toMimeType());
792:                        }
793:
794:                        return CBuiltinLeafInfo.DATA_HANDLER.makeMimeTyped(mt
795:                                .toMimeType());
796:                    } catch (ParseException e) {
797:                        getErrorReporter()
798:                                .error(
799:                                        referer.getLocator(),
800:                                        Messages
801:                                                .format(
802:                                                        Messages.ERR_ILLEGAL_EXPECTED_MIME_TYPE,
803:                                                        emt, e.getMessage()));
804:                        // recover by using the default
805:                    } catch (MimeTypeParseException e) {
806:                        getErrorReporter()
807:                                .error(
808:                                        referer.getLocator(),
809:                                        Messages
810:                                                .format(
811:                                                        Messages.ERR_ILLEGAL_EXPECTED_MIME_TYPE,
812:                                                        emt, e.getMessage()));
813:                    }
814:                }
815:                // default
816:                return CBuiltinLeafInfo.BASE64_BYTE_ARRAY;
817:            }
818:
819:            /**
820:             * Returns true if the specified sub-type is an XML type.
821:             */
822:            private boolean isXml(String subType) {
823:                return subType.equals("xml") || subType.endsWith("+xml");
824:            }
825:
826:            /**
827:             * Returns true if the {@link #initiatingType} is restricted
828:             * to '0' and '1'. This logic is not complete, but it at least
829:             * finds the such definition in SOAP @mustUnderstand.
830:             */
831:            private boolean isRestrictedTo0And1() {
832:                XSFacet pattern = initiatingType
833:                        .getFacet(XSFacet.FACET_PATTERN);
834:                if (pattern != null) {
835:                    String v = pattern.getValue().value;
836:                    if (v.equals("0|1") || v.equals("1|0") || v.equals("\\d"))
837:                        return true;
838:                }
839:                XSFacet enumf = initiatingType
840:                        .getFacet(XSFacet.FACET_ENUMERATION);
841:                if (enumf != null) {
842:                    String v = enumf.getValue().value;
843:                    if (v.equals("0") || v.equals("1"))
844:                        return true;
845:                }
846:                return false;
847:            }
848:
849:            private BigInteger readFacet(String facetName, int offset) {
850:                XSFacet me = initiatingType.getFacet(facetName);
851:                if (me == null)
852:                    return null;
853:                BigInteger bi = DatatypeConverterImpl._parseInteger(me
854:                        .getValue().value);
855:                if (offset != 0)
856:                    bi = bi.add(BigInteger.valueOf(offset));
857:                return bi;
858:            }
859:
860:            private BigInteger min(BigInteger a, BigInteger b) {
861:                if (a == null)
862:                    return b;
863:                if (b == null)
864:                    return a;
865:                return a.min(b);
866:            }
867:
868:            private BigInteger max(BigInteger a, BigInteger b) {
869:                if (a == null)
870:                    return b;
871:                if (b == null)
872:                    return a;
873:                return a.max(b);
874:            }
875:
876:            private static final BigInteger LONG_MIN = BigInteger
877:                    .valueOf(Long.MIN_VALUE);
878:            private static final BigInteger LONG_MAX = BigInteger
879:                    .valueOf(Long.MAX_VALUE);
880:            private static final BigInteger INT_MIN = BigInteger
881:                    .valueOf(Integer.MIN_VALUE);
882:            private static final BigInteger INT_MAX = BigInteger
883:                    .valueOf(Integer.MAX_VALUE);
884:
885:            static {
886:                // list of datatypes which have built-in conversions.
887:                // note that although xs:token and xs:normalizedString are not
888:                // specified in the spec, they need to be here because they
889:                // have different whitespace normalization semantics.
890:                Map<String, TypeUse> m = builtinConversions;
891:
892:                // TODO: this is so dumb
893:                m.put("string", CBuiltinLeafInfo.STRING);
894:                m.put("anyURI", CBuiltinLeafInfo.STRING);
895:                m.put("boolean", CBuiltinLeafInfo.BOOLEAN);
896:                // we'll also look at the expected media type, so don't just add this to the map
897:                // m.put("base64Binary",   CBuiltinLeafInfo.BASE64_BYTE_ARRAY);
898:                m.put("hexBinary", CBuiltinLeafInfo.HEXBIN_BYTE_ARRAY);
899:                m.put("float", CBuiltinLeafInfo.FLOAT);
900:                m.put("decimal", CBuiltinLeafInfo.BIG_DECIMAL);
901:                m.put("integer", CBuiltinLeafInfo.BIG_INTEGER);
902:                m.put("long", CBuiltinLeafInfo.LONG);
903:                m.put("unsignedInt", CBuiltinLeafInfo.LONG);
904:                m.put("int", CBuiltinLeafInfo.INT);
905:                m.put("unsignedShort", CBuiltinLeafInfo.INT);
906:                m.put("short", CBuiltinLeafInfo.SHORT);
907:                m.put("unsignedByte", CBuiltinLeafInfo.SHORT);
908:                m.put("byte", CBuiltinLeafInfo.BYTE);
909:                m.put("double", CBuiltinLeafInfo.DOUBLE);
910:                m.put("QName", CBuiltinLeafInfo.QNAME);
911:                m.put("NOTATION", CBuiltinLeafInfo.QNAME);
912:                m.put("dateTime", CBuiltinLeafInfo.CALENDAR);
913:                m.put("date", CBuiltinLeafInfo.CALENDAR);
914:                m.put("time", CBuiltinLeafInfo.CALENDAR);
915:                m.put("gYearMonth", CBuiltinLeafInfo.CALENDAR);
916:                m.put("gYear", CBuiltinLeafInfo.CALENDAR);
917:                m.put("gMonthDay", CBuiltinLeafInfo.CALENDAR);
918:                m.put("gDay", CBuiltinLeafInfo.CALENDAR);
919:                m.put("gMonth", CBuiltinLeafInfo.CALENDAR);
920:                m.put("duration", CBuiltinLeafInfo.DURATION);
921:                m.put("token", CBuiltinLeafInfo.TOKEN);
922:                m.put("normalizedString", CBuiltinLeafInfo.NORMALIZED_STRING);
923:                m.put("ID", CBuiltinLeafInfo.ID);
924:                m.put("IDREF", CBuiltinLeafInfo.IDREF);
925:                // TODO: handling dateTime, time, and date type
926:                //        String[] names = {
927:                //            "date", "dateTime", "time", "hexBinary" };
928:            }
929:        }
www__.___ja_v_a__2__s.___c___o___m | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.