velocity-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nbu...@apache.org
Subject svn commit: r743927 - in /velocity/tools/trunk: examples/showcase/WEB-INF/src/resources.properties src/main/java/org/apache/velocity/tools/generic/DisplayTool.java src/test/java/org/apache/velocity/tools/DisplayToolTests.java
Date Thu, 12 Feb 2009 23:37:53 GMT
Author: nbubna
Date: Thu Feb 12 23:37:52 2009
New Revision: 743927

URL: http://svn.apache.org/viewvc?rev=743927&view=rev
Log:
VELTOOLS-113 add br(), stripTags(), word-sensitive truncate(), property-based list(), and
plural() (thanks to Sergiy Kovalchuk)

Modified:
    velocity/tools/trunk/examples/showcase/WEB-INF/src/resources.properties
    velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/DisplayTool.java
    velocity/tools/trunk/src/test/java/org/apache/velocity/tools/DisplayToolTests.java

Modified: velocity/tools/trunk/examples/showcase/WEB-INF/src/resources.properties
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/examples/showcase/WEB-INF/src/resources.properties?rev=743927&r1=743926&r2=743927&view=diff
==============================================================================
--- velocity/tools/trunk/examples/showcase/WEB-INF/src/resources.properties (original)
+++ velocity/tools/trunk/examples/showcase/WEB-INF/src/resources.properties Thu Feb 12 23:37:52
2009
@@ -253,6 +253,7 @@
 display.truncate_ObjectintString = Limits the string output of the second argument to the
specified number of characters. If the string gets curtailed, the specified suffix is used
as the ending of the truncated string.
 display.alt = Returns the configured default value ("null" by default) if the specified value
is null.
 display.alt_ObjectObject = Returns the second argument if first argument specified is null.
+display.br_Object = Inserts HTML line break tag (<br />) in front of all newline
characters of the string value of the specified object and returns the resulting string.
 display.cell = Truncates or pads the string value of the specified object as necessary to
ensure that the returned string''s length equals the default cell size.
 display.cell_Objectint = Truncates or pads the string value of the specified object as necessary
to ensure that the returned string''s length equals the specified cell size.
 display.cell_ObjectString = Truncates or pads the string value of the specified object as
necessary to ensure that the returned string''s length equals the default cell size. If truncation
is necessary, the specified suffix will replace the end of the string value to indicate that.
@@ -260,11 +261,17 @@
 display.message = Uses <code>java.text.MessageFormat</code> to format the specified
String with the specified arguments. If there are no arguments, then the String is returned
directly.
 display.message_StringObjectVarArgs.param1 = ''foo {1} {0}''
 display.message_StringObjectVarArgs.param2 = [''bar'', 2]
+display.plural_intString = Builds plural form of a passed word if ''value'' is plural, otherwise
returns ''singular''. Plural form is built using some basic English language rules for nouns
which does not guarantee correct syntax of a result in all cases.
+display.plural_intStringString = Returns ''plural'' parameter if passed 'value' is plural,
otherwise ''singular'' is returned.
+display.printf_StringObjectVarArgs = Uses String.format(Locale,String,Object...) to format
the specified String with the specified arguments.  Please note that the format required here
is quite different from that of message(String,Object...).
 display.space = Returns a string of spaces of the specified length.
 display.space_int.param1 = 4
+display.stripTags_Object = Removes HTML tags from the string value of the specified object
and returns the resulting string.
+display.stripTags_ObjectStringVarArgs = Removes all not allowed HTML tags from the string
value of the specified object and returns the resulting string.
 display.capitalize = Changes the first character of the string value of the specified object
to upper case and returns the resulting string.
 display.uncapitalize = Changes the first character of the string value of the specified object
to lower case and returns the resulting string.
 display.measure = Returns the measurements of the string value of the specified object.
+display.getAllowedTags = Returns the configured tags allowed to remain by stripTags(Object).
 display.getCellLength = Returns the configured default cell size.
 display.getCellSuffix = Returns the configured default suffix used when cell contents need
truncating.
 display.getDefaultAlternate = Returns the configured default alternate used by alt(Object).
@@ -272,6 +279,8 @@
 display.getListFinalDelimiter = Returns the configured default delimiter used between the
