View Javadoc
1   /**
2    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3    *
4    * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
5    * Portions Copyright 2013-2019 Philip Helger + contributors
6    *
7    * The contents of this file are subject to the terms of either the GNU
8    * General Public License Version 2 only ("GPL") or the Common Development
9    * and Distribution License("CDDL") (collectively, the "License").  You
10   * may not use this file except in compliance with the License.  You can
11   * obtain a copy of the License at
12   * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
13   * or packager/legal/LICENSE.txt.  See the License for the specific
14   * language governing permissions and limitations under the License.
15   *
16   * When distributing the software, include this License Header Notice in each
17   * file and include the License file at packager/legal/LICENSE.txt.
18   *
19   * GPL Classpath Exception:
20   * Oracle designates this particular file as subject to the "Classpath"
21   * exception as provided by Oracle in the GPL Version 2 section of the License
22   * file that accompanied this code.
23   *
24   * Modifications:
25   * If applicable, add the following below the License Header, with the fields
26   * enclosed by brackets [] replaced by your own identifying information:
27   * "Portions Copyright [year] [name of copyright owner]"
28   *
29   * Contributor(s):
30   * If you wish your version of this file to be governed by only the CDDL or
31   * only the GPL Version 2, indicate your decision by adding "[Contributor]
32   * elects to include this software in this distribution under the [CDDL or GPL
33   * Version 2] license."  If you don't indicate a single choice of license, a
34   * recipient has the option to distribute your version of this file under
35   * either the CDDL, the GPL Version 2 or to extend the choice of license to
36   * its licensees as provided above.  However, if you add GPL Version 2 code
37   * and therefore, elected the GPL Version 2 license, then the option applies
38   * only if the new code is made subject to such option by the copyright
39   * holder.
40   */
41  package com.helger.jcodemodel;
42  
43  import java.util.Collection;
44  import java.util.Collections;
45  import java.util.Locale;
46  import java.util.Map;
47  import java.util.TreeMap;
48  
49  import javax.annotation.Nonnull;
50  import javax.annotation.Nullable;
51  
52  /**
53   * A generated Java class/interface/enum/annotation<br>
54   * This class models a declaration, and since a declaration can be always used
55   * as a reference, it inherits {@link AbstractJClass}.
56   *
57   * @author Philip Helger
58   * @param <CLASSTYPE>
59   *        Implementation type
60   */
61  public abstract class AbstractJClassContainerctJClassContainer">AbstractJClassContainer <CLASSTYPE extends AbstractJClassContainer <CLASSTYPE>> extends
62                                                AbstractJClass implements
63                                                IJClassContainer <CLASSTYPE>
64  {
65    /**
66     * If this is a package-member class, this is {@link JPackage}. If this is a
67     * nested class, this is {@link AbstractJClassContainer}. If this is an
68     * anonymous class, this constructor shouldn't be used.
69     */
70    private final IJClassContainer <?> m_aOuter;
71  
72    /**
73     * Default value is class or interface or annotationTypeDeclaration or enum
74     */
75    private final EClassType m_eClassType;
76  
77    /**
78     * Name of this class. <code>null</code> if anonymous.
79     */
80    private final String m_sName;
81  
82    /**
83     * Nested classes as a map from name to JDefinedClass. The name is all
84     * capitalized in a case sensitive file system (
85     * {@link JCodeModel#isFileSystemCaseSensitive()}) to avoid conflicts. Lazily
86     * created to save footprint.
87     */
88    protected Map <String, CLASSTYPE> m_aClasses;
89  
90    /**
91     * JClass constructor
92     *
93     * @param aOwner
94     *        Owning code model
95     * @param aOuter
96     *        Optional outer class container
97     * @param eClassType
98     *        Class type to use
99     * @param sName
100    *        Name of this class
101    */
102   protected AbstractJClassContainer (@Nonnull final JCodeModel aOwner,
103                                      @Nullable final IJClassContainer <?> aOuter,
104                                      @Nonnull final EClassType eClassType,
105                                      @Nullable final String sName)
106   {
107     super (aOwner);
108     m_aOuter = aOuter;
109     m_eClassType = eClassType;
110     m_sName = sName;
111   }
112 
113   @Nullable
114   public final IJClassContainer <?> getOuter ()
115   {
116     return m_aOuter;
117   }
118 
119   @Override
120   @Nullable
121   public final AbstractJClass outer ()
122   {
123     if (m_aOuter != null && m_aOuter.isClass ())
124       return (AbstractJClass) m_aOuter;
125     return null;
126   }
127 
128   @Nonnull
129   public final EClassType getClassType ()
130   {
131     return m_eClassType;
132   }
133 
134   @Override
135   public final boolean isInterface ()
136   {
137     return m_eClassType == EClassType.INTERFACE;
138   }
139 
140   /**
141    * This method indicates if the interface is an annotationTypeDeclaration
142    *
143    * @return <code>true</code> if this an annotation type declaration
144    */
145   public final boolean isAnnotationTypeDeclaration ()
146   {
147     return m_eClassType == EClassType.ANNOTATION_TYPE_DECL;
148   }
149 
150   /**
151    * Class name accessor. <br>
152    * For example, for <code>java.util.List</code>, this method returns
153    * <code>"List"</code>"
154    *
155    * @return Name of this class
156    */
157   @Override
158   @Nullable
159   public String name ()
160   {
161     return m_sName;
162   }
163 
164   /**
165    * Gets the fully qualified name of this class.
166    */
167   @Override
168   @Nullable
169   public String fullName ()
170   {
171     if (getOuter () instanceof AbstractJClassContainer <?>)
172       return ((AbstractJClassContainer <?>) getOuter ()).fullName () + '.' + name ();
173 
174     final JPackage aPkg = _package ();
175     if (aPkg.isUnnamed ())
176       return name ();
177     return aPkg.name () + '.' + name ();
178   }
179 
180   /**
181    * @return <code>true</code> if this is an anonymous class. Note: this applies
182    *         only to classes.
183    */
184   public final boolean isAnonymous ()
185   {
186     return m_sName == null;
187   }
188 
189   public final boolean isClass ()
190   {
191     return true;
192   }
193 
194   public final boolean isPackage ()
195   {
196     return false;
197   }
198 
199   @SuppressWarnings ("unchecked")
200   @Nonnull
201   protected final CLASSTYPE thisAsT ()
202   {
203     return (CLASSTYPE) this;
204   }
205 
206   @Nonnull
207   public final IJClassContainer <?> parentContainer ()
208   {
209     return m_aOuter;
210   }
211 
212   public final JPackage getPackage ()
213   {
214     return parentContainer ().getPackage ();
215   }
216 
217   @Nonnull
218   protected abstract CLASSTYPE createInnerClass (final int nMods,
219                                                  @Nonnull final EClassType eClassType,
220                                                  @Nonnull final String sName);
221 
222   @Nonnull
223   public final CLASSTYPE _class (final int nMods,
224                                  @Nonnull final String sName,
225                                  @Nonnull final EClassType eClassType) throws JClassAlreadyExistsException
226   {
227     String sRealName;
228     if (JCodeModel.isFileSystemCaseSensitive ())
229       sRealName = sName.toUpperCase (Locale.US);
230     else
231       sRealName = sName;
232 
233     // Existing class?
234     if (m_aClasses != null)
235     {
236       final CLASSTYPE aExistingClass = m_aClasses.get (sRealName);
237       if (aExistingClass != null)
238         throw new JClassAlreadyExistsException (aExistingClass);
239     }
240     else
241       m_aClasses = new TreeMap <> ();
242 
243     // Create and add inner class
244     final CLASSTYPE c = createInnerClass (nMods, eClassType, sName);
245     m_aClasses.put (sRealName, c);
246     return c;
247   }
248 
249   /**
250    * Returns an iterator that walks the nested classes defined in this class.
251    * Don't modify the returned collection!
252    */
253   @Nonnull
254   public final Collection <CLASSTYPE> classes ()
255   {
256     if (m_aClasses == null)
257       return Collections.emptyList ();
258     return m_aClasses.values ();
259   }
260 }