Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,16 @@ protected JEnumConstantExpr (@Nonnull final Enum <?> aEnumConstant)
m_aEnumConstant = ValueEnforcer.notNull (aEnumConstant, "EnumConstant");
}

@Override
public void generate (@Nonnull final IJFormatter f)
{
f.type (owner ().ref (m_aEnumConstant.getDeclaringClass ())).print ('.').print (m_aEnumConstant.name ());
}

public Enum <?> getEnumConstant ()
{
return m_aEnumConstant;
}
}

protected static final class FullClassNameExpr implements IJExpression
Expand All @@ -77,6 +83,7 @@ protected FullClassNameExpr (@Nonnull final Class <?> aClass)
m_aClass = ValueEnforcer.notNull (aClass, "Class");
}

@Override
public void generate (@Nonnull final IJFormatter f)
{
f.print (JCNameUtilities.getFullName (m_aClass)).print (".class");
Expand Down
53 changes: 45 additions & 8 deletions src/main/java/com/helger/jcodemodel/JCodeModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
*/
package com.helger.jcodemodel;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -223,7 +228,7 @@ public final IFileSystemConvention getFileSystemConvention ()
*/
@Nonnull
public final IFileSystemConvention setFileSystemConvention (@Nonnull final IFileSystemConvention aFSConvention) throws JCaseSensitivityChangeException,
JInvalidFileNameException
JInvalidFileNameException
{
ValueEnforcer.notNull (aFSConvention, "FSConvention");
if (aFSConvention == m_aFSConvention)
Expand Down Expand Up @@ -464,15 +469,15 @@ public List <JResourceDir> getAllResourceDirs ()
*/
@Nonnull
public JDefinedClass _class (final int nMods,
@Nonnull final String sFullyQualifiedClassName,
@Nonnull final EClassType eClassType) throws JCodeModelException
@Nonnull final String sFullyQualifiedClassName,
@Nonnull final EClassType eClassType) throws JCodeModelException
{
final int nIdx = sFullyQualifiedClassName.lastIndexOf (JPackage.SEPARATOR);
if (nIdx < 0)
return rootPackage ()._class (nMods, sFullyQualifiedClassName, eClassType);
return _package (sFullyQualifiedClassName.substring (0, nIdx))._class (nMods,
sFullyQualifiedClassName.substring (nIdx + 1),
eClassType);
sFullyQualifiedClassName.substring (nIdx + 1),
eClassType);
}

/**
Expand Down Expand Up @@ -520,7 +525,7 @@ public JDefinedClass _class (final int nMods, @Nonnull final String sFullyQualif
*/
@Nonnull
public JDefinedClass _class (@Nonnull final String sFullyQualifiedClassName,
@Nonnull final EClassType eClassType) throws JCodeModelException
@Nonnull final EClassType eClassType) throws JCodeModelException
{
return _class (JMod.PUBLIC, sFullyQualifiedClassName, eClassType);
}
Expand Down Expand Up @@ -769,7 +774,7 @@ public AbstractJClass ref (@Nonnull final Class <?> aClazz)
*/
@Nonnull
public JDefinedClass ref (@Nonnull final TypeElement aElement, @Nonnull final Elements aElementUtils) throws ErrorTypeFound,
CodeModelBuildingException
CodeModelBuildingException
{
final JCodeModelJavaxLangModelAdapter adapter = new JCodeModelJavaxLangModelAdapter (this, aElementUtils);
return adapter.getClass (aElement);
Expand Down Expand Up @@ -806,7 +811,7 @@ public JDefinedClass ref (@Nonnull final TypeElement aElement, @Nonnull final El
*/
@Nonnull
public JDefinedClass refWithErrorTypes (@Nonnull final TypeElement aElement,
@Nonnull final Elements aElementUtils) throws CodeModelBuildingException
@Nonnull final Elements aElementUtils) throws CodeModelBuildingException
{
final JCodeModelJavaxLangModelAdapter adapter = new JCodeModelJavaxLangModelAdapter (this, aElementUtils);
return adapter.getClassWithErrorTypes (aElement);
Expand Down Expand Up @@ -1083,4 +1088,36 @@ public Set <AbstractJClass> getAllDontImportClasses ()
{
return new HashSet <> (m_aDontImportClasses);
}

/**
* copy a codemodel using serialization.
*
* @param source
* codemodel to copy
* @return a deserialization of the serialization of the source.
*/
public static JCodeModel copySerial (JCodeModel source)
{
try
{
ByteArrayOutputStream buffer = new ByteArrayOutputStream ();
new ObjectOutputStream (buffer).writeObject (source);
ByteArrayInputStream in = new ByteArrayInputStream (buffer.toByteArray ());
return (JCodeModel) new ObjectInputStream (in).readObject ();
}
catch (IOException | ClassNotFoundException e)
{
throw new UnsupportedOperationException ("catch this", e);
Copy link

Copilot AI Aug 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message "catch this" is unclear and unhelpful. Consider using a more descriptive message that explains the serialization failure, such as "Failed to copy JCodeModel through serialization".

Suggested change
throw new UnsupportedOperationException ("catch this", e);
throw new UnsupportedOperationException ("Failed to copy JCodeModel through serialization", e);

Copilot uses AI. Check for mistakes.
}
}

/**
* create a new copy of this model
*
* @return a new object, which should have the same representation but not linked to this in any way.
*/
public JCodeModel copy ()
{
return copySerial (this);
}
}
11 changes: 10 additions & 1 deletion src/main/java/com/helger/jcodemodel/JReferencedClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ class JReferencedClass extends AbstractJClass implements IJDeclaration
assert !m_aClass.isArray ();
}