last two items by the list formatting methods.
 display.getTruncateLength = Returns the configured default length used by truncate(Object).
 display.getTruncateSuffix = Returns the configured default suffix used by the truncate methods.
+display.getTruncateAtWord = Returns the configured default setting for whether to truncate
at a precise character or the last fitting word.
+display.Object = ''string''
 
 # field.vm resources
 field.intro = This tool allows easy access to public static fields in classes,  such as string
constants.

Modified: velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/DisplayTool.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/DisplayTool.java?rev=743927&r1=743926&r2=743927&view=diff
==============================================================================
--- velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/DisplayTool.java
(original)
+++ velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/DisplayTool.java
Thu Feb 12 23:37:52 2009
@@ -25,6 +25,9 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.regex.Pattern;
+
+import org.apache.commons.beanutils.PropertyUtils;
 import org.apache.velocity.tools.config.DefaultKey;
 
 /**
@@ -49,7 +52,7 @@
  * template...
  *   #set( $list = [1..5] )
  *   $display.list($list)
- *   $display.truncate(10, "This is a long string.")
+ *   $display.truncate("This is a long string.", 10)
  *   Not Null: $display.alt("not null", "--")
  *   Null: $display.alt($null, "--")
  *
@@ -74,17 +77,21 @@
     public static final String LIST_FINAL_DELIM_KEY = "listFinalDelim";
     public static final String TRUNCATE_LENGTH_KEY = "truncateLength";
     public static final String TRUNCATE_SUFFIX_KEY = "truncateSuffix";
+    public static final String TRUNCATE_AT_WORD_KEY = "truncateAtWord";
     public static final String CELL_LENGTH_KEY = "cellLength";
     public static final String CELL_SUFFIX_KEY = "cellSuffix";
     public static final String DEFAULT_ALTERNATE_KEY = "defaultAlternate";
+    public static final String ALLOWED_TAGS_KEY = "allowedTags";
 
     private String defaultDelim = ", ";
     private String defaultFinalDelim = " and ";
     private int defaultTruncateLength = 30;
     private String defaultTruncateSuffix = "...";
+    private boolean defaultTruncateAtWord = false;
     private int defaultCellLength = 30;
     private String defaultCellSuffix = "...";
     private String defaultAlternate = "null";
+    private String[] defaultAllowedTags = null;
 
     /**
      * Does the actual configuration. This is protected, so
@@ -118,6 +125,12 @@
             setTruncateSuffix(truncateSuffix);
         }
 
+        Boolean truncateAtWord = values.getBoolean(TRUNCATE_AT_WORD_KEY);
+        if (truncateAtWord != null)
+        {
+            setTruncateAtWord(truncateAtWord);
+        }
+
         Integer cellLength = values.getInteger(CELL_LENGTH_KEY);
         if (cellLength != null)
         {
@@ -135,6 +148,12 @@
         {
             setDefaultAlternate(defaultAlternate);
         }
+
+        String[] allowedTags = values.getStrings(ALLOWED_TAGS_KEY);
+        if (allowedTags != null)
+        {
+            setAllowedTags(allowedTags);
+        }
     }
 
     public String getListDelimiter()
@@ -177,6 +196,16 @@
         this.defaultTruncateSuffix = suffix;
     }
 
+    public boolean getTruncateAtWord()
+    {
+        return this.defaultTruncateAtWord;
+    }
+
+    protected void setTruncateAtWord(boolean atWord)
+    {
+        this.defaultTruncateAtWord = atWord;
+    }
+
     public String getCellSuffix()
     {
         return this.defaultCellSuffix;
@@ -207,6 +236,16 @@
         this.defaultAlternate = dflt;
     }
 
+    public String[] getAllowedTags()
+    {
+        return this.defaultAllowedTags;
+    }
+
+    protected void setAllowedTags(String[] tags)
+    {
+        this.defaultAllowedTags = tags;
+    }
+
 
     /**
      * Formats a collection or array into the form "A, B and C".
@@ -235,7 +274,7 @@
     /**
      * Formats a collection or array into the form
      * "A&lt;delim&gt;B&lt;finaldelim&gt;C".
-     *
+     * 
      * @param list A collection or array.
      * @param delim A String.
      * @param finaldelim A String.
@@ -243,20 +282,36 @@
      */
     public String list(Object list, String delim, String finaldelim)
     {
+        return list(list, delim, finaldelim, null);
+    }
+
+    /**
+     * Formats a specified property of collection or array of objects into the
+     * form "A&lt;delim&gt;B&lt;finaldelim&gt;C".
+     * 
+     * @param list A collection or array.
+     * @param delim A String.
+     * @param finaldelim A String.
+     * @param property An object property to format.
+     * @return A String.
+     */
+    public String list(Object list, String delim, String finaldelim,
+                       String property)
+    {
         if (list == null)
         {
             return null;
         }
         if (list instanceof Collection)
         {
-            return format((Collection)list, delim, finaldelim);
+            return format((Collection) list, delim, finaldelim, property);
         }
         Collection items;
         if (list.getClass().isArray())
         {
             int size = Array.getLength(list);
             items = new ArrayList(size);
-            for (int i=0; i < size; i++)
+            for (int i = 0; i < size; i++)
             {
                 items.add(Array.get(list, i));
             }
@@ -265,20 +320,28 @@
         {
             items = Collections.singletonList(list);
         }
-        return format(items, delim, finaldelim);
+        return format(items, delim, finaldelim, property);
     }
 
     /**
      * Does the actual formatting of the collection.
      */
-    protected String format(Collection list, String delim, String finaldelim)
+    protected String format(Collection list, String delim, String finaldelim,
+                            String property)
     {
         StringBuilder sb = new StringBuilder();
         int size = list.size();
         Iterator iterator = list.iterator();
         for (int i = 0; i < size; i++)
         {
-            sb.append(iterator.next());
+            if (property != null && property.length() > 0)
+            {
+                sb.append(getProperty(iterator.next(), property));
+            }
+            else
+            {
+                sb.append(iterator.next());
+            }
             if (i < size - 2)
             {
                 sb.append(delim);
@@ -430,10 +493,10 @@
     }
 
     /**
-     * Limits the string value of 'truncateMe' to the specified max length
-     * in characters. If the string gets curtailed, the specified suffix
-     * is used as the ending of the truncated string.
-     *
+     * Limits the string value of 'truncateMe' to the specified max length in
+     * characters. If the string gets curtailed, the specified suffix is used as
+     * the ending of the truncated string.
+     * 
      * @param truncateMe The value to be truncated.
      * @param maxLength An int with the maximum length.
      * @param suffix A String.
@@ -441,6 +504,23 @@
      */
     public String truncate(Object truncateMe, int maxLength, String suffix)
     {
+        return truncate(truncateMe, maxLength, suffix, defaultTruncateAtWord);
+    }
+
+    /**
+     * Limits the string value of 'truncateMe' to the latest complete word
+     * within the specified maxLength. If the string gets curtailed, the
+     * specified suffix is used as the ending of the truncated string.
+     * 
+     * @param truncateMe The value to be truncated.
+     * @param maxLength An int with the maximum length.
+     * @param suffix A String.
+     * @param defaultTruncateAtWord Truncate at a word boundary if true.
+     * @return A String.
+     */
+    public String truncate(Object truncateMe, int maxLength, String suffix,
+                           boolean defaultTruncateAtWord)
+    {
         if (truncateMe == null || maxLength <= 0)
         {
             return null;
@@ -456,8 +536,19 @@
             // either no need or no room for suffix
             return string.substring(0, maxLength);
         }
-        // truncate early and append suffix
+        if (defaultTruncateAtWord)
+        {
+            // find the latest space within maxLength
+            int lastSpace = string.substring(0, maxLength - suffix.length() + 1)
+                            .lastIndexOf(" ");
+            if (lastSpace > suffix.length())
+            {
+                return string.substring(0, lastSpace) + suffix;
+            }
+        }
+        // truncate to exact character and append suffix
         return string.substring(0, maxLength - suffix.length()) + suffix;
+
     }
 
     /**
@@ -626,6 +717,154 @@
     }
 
     /**
+     * Inserts HTML line break tag (&lt;br /&gt;) in front of all newline
+     * characters of the string value of the specified object and returns the
+     * resulting string.
+     * @param obj
+     */
+    public String br(Object obj)
+    {
+        if (obj == null) 
+        {
+            return null;
+        }
+        else
+        {
+            return String.valueOf(obj).replaceAll("\n", "<br />\n");
+        }
+    }
+
+    /**
+     * Removes HTML tags from the string value of the specified object and
+     * returns the resulting string.
+     * @param obj
+     */
+    public String stripTags(Object obj)
+    {
+        return stripTags(obj, defaultAllowedTags);
+    }
+
+    /**
+     * Removes all not allowed HTML tags from the string value of the specified
+     * object and returns the resulting string.
+     * @param obj
+     * @param allowedTags An array of allowed tag names (i.e. "h1","br","img")
+     */
+    public String stripTags(Object obj, String... allowedTags)
+    {
+        if (obj == null)
+        {
+            return null;
+        }
+        
+        //build list of tags to be used in regex pattern
+        StringBuilder allowedTagList = new StringBuilder();
+        if (allowedTags != null)
+        {
+            for (String tag : allowedTags)
+            {
+                if (tag !=null && tag.matches("[a-zA-Z0-9]+"))
+                {
+                    if (allowedTagList.length() > 0)
+                    {
+                        allowedTagList.append("|");
+                    }
+                    allowedTagList.append(tag);
+                }
+            }
+        }
+        String tagRule = "<[^>]*?>";
+        if (allowedTagList.length() > 0)
+        {
+            tagRule = "<(?!/?(" + allowedTagList.toString() + ")[\\s>/])[^>]*?>";
+        }
+        return Pattern.compile(tagRule, Pattern.CASE_INSENSITIVE)
+                .matcher(String.valueOf(obj)).replaceAll("");
+    }
+
+    /**
+     * Builds plural form of a passed word if 'value' is plural, otherwise
+     * returns 'singular'. Plural form is built using some basic English
+     * language rules for nouns which does not guarantee correct syntax of a
+     * result in all cases.
+     * @param value
+     * @param singular Singular form of a word.
+     */
+    public String plural(int value, String singular)
+    {
+        return plural(value, singular, null);
+    }
+
+    /**
+     * Returns 'plural' parameter if passed 'value' is plural, otherwise
+     * 'singular' is returned.
+     * @param value
+     * @param singular Singular form of a word.
+     * @param plural Plural form of a word.
+     */
+    public String plural(int value, String singular, String plural)
+    {
+        if (value == 1 || value == -1)
+        {
+            return singular;
+        }
+        else if (plural != null)
+        {
+            return plural;
+        }
+        else if (singular == null || singular.length() == 0)
+        {
+            return singular;
+        }
+        else
+        {
+            //if the last letter is capital then we will append capital letters 
+            boolean isCapital = !singular.substring(singular.length() - 1)
+                                .toLowerCase().equals(singular
+                                .substring(singular.length() - 1));
+            
+            String word = singular.toLowerCase();
+            
+            if (word.endsWith("x") || word.endsWith("sh")
+                    || word.endsWith("ch") || word.endsWith("s"))
+            {
+                return singular.concat(isCapital ? "ES" : "es");
+            }
+            else if (word.length() > 1
+                    && word.endsWith("y")
+                    && !word.substring(word.length() - 2, word.length() - 1)
+                            .matches("[aeiou]"))
+            {
+                return singular.substring(0, singular.length() - 1)
+                        .concat(isCapital ? "IES" : "ies");
+            }
+            else
+            {
+                return singular.concat(isCapital ? "S" : "s");
+            }
+        }
+    }
+
+    /**
+     * Safely retrieves the specified property from the specified object.
+     * Subclasses that wish to perform more advanced, efficient, or just
+     * different property retrieval methods should override this method to do
+     * so.
+     */
+    protected Object getProperty(Object object, String property)
+    {
+        try
+        {
+            return PropertyUtils.getProperty(object, property);
+        }
+        catch (Exception e)
+        {
+            throw new IllegalArgumentException("Could not retrieve '"
+                    + property + "' from " + object + ": " + e);
+        }
+    }
+
+    /**
      * Returns the {@link Measurements} of the string value of the specified object.
      */
     public Measurements measure(Object measureMe)

Modified: velocity/tools/trunk/src/test/java/org/apache/velocity/tools/DisplayToolTests.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/src/test/java/org/apache/velocity/tools/DisplayToolTests.java?rev=743927&r1=743926&r2=743927&view=diff
==============================================================================
--- velocity/tools/trunk/src/test/java/org/apache/velocity/tools/DisplayToolTests.java (original)
+++ velocity/tools/trunk/src/test/java/org/apache/velocity/tools/DisplayToolTests.java Thu
Feb 12 23:37:52 2009
@@ -22,6 +22,7 @@
 import org.junit.*;
 import static org.junit.Assert.*;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -110,17 +111,24 @@
         conf.put(DisplayTool.LIST_FINAL_DELIM_KEY, " und ");
         conf.put(DisplayTool.TRUNCATE_LENGTH_KEY, "5");
         conf.put(DisplayTool.TRUNCATE_SUFFIX_KEY, ">");
+        conf.put(DisplayTool.TRUNCATE_AT_WORD_KEY, "true");
         conf.put(DisplayTool.CELL_LENGTH_KEY, "4");
         conf.put(DisplayTool.CELL_SUFFIX_KEY, "~");
         conf.put(DisplayTool.DEFAULT_ALTERNATE_KEY, "n/a");
+        conf.put(DisplayTool.ALLOWED_TAGS_KEY, "img,br");
         display.configure(conf);
         assertEquals(";", display.getListDelimiter());
         assertEquals(" und ", display.getListFinalDelimiter());
         assertEquals(5, display.getTruncateLength());
         assertEquals(">", display.getTruncateSuffix());
+        assertEquals(true, display.getTruncateAtWord());
         assertEquals("~", display.getCellSuffix());
         assertEquals(4, display.getCellLength());
         assertEquals("n/a", display.getDefaultAlternate());
+        String[] tags = display.getAllowedTags();
+        assertNotNull(tags);
+        assertEquals("img", tags[0]);
+        assertEquals("br", tags[1]);
 
         // ensure that configure is locked now
         conf.put(DisplayTool.LIST_DELIM_KEY, " & ");
@@ -204,6 +212,31 @@
         assertEquals("123", display.list(nums, "", ""));
         assertEquals("1; 2 und 3", display.list(nums, "; ", " und "));
     }
+    
+    public @Test void methodList_ObjectStringStringString() throws Exception
+    {
+        TestBean bean1 = new TestBean(1, "one");
+        TestBean bean2 = new TestBean(2, "two");
+        TestBean bean3 = new TestBean(3, "three");
+        TestBean[] beanArray = new TestBean[] { bean1, bean2, bean3 };
+        List<TestBean> beanList = new ArrayList<TestBean>();
+        beanList.addAll(Arrays.asList(beanArray));
+        
+        DisplayTool display = new DisplayTool();
+        assertEquals(null, display.list(null, null, null, null));
+        assertEquals("1null2null3", display.list(beanArray, null, null, "num"));
+        assertEquals("123", display.list(beanList, "", "", "num"));
+        assertEquals("one, two or three", display.list(beanList, ", ", " or ", "str"));
+    }
+
+    public @Test void methodSetAllowedTags_StringArray() throws Exception
+    {
+        DisplayTool display = new DisplayTool();
+        assertNull(display.getAllowedTags());
+        String[] tags = new String[] { "img" };
+        display.setAllowedTags(tags);
+        assertEquals(tags, display.getAllowedTags());
+    }
 
     public @Test void methodSetCellLength_int() throws Exception
     {
@@ -254,6 +287,14 @@
         assertEquals("foo", display.getTruncateSuffix());
     }
 
+    public @Test void methodSetTruncateAtWord_String() throws Exception
+    {
+        DisplayTool display = new DisplayTool();
+        assertEquals(false, display.getTruncateAtWord());
+        display.setTruncateAtWord(true);
+        assertEquals(true, display.getTruncateAtWord());
+    }
+
     public @Test void methodSpace_int() throws Exception
     {
         DisplayTool display = new DisplayTool();
@@ -308,6 +349,16 @@
         assertEquals("foob", display.truncate("foobar", 4, null));
         assertEquals("foo>", display.truncate("foobar", 4, ">"));
     }
+    
+    public @Test void methodTruncate_ObjectintStringboolean() throws Exception
+    {
+        DisplayTool display = new DisplayTool();
+        assertEquals(null, display.truncate(null, 0, null, true));
+        assertEquals(null, display.truncate("foo", 0, null, false));
+        assertEquals("f", display.truncate("foo", 1, null, true));
+        assertEquals("long stri>", display.truncate("long string", 10, ">", false));
+        assertEquals("long>", display.truncate("long string", 10, ">", true));
+    }
 
     public @Test void methodUncapitalize_Object() throws Exception
     {
@@ -318,7 +369,92 @@
         assertEquals("test", display.uncapitalize("Test"));
         assertEquals("tEST", display.uncapitalize("TEST"));
     }
+    
+    public @Test void methodBr_Object() throws Exception
+    {
+        DisplayTool display = new DisplayTool();
+        assertEquals(null, display.br(null));
+        assertEquals("", display.br(""));
+        assertEquals("<br />\n", display.br("\n"));
+        assertEquals("line1 <br />\n LINE2", display.br("line1 \n LINE2"));
+    }
+    
+    public @Test void methodStripTags_Object() throws Exception
+    {
+        DisplayTool display = new DisplayTool();
+        String html = "<p>paragraph <a href=\"url\" target='t'>link</a></p>
"
+                      + "<h1>header1</h1> <h2>header2</h2> "
+                      + "<br><br/><br  /><b>bold</b>";
+        assertEquals(null, display.stripTags(null));
+        assertEquals("", display.stripTags(""));
+        assertEquals("paragraph link header1 header2 bold", display.stripTags(html));
+    }
+    
+    public @Test void methodStripTags_ObjectStringVarArgs() throws Exception
+    {
+        DisplayTool display = new DisplayTool();
+        String html = "<p>paragraph <a href=\"url\" target='t'>link</a></p>
"
+                      + "<h1>header1</h1> <h2>header2</h2> "
+                      + "<br><br/><br  /><b>bold</b>";
+        assertEquals(null, display.stripTags(null, (String[])null));
+        assertEquals("", display.stripTags("","",""));
+        assertEquals("paragraph link <h1>header1</h1> <h2>header2</h2>
bold", 
+                display.stripTags(html, "h1", "h2"));
+        assertEquals("paragraph <a href=\"url\" target='t'>link</a> header1 header2
bold", 
+                display.stripTags(html, "a"));
+        assertEquals("paragraph link header1 header2 <br><br/><br  /><b>bold</b>",

+                display.stripTags(html, "b", "", null, "br"));
+    }
+    
+    public @Test void methodPlural_intString() throws Exception
+    {
+        DisplayTool display = new DisplayTool();
+        assertEquals(null, display.plural(1,null));
+        assertEquals("", display.plural(2,""));
+        assertEquals("items", display.plural(0,"item"));
+        assertEquals("item", display.plural(-1,"item"));
+        assertEquals("555s", display.plural(2,"555"));
+        assertEquals("TOYS", display.plural(2,"TOY"));
+        assertEquals("ladies", display.plural(2,"lady"));
+        assertEquals("foxes", display.plural(2,"fox"));
+        assertEquals("churches", display.plural(2,"church"));
+    }
+    
+    public @Test void methodPlural_intStringString() throws Exception
+    {
+        DisplayTool display = new DisplayTool();
+        assertEquals(null, display.plural(1,null,null));
+        assertEquals("", display.plural(2,"empty",""));
+        assertEquals("men", display.plural(0,"man","men"));
+        assertEquals("mouse", display.plural(-1,"mouse", "mice"));
+    }
 
-
-}
+    public class TestBean {
+        private int num;
+        private String str;
+        
+        public TestBean(int num, String str)
+        {
+            this.num = num;
+            this.str = str;
+        }
         
+        public int getNum()
+        {
+            return num;
+        }
+        public void setNum(int num)
+        {
+            this.num = num;
+        }
+        public String getStr()
+        {
+            return str;
+        }
+        public void setStr(String str)
+        {
+            this.str = str;
+        }
+    }
+
+}
\ No newline at end of file



Mime
View raw message