Skip to content

Commit

Permalink
Added JResourceDir; #74
Browse files Browse the repository at this point in the history
  • Loading branch information
phax committed Jan 14, 2020
1 parent 287e186 commit 1873afe
Show file tree
Hide file tree
Showing 19 changed files with 1,839 additions and 126 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ A site with the links to the [API docs](http://phax.github.io/jcodemodel/) etc.

# News and noteworthy

* v3.3.1 - work in progress
* Added special top-level construct `JResourceDir` to represent pure resource directories ([issue #74](https://github.com/phax/jcodemodel/issues/74) from @guiguilechat)
* v3.3.0 - 2019-11-24
* Added check for package names so that no invalid package names can be created ([issue #70](https://github.com/phax/jcodemodel/issues/70) from @guiguilechat)
* Added check to avoid creating classes existing in the "java.lang" package ([issue #71](https://github.com/phax/jcodemodel/issues/71) from @guiguilechat)
Expand Down
171 changes: 117 additions & 54 deletions src/main/java/com/helger/jcodemodel/JCodeModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.annotation.concurrent.NotThreadSafe;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
Expand Down Expand Up @@ -144,7 +145,8 @@ public static boolean isFileSystemCaseSensitive ()

/**
* Conversion from primitive type {@link Class} (such as {@link Integer#TYPE})
* to its boxed type (such as <tt>Integer.class</tt>). It's an unmodifiable map.
* to its boxed type (such as <tt>Integer.class</tt>). It's an unmodifiable
* map.
*/
public static final Map <Class <?>, Class <?>> primitiveToBox;

Expand Down Expand Up @@ -179,6 +181,9 @@ public static boolean isFileSystemCaseSensitive ()
/** The packages that this JCodeWriter contains. */
private final Map <String, JPackage> m_aPackages = new HashMap <> ();

/** The resource directories that this JCodeWriter contains. */
private final Map <String, JResourceDir> m_aResourceDirs = new HashMap <> ();

/** All JReferencedClasses are pooled here. */
private final Map <Class <?>, JReferencedClass> m_aRefClasses = new HashMap <> ();

Expand Down Expand Up @@ -218,14 +223,19 @@ public JCodeModel ()
*
* @param sName
* Name of the package. Use "" to indicate the root package.
* @return Newly generated package
* @return Newly generated package. Never <code>null</code>.
* @see #rootPackage()
*/
@Nonnull
public JPackage _package (@Nonnull final String sName)
{
return m_aPackages.computeIfAbsent (sName, k -> new JPackage (k, this));
}

/**
* @return The root package. Never <code>null</code>. This is a shortcut for
* <code>_package ("")</code>.
*/
@Nonnull
public JPackage rootPackage ()
{
Expand All @@ -251,6 +261,55 @@ public List <JPackage> getAllPackages ()
return new ArrayList <> (m_aPackages.values ());
}

/**
* Add a {@link Resource} directory to the list of resource directories to be
* generated
*
* @param sName
* Name of the resource directory. Use "" to indicate the root
* directory.
* @return Newly generated resource directory. Never <code>null</code>.
* @see #rootResourceDir()
* @since 3.3.1
*/
@Nonnull
public JResourceDir resourceDir (@Nonnull final String sName)
{
return m_aResourceDirs.computeIfAbsent (sName, k -> new JResourceDir (k, this));
}

/**
* @return The root resource directory. Never <code>null</code>. This is a
* shortcut for <code>resourceDir ("")</code>.
* @since 3.3.1
*/
@Nonnull
public JResourceDir rootResourceDir ()
{
return resourceDir ("");
}

/**
* @return an iterator that walks the packages defined using this code writer.
* @since 3.3.1
*/
@Nonnull
public Iterator <JResourceDir> resourceDirs ()
{
return m_aResourceDirs.values ().iterator ();
}

/**
* @return a list with all packages. The list is mutable. Never
* <code>null</code>.
* @since 3.3.1
*/
@Nonnull
public List <JResourceDir> getAllResourceDirs ()
{
return new ArrayList <> (m_aResourceDirs.values ());
}

/**
* Creates a new generated class.
*
Expand Down Expand Up @@ -333,8 +392,8 @@ public JDefinedClass _class (@Nonnull final String sFullyQualifiedClassName,
* Creates a dummy, unknown {@link JDirectClass} that represents a given name.
* <br>
* This method is useful when the code generation needs to include the
* user-specified class that may or may not exist, and only thing known about it
* is a class name.
* user-specified class that may or may not exist, and only thing known about
* it is a class name.
*
* @param sName
* The fully qualified name of the class. When using type parameters
Expand All @@ -351,8 +410,8 @@ public JDirectClass directClass (@Nonnull final String sName)
* Creates a dummy, unknown {@link JDirectClass} that represents a given name.
* <br>
* This method is useful when the code generation needs to include the
* user-specified class that may or may not exist, and only thing known about it
* is a class name.
* user-specified class that may or may not exist, and only thing known about
* it is a class name.
*
* @param eClassType
* Class type to use.
Expand All @@ -375,18 +434,18 @@ public JDirectClass directClass (@Nonnull final EClassType eClassType, @Nonnull
* class that should never leak into actually written code.
* <p>
* Error-types represents holes or place-holders that can't be filled.
* References to error-classes can be used in hidden class-models. Such classes
* should never be actually written but can be somehow used during code
* generation. Use {@code JCodeModel#buildsErrorTypeRefs} method to test if your
* generated Java-sources contains references to error-types.
* References to error-classes can be used in hidden class-models. Such
* classes should never be actually written but can be somehow used during
* code generation. Use {@code JCodeModel#buildsErrorTypeRefs} method to test
* if your generated Java-sources contains references to error-types.
* <p>
* You should probably always check generated code with
* {@code JCodeModel#buildsErrorTypeRefs} method if you use any error-types.
* <p>
* Most of error-types methods throws {@code JErrorClassUsedException} unchecked
* exceptions. Be careful and use {@link AbstractJType#isError()
* AbstractJType#isError} method to check for error-types before actually using
* it's methods.
* Most of error-types methods throws {@code JErrorClassUsedException}
* unchecked exceptions. Be careful and use {@link AbstractJType#isError()
* AbstractJType#isError} method to check for error-types before actually
* using it's methods.
*
* @param sMessage
* some free form text message to identify source of error
Expand All @@ -408,18 +467,18 @@ public JErrorClass errorClass (@Nonnull final String sMessage)
* class that should never leak into actually written code.
* <p>
* Error-types represents holes or place-holders that can't be filled.
* References to error-classes can be used in hidden class-models. Such classes
* should never be actually written but can be somehow used during code
* generation. Use {@code JCodeModel#buildsErrorTypeRefs} method to test if your
* generated Java-sources contains references to error-types.
* References to error-classes can be used in hidden class-models. Such
* classes should never be actually written but can be somehow used during
* code generation. Use {@code JCodeModel#buildsErrorTypeRefs} method to test
* if your generated Java-sources contains references to error-types.
* <p>
* You should probably always check generated code with
* {@code JCodeModel#buildsErrorTypeRefs} method if you use any error-types.
* <p>
* Most of error-types methods throws {@code JErrorClassUsedException} unchecked
* exceptions. Be careful and use {@link AbstractJType#isError()
* AbstractJType#isError} method to check for error-types before actually using
* it's methods.
* Most of error-types methods throws {@code JErrorClassUsedException}
* unchecked exceptions. Be careful and use {@link AbstractJType#isError()
* AbstractJType#isError} method to check for error-types before actually
* using it's methods.
*
* @param sName
* name of missing class if it is known
Expand Down Expand Up @@ -495,8 +554,8 @@ public JAnonymousClass anonymousClass (@Nonnull final Class <?> aBaseClass)
}

/**
* @return The default charset used for building. <code>null</code> means system
* default.
* @return The default charset used for building. <code>null</code> means
* system default.
* @deprecated In favor of the new {@link JCMWriter} class offering more
* configuration flexibility.
*/
Expand Down Expand Up @@ -676,16 +735,18 @@ public void build (@Nonnull final AbstractCodeWriter aSource,
}

/**
* @return the number of files to be generated if {@link #build} is invoked now.
* @return the number of files to be generated if {@link #build} is invoked
* now.
*/
@Nonnegative
public int countArtifacts ()
{
int r = 0;
final JPackage [] pkgs = m_aPackages.values ().toArray (new JPackage [m_aPackages.size ()]);
// avoid concurrent modification exception
for (final JPackage pkg : pkgs)
r += pkg.countArtifacts ();
for (final JPackage aItem : new ArrayList <> (m_aPackages.values ()))
r += aItem.countArtifacts ();
for (final JResourceDir aItem : new ArrayList <> (m_aResourceDirs.values ()))
r += aItem.countArtifacts ();
return r;
}

Expand Down Expand Up @@ -726,20 +787,21 @@ public AbstractJClass ref (@Nonnull final Class <?> aClazz)
}

/**
* Obtains a reference to a processable class from its TypeElement description.
* Obtains a reference to a processable class from its TypeElement
* description.
* <p>
* Annotation processors can get access of {@link TypeElement} objects during
* annotation processing. These TypeElement objects can be used with jcodemodel
* as a references to classes.
* annotation processing. These TypeElement objects can be used with
* jcodemodel as a references to classes.
* <p>
* This method result-class definition can never include references to
* "error"-types. Error-types araise during annotation processing when something
* is not fully defined.
* "error"-types. Error-types araise during annotation processing when
* something is not fully defined.
* <p>
* You can post-pond annotation processing for later stages of annotation
* processor hoping that all error-types will become defined on some annotation
* processing stage at last. You can catch {@link ErrorTypeFound} exception to
* achieve this.
* processor hoping that all error-types will become defined on some
* annotation processing stage at last. You can catch {@link ErrorTypeFound}
* exception to achieve this.
*
* @param aElement
* Processable class to reference
Expand All @@ -762,20 +824,21 @@ public JDefinedClass ref (@Nonnull final TypeElement aElement,
}

/**
* Obtains a reference to a processable class from its TypeElement description.
* Obtains a reference to a processable class from its TypeElement
* description.
* <p>
* Annotation processors can get access of TypeElement objects during annotation
* processing. These TypeElement objects can be used with jcodemodel as a
* references to classes.
* Annotation processors can get access of TypeElement objects during
* annotation processing. These TypeElement objects can be used with
* jcodemodel as a references to classes.
* <p>
* This method result-class definition can include references to "error"-types.
* Error-types araise during annotation processing when something is not fully
* defined.
* This method result-class definition can include references to
* "error"-types. Error-types araise during annotation processing when
* something is not fully defined.
* <p>
* Sometimes direct treatment of error-types is required. You can use
* {@link AbstractJType#isError()} and {@link JCodeModel#buildsErrorTypeRefs()}
* methods to handle error-types and to prevent error-types to leak into
* generated code.
* {@link AbstractJType#isError()} and
* {@link JCodeModel#buildsErrorTypeRefs()} methods to handle error-types and
* to prevent error-types to leak into generated code.
*
* @param aElement
* Processable class to reference
Expand All @@ -802,8 +865,8 @@ public JDefinedClass refWithErrorTypes (@Nonnull final TypeElement aElement,
*
* @param aClass
* Class to be referenced
* @return Might be a <code>JReferencedClass</code> or a {@link JArrayClass} or
* a {@link JPrimitiveType}
* @return Might be a <code>JReferencedClass</code> or a {@link JArrayClass}
* or a {@link JPrimitiveType}
* @see #ref(Class)
*/
@Nonnull
Expand All @@ -815,11 +878,11 @@ public AbstractJType _ref (@Nonnull final Class <?> aClass)
}

/**
* Obtains a reference to an existing class from its fully-qualified class name.
* <br>
* Obtains a reference to an existing class from its fully-qualified class
* name. <br>
* First, this method attempts to load the class of the given name. If that
* fails, we assume that the class is derived straight from {@link Object}, and
* return a {@link AbstractJClass}.
* fails, we assume that the class is derived straight from {@link Object},
* and return a {@link AbstractJClass}.
*
* @param sFullyQualifiedClassName
* FQCN
Expand Down Expand Up @@ -968,8 +1031,8 @@ AbstractJClass parseTypeName ()
}

/**
* Parses additional left-associative suffixes, like type arguments and array
* specifiers.
* Parses additional left-associative suffixes, like type arguments and
* array specifiers.
*/
@Nonnull
private AbstractJClass _parseSuffix (@Nonnull final AbstractJClass aClazz)
Expand Down
21 changes: 18 additions & 3 deletions src/main/java/com/helger/jcodemodel/JPackage.java
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,11 @@ public JDefinedClass _getClass (@Nullable final String sName)
* @param rsrc
* Resource file to add
* @return Parameter resource file
* @deprecated Use the API from {@link JResourceDir} instead. Deprecated since
* v3.3.1
*/
@Nonnull
@Deprecated
public AbstractJResourceFile addResourceFile (@Nonnull final AbstractJResourceFile rsrc)
{
JCValueEnforcer.notNull (rsrc, "ResourceFile");
Expand All @@ -297,7 +300,10 @@ public AbstractJResourceFile addResourceFile (@Nonnull final AbstractJResourceFi
* @param sName
* Filename to check
* @return <code>true</code> if contained
* @deprecated Use the API from {@link JResourceDir} instead. Deprecated since
* v3.3.1
*/
@Deprecated
public boolean hasResourceFile (@Nullable final String sName)
{
for (final AbstractJResourceFile r : m_aResources)
Expand All @@ -310,7 +316,7 @@ public boolean hasResourceFile (@Nullable final String sName)
* Iterates all resource files in this package.
*
* @return Iterator
* @deprecated Use {@link #resourceFiles()} instead
* @deprecated Use {@link #resourceFiles()} instead. Deprecated since v3.3.1
*/
@Deprecated
@Nonnull
Expand All @@ -324,13 +330,22 @@ public Iterator <AbstractJResourceFile> propertyFiles ()
*
* @return Iterator
* @since 3.2.0
* @deprecated Use the API from {@link JResourceDir} instead. Deprecated since
* v3.3.1
*/
@Deprecated
@Nonnull
public Iterator <AbstractJResourceFile> resourceFiles ()
{
return m_aResources.iterator ();
}

/**
* @return A copy of all contained resource files. Never <code>null</code>.
* @deprecated Use the API from {@link JResourceDir} instead. Deprecated since
* v3.3.1
*/
@Deprecated
@Nonnull
public List <AbstractJResourceFile> getAllResourceFiles ()
{
Expand Down Expand Up @@ -501,14 +516,14 @@ public Collection <JAnnotationUse> annotations ()
@Nonnull
File toPath (@Nonnull final File aDir)
{
if (m_sName == null)
if (isUnnamed ())
return aDir;
return new File (aDir, m_sName.replace ('.', File.separatorChar));
}

public void declare (@Nonnull final IJFormatter f)
{
if (m_sName.length () != 0)
if (!isUnnamed ())
f.print ("package").print (m_sName).print (';').newline ();
}

Expand Down
Loading

0 comments on commit 1873afe

Please sign in to comment.