Skip to content

Commit

Permalink
Added support for try-with-resources support (issue #67 from @gmcfall)
Browse files Browse the repository at this point in the history
  • Loading branch information
phax committed Mar 27, 2019
1 parent ab46574 commit 2193e9e
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 5 deletions.
3 changes: 3 additions & 0 deletions README.md
Expand Up @@ -14,6 +14,9 @@ A site with the links to the [API docs](http://phax.github.io/jcodemodel/) etc.

# News and noteworthy

* v3.2.3 - work in progress
* Extended `JTryBlock` API to have more control.
* Added support for `try-with-resources` support (issue #67 from @gmcfall)
* v3.2.2 - 2019-02-25
* Using `jsr305` instead of `annotations` in POM (issue #66 from @jjYBdx4IL)
* v3.2.1 - 2019-01-23
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/helger/jcodemodel/JCatchBlock.java
Expand Up @@ -52,7 +52,7 @@ public class JCatchBlock implements IJGenerable
private JVar m_aVar;
private final JBlock m_aBody = new JBlock ();

protected JCatchBlock (@Nonnull final AbstractJClass aException)
public JCatchBlock (@Nonnull final AbstractJClass aException)
{
m_aException = aException;
}
Expand Down
87 changes: 83 additions & 4 deletions src/main/java/com/helger/jcodemodel/JTryBlock.java
Expand Up @@ -41,29 +41,52 @@
package com.helger.jcodemodel;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.Nonnull;

/**
* Try statement with Catch and/or Finally clause
* Try statement with Catch and/or Finally clause.
*/
public class JTryBlock implements IJStatement
{
private final List <JTryResource> m_aResources = new ArrayList <> ();
private final JBlock m_aBody = new JBlock ();
private final List <JCatchBlock> m_aCatches = new ArrayList <> ();
private JBlock m_aFinally;

public JTryBlock ()
{}

/**
* @return A mutable list of all try-resources for "try-with-resources".
* @since 3.2.3
*/
@Nonnull
public List <JTryResource> tryResources ()
{
return m_aResources;
}

/**
* @return The non-<code>null</code> try-body.
*/
@Nonnull
public JBlock body ()
{
return m_aBody;
}

/**
* Add a new catch block for the specification exception class. The variable
* name is automatically created.
*
* @param aException
* The exception class to catch. May not be <code>null</code>.
* @return the created catch block for further customization and never
* <code>null</code>.
* @see #catches()
*/
@Nonnull
public JCatchBlock _catch (@Nonnull final AbstractJClass aException)
{
Expand All @@ -72,12 +95,32 @@ public JCatchBlock _catch (@Nonnull final AbstractJClass aException)
return cb;
}

/**
* Get a list of all catch blocks. Since v3.2.3 the returned list is mutable.
* Previously it was immutable.
*
* @return A mutable list of all contained catch blocks.
*/
@Nonnull
public List <JCatchBlock> catches ()
{
return Collections.unmodifiableList (m_aCatches);
return m_aCatches;
}

/**
* @return <code>true</code> if at least one catch block is present,
* <code>false</code> if not.
* @since 3.2.3
*/
public boolean hasCatchBlock ()
{
return !m_aCatches.isEmpty ();
}

/**
* @return A non-<code>null</code> finally block. The block is automatically
* created the first time you call this method.
*/
@Nonnull
public JBlock _finally ()
{
Expand All @@ -86,9 +129,45 @@ public JBlock _finally ()
return m_aFinally;
}

/**
* Remove the finally block - this allows to reset an eventually accidentally
* created finally block.
*
* @since 3.2.3
*/
public void resetFinally ()
{
m_aFinally = null;
}

/**
* @return <code>true</code> if a finally block is present, <code>false</code>
* if not.
* @since 3.2.3
*/
public boolean hasFinally ()
{
return m_aFinally != null;
}

public void state (@Nonnull final IJFormatter f)
{
f.print ("try").generable (m_aBody);
f.print ("try");
if (!m_aResources.isEmpty ())
{
f.print ('(');
boolean bFirst = true;
for (final JTryResource aResource : m_aResources)
{
if (bFirst)
bFirst = false;
else
f.print (';').newline ();
f.generable (aResource);
}
f.print (')');
}
f.generable (m_aBody);
for (final JCatchBlock cb : m_aCatches)
f.generable (cb);
if (m_aFinally != null)
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/com/helger/jcodemodel/JTryResource.java
@@ -0,0 +1,41 @@
package com.helger.jcodemodel;

import javax.annotation.Nonnull;

/**
* This class represents a single resources that is used in try-with-resources
* statement. See {@link JTryBlock}.
*
* @author Philip Helger
* @since 3.2.3
*/
public class JTryResource implements IJGenerable
{
private final JVar m_aVar;

public JTryResource (@Nonnull final AbstractJType aType,
@Nonnull final String sName,
@Nonnull final IJExpression aInitExpr)
{
this (JMod.FINAL, aType, sName, aInitExpr);
}

public JTryResource (final int nMods,
@Nonnull final AbstractJType aType,
@Nonnull final String sName,
@Nonnull final IJExpression aInitExpr)
{
m_aVar = new JVar (JMods.forVar (nMods), aType, sName, aInitExpr);
}

@Nonnull
public JVar var ()
{
return m_aVar;
}

public void generate (@Nonnull final IJFormatter aFormatter)
{
aFormatter.var (m_aVar);
}
}
110 changes: 110 additions & 0 deletions src/test/java/com/helger/jcodemodel/JTryResourcesTest.java
@@ -0,0 +1,110 @@
/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
* Portions Copyright 2013-2019 Philip Helger + contributors
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.helger.jcodemodel;

import static org.junit.Assert.assertEquals;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;

import org.junit.Test;

import com.helger.jcodemodel.util.CodeModelTestsHelper;
import com.helger.jcodemodel.writer.JCMWriter;

/**
* Test class for class {@link JTryResource}.
*
* @author Philip Helger
*/
public final class JTryResourcesTest
{
private static final String CRLF = JCMWriter.getDefaultNewLine ();

@Test
public void testWith1 ()
{
final JCodeModel cm = new JCodeModel ();

final JTryBlock aTB = new JTryBlock ();

final JTryResource aTR1 = new JTryResource (cm.ref (OutputStream.class),
"os",
cm.ref (ByteArrayOutputStream.class)._new ());
aTB.tryResources ().add (aTR1);
aTB.body ().add (aTR1.var ().invoke ("read"));
assertEquals ("try(final java.io.OutputStream os = new java.io.ByteArrayOutputStream()) {" +
CRLF +
" os.read();" +
CRLF +
"}" +
CRLF,
CodeModelTestsHelper.toString (aTB));
}

@Test
public void testWith2 ()
{
final JCodeModel cm = new JCodeModel ();

final JTryBlock aTB = new JTryBlock ();

final JTryResource aTR1 = new JTryResource (cm.ref (OutputStream.class),
"os",
cm.ref (ByteArrayOutputStream.class)._new ());
aTB.tryResources ().add (aTR1);
final JTryResource aTR2 = new JTryResource (cm.ref (BufferedOutputStream.class),
"bos",
cm.ref (BufferedOutputStream.class)._new ().arg (aTR1.var ()));
aTB.tryResources ().add (aTR2);
aTB.body ().add (aTR2.var ().invoke ("readLine"));
assertEquals ("try(final java.io.OutputStream os = new java.io.ByteArrayOutputStream();" +
CRLF +
"final java.io.BufferedOutputStream bos = new java.io.BufferedOutputStream(os)) {" +
CRLF +
" bos.readLine();" +
CRLF +
"}" +
CRLF,
CodeModelTestsHelper.toString (aTB));
}
}

0 comments on commit 2193e9e

Please sign in to comment.