public Class <?> getReferencedClass ()
{
return m_aClass;
}

@Override
public String name ()
{
Expand Down Expand Up @@ -142,17 +147,20 @@ public Iterator <AbstractJClass> _implements ()
{
private int m_nIdx = 0;

@Override
public boolean hasNext ()
{
return m_nIdx < aInterfaces.length;
}

@Override
@Nonnull
public AbstractJClass next ()
{
return owner ().ref (aInterfaces[m_nIdx++]);
}

@Override
public void remove ()
{
throw new UnsupportedOperationException ();
Expand Down Expand Up @@ -189,6 +197,7 @@ public final JPrimitiveType getPrimitiveType ()
return m_aPrimitiveType;
}

@Override
public void declare (final IJFormatter f)
{
// Nothing to do here...
Expand All @@ -203,7 +212,7 @@ public void declare (final IJFormatter f)

@Override
protected AbstractJClass substituteParams (@Nonnull final JTypeVar [] aVariables,
@Nonnull final List <? extends AbstractJClass> aBindings)
@Nonnull final List <? extends AbstractJClass> aBindings)
{
// TODO: does JDK 1.5 reflection provides these information?
return this;
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/com/helger/jcodemodel/JResourceDir.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
package com.helger.jcodemodel;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
Expand All @@ -66,7 +67,7 @@
*
* @since 3.3.1
*/
public class JResourceDir implements IJOwned
public class JResourceDir implements IJOwned, Serializable
{
public static final char SEPARATOR = FilenameHelper.UNIX_SEPARATOR;
public static final String SEPARATOR_STR = Character.toString (SEPARATOR);
Expand Down Expand Up @@ -105,8 +106,8 @@ public class JResourceDir implements IJOwned
* If a part of the package name is not a valid filename part.
*/
protected JResourceDir (@Nonnull final JCodeModel aOwner,
@Nullable final JResourceDir aParentDir,
@Nonnull final String sName) throws JInvalidFileNameException
@Nullable final JResourceDir aParentDir,
@Nonnull final String sName) throws JInvalidFileNameException
{
ValueEnforcer.notNull (sName, "Name");
ValueEnforcer.notNull (aOwner, "CodeModel");
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/com/helger/jcodemodel/JTypeVarClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ protected JTypeVarClass (@Nonnull final AbstractJClass aClass)
m_aClass = aClass;
}

public AbstractJClass getRefClass ()
{
return m_aClass;
}

@Override
@Nonnull
public String name ()
Expand All @@ -68,10 +73,8 @@ public String name ()
{
final JTypeVar [] aTypeParams = ((JDefinedClass) m_aClass).typeParams ();
if (aTypeParams.length > 0)
{
// We need the type params here!
return new JNarrowedClass (m_aClass, aTypeParams).name ();
}
}
return m_aClass.name ();
}
Expand All @@ -82,10 +85,8 @@ public String fullName ()
{
// This method is e.g. used for import statements
if (m_aClass instanceof JNarrowedClass)
{
// Avoid the type parameters
return ((JNarrowedClass) m_aClass).erasure ().fullName ();
}
return m_aClass.fullName ();
}

Expand Down
16 changes: 13 additions & 3 deletions src/main/java/com/helger/jcodemodel/JVar.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ public class JVar implements IJAssignmentTarget, IJDeclaration, IJAnnotatable
* Value to initialize this variable to
*/
public JVar (@Nonnull final JMods aMods,
@Nonnull final AbstractJType aType,
@Nonnull final String sName,
@Nullable final IJExpression aInitExpr)
@Nonnull final AbstractJType aType,
@Nonnull final String sName,
@Nullable final IJExpression aInitExpr)
{
ValueEnforcer.isTrue (JJavaName.isJavaIdentifier (sName), () -> "Illegal variable name '" + sName + "'");
m_aMods = aMods;
Expand Down Expand Up @@ -189,13 +189,19 @@ public AbstractJType type (@Nonnull final AbstractJType aNewType)
return aOldType;
}

public List <JAnnotationUse> getAnnotations ()
{
return m_aAnnotations == null ? Collections.emptyList () : m_aAnnotations;
}

/**
* Adds an annotation to this variable.
*
* @param aClazz
* The annotation class to annotate the field with
* @return New {@link JAnnotationUse}
*/
@Override
@Nonnull
public JAnnotationUse annotate (@Nonnull final AbstractJClass aClazz)
{
Expand All @@ -213,6 +219,7 @@ public JAnnotationUse annotate (@Nonnull final AbstractJClass aClazz)
* The annotation class to annotate the field with
* @return New {@link JAnnotationUse}
*/
@Override
@Nonnull
public JAnnotationUse annotate (@Nonnull final Class <? extends Annotation> aClazz)
{
Expand All @@ -227,6 +234,7 @@ public List <JAnnotationUse> annotationsMutable ()
return m_aAnnotations;
}

@Override
@Nonnull
public List <JAnnotationUse> annotations ()
{
Expand Down Expand Up @@ -257,11 +265,13 @@ public void bind (@Nonnull final IJFormatter f)
f.print ('=').generable (m_aInitExpr);
}

@Override
public void declare (@Nonnull final IJFormatter f)
{
f.var (this).print (';').newline ();
}

@Override
public void generate (@Nonnull final IJFormatter f)
{
f.id (m_sName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
*/
package com.helger.jcodemodel.util;

import java.io.Serializable;
import java.util.Comparator;

import javax.annotation.Nonnull;
Expand All @@ -52,7 +53,7 @@
*
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public final class ClassNameComparator implements Comparator <AbstractJClass>
public final class ClassNameComparator implements Comparator <AbstractJClass>, Serializable
{
private static final ClassNameComparator s_aInstance = new ClassNameComparator ();

Expand All @@ -70,6 +71,7 @@ public static ClassNameComparator getInstance ()
* to packages java and javax over all others. This method is used to sort
* generated import statements in a conventional way for readability.
*/
@Override
public int compare (@Nonnull final AbstractJClass aObj1, @Nonnull final AbstractJClass aObj2)
{
if (aObj1.isError () && aObj2.isError ())
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/helger/jcodemodel/util/FSName.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
*/
package com.helger.jcodemodel.util;

import java.io.Serializable;
import java.util.Locale;

import javax.annotation.Nonnull;
Expand All @@ -55,7 +56,7 @@
* @author Philip Helger
* @since 3.4.0
*/
public final class FSName implements Comparable <FSName>
public final class FSName implements Comparable <FSName>, Serializable
{
private final String m_sName;
private final String m_sKey;
Expand Down Expand Up @@ -94,6 +95,7 @@ public int hashCode ()
return ret;
}

@Override
public int compareTo (@Nonnull final FSName o)
{
return m_sKey.compareTo (o.m_sKey);
Expand Down
Loading