Skip to content

Commit

Permalink
Further #74 improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
phax committed Jan 18, 2020
1 parent b5cdf7e commit 78d37e4
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 15 deletions.
18 changes: 10 additions & 8 deletions src/main/java/com/helger/jcodemodel/JPackage.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public class JPackage implements
IJAnnotatable,
IJDocCommentable
{
public static final char SEPARATOR = '.';
public static final Pattern VALID_PACKAGE_NAME_ANYCASE = Pattern.compile ("[A-Za-z_][A-Za-z0-9_]*");
public static final Pattern VALID_PACKAGE_NAME_LOWERCASE = Pattern.compile ("[a-z_][a-z0-9_]*");
private static final AtomicBoolean FORCE_PACKAGE_NAME_LOWERCASE = new AtomicBoolean (false);
Expand Down Expand Up @@ -188,7 +189,7 @@ protected JPackage (@Nonnull final String sName, @Nonnull final JCodeModel aOwne
// An empty package name is okay
if (sName.length () > 0)
{
final String [] aParts = JCStringHelper.getExplodedArray ('.', sName);
final String [] aParts = JCStringHelper.getExplodedArray (SEPARATOR, sName);
for (final String sPart : aParts)
if (isForbiddenPackageNamePart (sPart))
throw new IllegalArgumentException ("Part '" + sPart + "' of the package name '" + sName + "' is invalid");
Expand Down Expand Up @@ -218,7 +219,7 @@ public JPackage parent ()
if (isUnnamed ())
return null;

final int idx = m_sName.lastIndexOf ('.');
final int idx = m_sName.lastIndexOf (SEPARATOR);
if (idx < 0)
return m_aOwner.rootPackage ();
return m_aOwner._package (m_sName.substring (0, idx));
Expand Down Expand Up @@ -261,13 +262,13 @@ public JDefinedClass _class (final int nMods,

// Okay, the class name is unique inside this package
// Check if a resource with the same name already exists
JResourceDir aRD = m_aOwner.resourceDir (m_sName.replace ('.', '/'));
JResourceDir aRD = m_aOwner.resourceDir (m_sName.replace (SEPARATOR, JResourceDir.SEPARATOR));
if (aRD.hasResourceFile (sClassName + ".java"))
throw new JResourceAlreadyExistsException (aRD.fullChildName (sClassName + ".java"));

if (m_aUpperCaseClassMap != null)
{
aRD = m_aOwner.resourceDir (m_sName.toUpperCase (Locale.ROOT).replace ('.', '/'));
aRD = m_aOwner.resourceDir (m_sName.toUpperCase (Locale.ROOT).replace (SEPARATOR, JResourceDir.SEPARATOR));
if (aRD.hasResourceFile (sUpperClassName + ".java"))
throw new JResourceAlreadyExistsException (aRD.fullChildName (sUpperClassName + ".java"));
}
Expand Down Expand Up @@ -427,13 +428,14 @@ public void remove (@Nonnull final AbstractJClass aClass)
@Nonnull
public AbstractJClass ref (@Nonnull final String sClassLocalName) throws ClassNotFoundException
{
JCValueEnforcer.isTrue (sClassLocalName.indexOf ('.') < 0, () -> "JClass name contains '.': " + sClassLocalName);
JCValueEnforcer.isTrue (sClassLocalName.indexOf (SEPARATOR) < 0,
() -> "JClass name contains '.': " + sClassLocalName);

String sFQCN;
if (isUnnamed ())
sFQCN = "";
else
sFQCN = m_sName + '.';
sFQCN = m_sName + SEPARATOR;
sFQCN += sClassLocalName;

return m_aOwner.ref (Class.forName (sFQCN));
Expand All @@ -451,7 +453,7 @@ public JPackage subPackage (@Nonnull final String sSubPackageName)
{
if (isUnnamed ())
return owner ()._package (sSubPackageName);
return owner ()._package (m_sName + '.' + sSubPackageName);
return owner ()._package (m_sName + SEPARATOR + sSubPackageName);
}

/**
Expand Down Expand Up @@ -545,7 +547,7 @@ File toPath (@Nonnull final File aDir)
{
if (isUnnamed ())
return aDir;
return new File (aDir, m_sName.replace ('.', File.separatorChar));
return new File (aDir, m_sName.replace (SEPARATOR, File.separatorChar));
}

public void declare (@Nonnull final IJFormatter f)
Expand Down
15 changes: 10 additions & 5 deletions src/main/java/com/helger/jcodemodel/JResourceDir.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
public class JResourceDir implements IJOwned
{
public static final char SEPARATOR = JCFilenameHelper.UNIX_SEPARATOR;
public static final String SEPARATOR_STR = Character.toString (SEPARATOR);
private static final String SEPARATOR_TWICE = SEPARATOR_STR + SEPARATOR_STR;

/**
* Check if the resource directory name part is valid or not.
Expand Down Expand Up @@ -128,10 +130,12 @@ protected JResourceDir (@Nonnull final String sName, @Nonnull final JCodeModel a
{
// Convert "\" to "/"
String sCleanPath = JCFilenameHelper.getPathUsingUnixSeparator (sName);
// Replace all double separators with a single one
sCleanPath = JCStringHelper.replaceAllRepeatedly (sCleanPath, SEPARATOR_TWICE, SEPARATOR_STR);
// Ensure last part is not a "/"
sCleanPath = JCFilenameHelper.ensurePathEndingWithoutSeparator (sCleanPath);

if (sCleanPath.startsWith ("/"))
if (sCleanPath.startsWith (SEPARATOR_STR))
throw new IllegalArgumentException ("A resource directory may not be an absolute path: '" + sName + "'");

final String [] aParts = JCStringHelper.getExplodedArray (SEPARATOR, sCleanPath);
Expand Down Expand Up @@ -186,7 +190,7 @@ public JResourceDir parent ()
if (isUnnamed ())
return null;

final int idx = m_sName.lastIndexOf ('/');
final int idx = m_sName.lastIndexOf (SEPARATOR);
if (idx < 0)
return m_aOwner.rootResourceDir ();
return m_aOwner.resourceDir (m_sName.substring (0, idx));
Expand Down Expand Up @@ -229,7 +233,8 @@ public <T extends AbstractJResourceFile> T addResourceFile (@Nonnull final T aRe
bIsPotentiallyJavaSrcFile = sName.endsWith (".java");
if (bIsPotentiallyJavaSrcFile)
{
final JPackage aPackage = owner ()._package (m_sName.replace ('/', '.'));
final JPackage aPackage = owner ()._package (m_sName.replace (SEPARATOR, JPackage.SEPARATOR));
// Cut trailing ".java"
final JDefinedClass aDC = aPackage.getClassResource (sName.substring (0, sName.length () - 5));
if (aDC != null)
throw new JClassAlreadyExistsException (aDC);
Expand Down Expand Up @@ -289,7 +294,7 @@ public JResourceDir subDir (@Nonnull final String sSubDirName)
{
if (isUnnamed ())
return owner ().resourceDir (sSubDirName);
return owner ().resourceDir (m_sName + '/' + sSubDirName);
return owner ().resourceDir (m_sName + SEPARATOR + sSubDirName);
}

/**
Expand Down Expand Up @@ -322,6 +327,6 @@ int countArtifacts ()
@Nonnull
String fullChildName (@Nonnull final String sChildName)
{
return isUnnamed () ? sChildName : m_sName + '/' + sChildName;
return isUnnamed () ? sChildName : m_sName + SEPARATOR + sChildName;
}
}
40 changes: 40 additions & 0 deletions src/main/java/com/helger/jcodemodel/util/JCStringHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,46 @@ public static String replaceAll (@Nullable final String sInputString,
return ret.toString ();
}

/**
* Just calls <code>replaceAll</code> as long as there are still replacements
* found
*
* @param sInputString
* The input string where the text should be replace. If this parameter
* is <code>null</code> or empty, no replacement is done.
* @param sSearchText
* The string to be replaced. May neither be <code>null</code> nor
* empty.
* @param sReplacementText
* The string with the replacement. May not be <code>null</code> but
* may be empty.
* @return The input string as is, if the input string is empty or if the
* string to be replaced is not contained.
*/
@Nullable
public static String replaceAllRepeatedly (@Nullable final String sInputString,
@Nonnull final String sSearchText,
@Nonnull final String sReplacementText)
{
JCValueEnforcer.notEmpty (sSearchText, "SearchText");
JCValueEnforcer.notNull (sReplacementText, "ReplacementText");
JCValueEnforcer.isFalse (sReplacementText.contains (sSearchText),
"Loop detection: replacementText must not contain searchText");

// Is input string empty?
if (hasNoText (sInputString))
return sInputString;

String sRet = sInputString;
String sLastLiteral;
do
{
sLastLiteral = sRet;
sRet = sRet.replace (sSearchText, sReplacementText);
} while (!sLastLiteral.equals (sRet));
return sRet;
}

/**
* Get the first character of the passed character sequence
*
Expand Down
14 changes: 12 additions & 2 deletions src/test/java/com/helger/jcodemodel/JResourceDirTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,21 @@ public void testAbsolutePath ()
}

@Test (expected = IllegalArgumentException.class)
public void testDoubleSlash ()
public void testAbsolutePath2 ()
{
final JCodeModel cm = new JCodeModel ();
// this should fail because of empty "in-between" directory
// this should fail
cm.resourceDir ("\\usr");
}

public void testMultiSeparator ()
{
final JCodeModel cm = new JCodeModel ();
// works because of internal unification
cm.resourceDir ("usr//bla");
cm.resourceDir ("usr////////////////////////////////////////////////////bla");
cm.resourceDir ("usr//bla///////////////////////////////////////");
cm.resourceDir ("usr//\\\\\\\\\\\\\\\\\\\\\\///\\\\\\\\bla\\\\\\\\\\\\/////");
}

@Test (expected = JResourceAlreadyExistsException.class)
Expand Down

0 comments on commit 78d37e4

Please sign in to comment.