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.util;
027:
028: import com.sun.codemodel.internal.ClassType;
029: import com.sun.codemodel.internal.JClassAlreadyExistsException;
030: import com.sun.codemodel.internal.JClassContainer;
031: import com.sun.codemodel.internal.JDefinedClass;
032: import com.sun.codemodel.internal.JJavaName;
033: import com.sun.codemodel.internal.JMod;
034: import com.sun.tools.internal.xjc.ErrorReceiver;
035:
036: import org.xml.sax.Locator;
037: import org.xml.sax.SAXParseException;
038:
039: /**
040: * Create new {@link JDefinedClass} and report class collision errors,
041: * if necessary.
042: *
043: * This is just a helper class that simplifies the class name collision
044: * detection. This object maintains no state, so it is OK to use
045: * multiple instances of this.
046: *
047: * @author
048: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
049: */
050: public final class CodeModelClassFactory {
051:
052: /** errors are reported to this object. */
053: private ErrorReceiver errorReceiver;
054:
055: /** unique id generator. */
056: private int ticketMaster = 0;
057:
058: public CodeModelClassFactory(ErrorReceiver _errorReceiver) {
059: this .errorReceiver = _errorReceiver;
060: }
061:
062: public JDefinedClass createClass(JClassContainer parent,
063: String name, Locator source) {
064: return createClass(parent, JMod.PUBLIC, name, source);
065: }
066:
067: public JDefinedClass createClass(JClassContainer parent, int mod,
068: String name, Locator source) {
069: return createClass(parent, mod, name, source, ClassType.CLASS);
070: }
071:
072: public JDefinedClass createInterface(JClassContainer parent,
073: String name, Locator source) {
074: return createInterface(parent, JMod.PUBLIC, name, source);
075: }
076:
077: public JDefinedClass createInterface(JClassContainer parent,
078: int mod, String name, Locator source) {
079: return createClass(parent, mod, name, source,
080: ClassType.INTERFACE);
081: }
082:
083: public JDefinedClass createClass(JClassContainer parent,
084: String name, Locator source, ClassType kind) {
085: return createClass(parent, JMod.PUBLIC, name, source, kind);
086: }
087:
088: public JDefinedClass createClass(JClassContainer parent, int mod,
089: String name, Locator source, ClassType kind) {
090:
091: if (!JJavaName.isJavaIdentifier(name)) {
092: // report the error
093: errorReceiver.error(new SAXParseException(Messages.format(
094: Messages.ERR_INVALID_CLASSNAME, name), source));
095: return createDummyClass(parent);
096: }
097:
098: try {
099: if (parent.isClass() && kind == ClassType.CLASS)
100: mod |= JMod.STATIC;
101:
102: JDefinedClass r = parent._class(mod, name, kind);
103: // use the metadata field to store the source location,
104: // so that we can report class name collision errors.
105: r.metadata = source;
106:
107: return r;
108: } catch (JClassAlreadyExistsException e) {
109: // class collision.
110: JDefinedClass cls = e.getExistingClass();
111:
112: // report the error
113: errorReceiver.error(new SAXParseException(Messages.format(
114: Messages.ERR_CLASSNAME_COLLISION, cls.fullName()),
115: (Locator) cls.metadata));
116: errorReceiver.error(new SAXParseException(Messages.format(
117: Messages.ERR_CLASSNAME_COLLISION_SOURCE, name),
118: source));
119:
120: if (!name.equals(cls.name())) {
121: // on Windows, FooBar and Foobar causes name collision
122: errorReceiver
123: .error(new SAXParseException(
124: Messages
125: .format(
126: Messages.ERR_CASE_SENSITIVITY_COLLISION,
127: name, cls.name()), null));
128: }
129:
130: return createDummyClass(parent);
131: }
132: }
133:
134: /**
135: * Create a dummy class to recover from an error.
136: *
137: * We won't generate the code, so the client will never see this class
138: * getting generated.
139: */
140: private JDefinedClass createDummyClass(JClassContainer parent) {
141: try {
142: return parent._class("$$$garbage$$$" + (ticketMaster++));
143: } catch (JClassAlreadyExistsException ee) {
144: return ee.getExistingClass();
145: }
146: }
147: }
|