[jbosscache-commits] JBoss Cache SVN: r5620 - in core/trunk/src: test/java/org/jboss/cache and 1 other directory.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Tue Apr 22 10:53:02 EDT 2008


Author: manik.surtani at jboss.com
Date: 2008-04-22 10:53:02 -0400 (Tue, 22 Apr 2008)
New Revision: 5620

Added:
   core/trunk/src/main/java/org/jboss/cache/StringFqn.java
Modified:
   core/trunk/src/main/java/org/jboss/cache/Fqn.java
   core/trunk/src/test/java/org/jboss/cache/FqnTest.java
Log:
Optimised Fqns for String representation

Modified: core/trunk/src/main/java/org/jboss/cache/Fqn.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/Fqn.java	2008-04-22 12:57:24 UTC (rev 5619)
+++ core/trunk/src/main/java/org/jboss/cache/Fqn.java	2008-04-22 14:53:02 UTC (rev 5620)
@@ -94,7 +94,7 @@
 
    private static final Log log = LogFactory.getLog(Fqn.class);
 
-   private List<E> elements;
+   protected List<E> elements;
    private transient int hash_code = 0;
    private int size = 0;
 
@@ -102,25 +102,25 @@
     * Immutable root FQN.
     */
    @SuppressWarnings("unchecked")
-   public static final Fqn ROOT = new Fqn(true);
+   public static final Fqn ROOT = new StringFqn();
 
    /**
     * A cached string representation of this Fqn, used by toString to it isn't calculated again every time.
     */
-   private String cachedStringRep;
+   protected String stringRepresentation;
 
    // ----------------- START: Private constructors for use by factory methods only. ----------------------
 
    // TODO: Remove the unnecessary internalMarker boolean parameters to these methods once the deprecated public constructors are removed in 3.0.0.
 
-   private Fqn(boolean internalMarker)
+   protected Fqn(boolean internalMarker)
    {
       elements = Collections.emptyList();
       size = 0;
    }
 
    @SuppressWarnings("unchecked")
-   private Fqn(boolean internalMarker, List<?> names, boolean safe)
+   protected Fqn(boolean internalMarker, List<?> names, boolean safe)
    {
       if (names != null)
       {
@@ -136,7 +136,7 @@
    }
 
    @SuppressWarnings("unchecked")
-   private Fqn(boolean internalMarker, Fqn<?> base, List<?> relative)
+   protected Fqn(boolean internalMarker, Fqn<?> base, List<?> relative)
    {
       List elements = new ArrayList(base.elements.size() + relative.size());
       elements.addAll(base.elements);
@@ -180,7 +180,10 @@
     */
    public static <E> Fqn<E> fromList(List<E> names)
    {
-      return new Fqn<E>(true, names, false);
+      if (containsStrings(names))
+         return new StringFqn((List<String>) names);
+      else
+         return new Fqn<E>(true, names, false);
    }
 
    /**
@@ -221,7 +224,11 @@
     */
    public static <E> Fqn<E> fromElements(E... elements)
    {
-      return new Fqn<E>(true, Arrays.asList(elements), true);
+      List el = Arrays.asList(elements);
+      if (containsStrings(el))
+         return new StringFqn(el);
+      else
+         return new Fqn<E>(true, el, true);
    }
 
    /**
@@ -247,7 +254,10 @@
     */
    public static Fqn<Object> fromRelativeFqn(Fqn<?> base, Fqn<?> relative)
    {
-      return new Fqn<Object>(true, base, relative.elements);
+      if (base.getClass().equals(StringFqn.class) && relative.getClass().equals(StringFqn.class))
+         return new StringFqn((StringFqn) base, (StringFqn) relative);
+      else
+         return new Fqn<Object>(true, base, relative.elements);
    }
 
    /**
@@ -273,7 +283,10 @@
     */
    public static Fqn<Object> fromRelativeList(Fqn<?> base, List<?> relativeElements)
    {
-      return new Fqn<Object>(true, base, relativeElements);
+      if (base.getClass().equals(StringFqn.class) && containsStrings(relativeElements))
+         return new StringFqn((StringFqn) base, (List<String>) relativeElements);
+      else
+         return new Fqn<Object>(true, base, relativeElements);
    }
 
    /**
@@ -299,9 +312,22 @@
     */
    public static Fqn<Object> fromRelativeElements(Fqn<?> base, Object... relativeElements)
    {
-      return new Fqn<Object>(true, base, Arrays.asList(relativeElements));
+      List rel = Arrays.asList(relativeElements);
+      if (base.getClass().equals(StringFqn.class) && containsStrings(rel))
+         return new StringFqn((StringFqn) base, rel);
+      else
+         return new Fqn<Object>(true, base, rel);
    }
 
+   protected static boolean containsStrings(List l)
+   {
+      for (Object o : l)
+      {
+         if (!(o instanceof String)) return false;
+      }
+      return true;
+   }
+
    /**
     * Returns a new Fqn from a string, where the elements are deliminated by
     * one or more separator ({@link #SEPARATOR}) characters.<br><br>
@@ -322,6 +348,7 @@
     * @return an Fqn<String> constructed from the string representation passed in
     * @see #Fqn(Object[])
     */
+   @SuppressWarnings("unchecked")
    public static Fqn<String> fromString(String stringRepresentation)
    {
       if (stringRepresentation == null)
@@ -331,7 +358,7 @@
       List<String> list = new ArrayList<String>();
       StringTokenizer tok = new StringTokenizer(stringRepresentation, SEPARATOR);
       while (tok.hasMoreTokens()) list.add(tok.nextToken());
-      return new Fqn<String>(true, list, true);
+      return new StringFqn(list);
    }
 
    /**
@@ -465,7 +492,7 @@
    {
       if (hash_code == 0)
       {
-         hash_code = _hashCode();
+         hash_code = calculateHashCode();
       }
       return hash_code;
    }
@@ -482,11 +509,11 @@
     */
    public String toString()
    {
-      if (cachedStringRep == null)
+      if (stringRepresentation == null)
       {
          if (isRoot())
          {
-            cachedStringRep = SEPARATOR;
+            stringRepresentation = SEPARATOR;
          }
          else
          {
@@ -495,10 +522,10 @@
             {
                sb.append(SEPARATOR).append(element);
             }
-            cachedStringRep = sb.toString();
+            stringRepresentation = sb.toString();
          }
       }
-      return cachedStringRep;
+      return stringRepresentation;
    }
 
    public void writeExternal(ObjectOutput out) throws IOException
@@ -578,7 +605,7 @@
     *
     * @return a cached hashcode
     */
-   private int _hashCode()
+   protected int calculateHashCode()
    {
       int hashCode = 0;
       int count = 1;

Added: core/trunk/src/main/java/org/jboss/cache/StringFqn.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/StringFqn.java	                        (rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/StringFqn.java	2008-04-22 14:53:02 UTC (rev 5620)
@@ -0,0 +1,86 @@
+package org.jboss.cache;
+
+import java.util.List;
+
+/**
+ * An optimisation of Fqn that does more efficient equals() and hashcode() computations.  This is returned by default when
+ * the factory method {@link Fqn#fromString(String)} is used, or when any of the other factory methods on {@link Fqn} are
+ * passed only String elements.
+ *
+ * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ * @since 2.2.0
+ */
+public class StringFqn extends Fqn
+{
+   protected StringFqn()
+   {
+      super(true);
+      stringRepresentation = SEPARATOR;
+   }
+
+   protected StringFqn(StringFqn base, List<String> elements)
+   {
+      super(true, base, elements);
+      String elementStringRep = getStringRepresentation(elements);
+      stringRepresentation = base.isRoot() ? elementStringRep : base.stringRepresentation + elementStringRep;
+   }
+
+   protected StringFqn(StringFqn base, StringFqn relative)
+   {
+      super(true, base, relative.elements);
+      stringRepresentation = base.isRoot() ? relative.stringRepresentation : base.stringRepresentation + relative.stringRepresentation;
+   }
+
+   protected StringFqn(List<String> elements)
+   {
+      super(true, elements, false);
+      stringRepresentation = getStringRepresentation(elements);
+   }
+
+   private String getStringRepresentation(List<String> elements)
+   {
+      StringBuilder builder = new StringBuilder();
+      for (String e : elements)
+      {
+         builder.append(SEPARATOR);
+         // escape special chars.
+         builder.append(e.replace("\\", "\\\\").replace("/", "\\/"));
+      }
+      return builder.toString();
+   }
+
+   @Override
+   public boolean equals(Object other)
+   {
+      if (other == this) return true;
+      if (other == null) return false;
+      if (other.getClass().equals(StringFqn.class))
+      {
+         return stringRepresentation.equals(((StringFqn) other).stringRepresentation);
+      }
+      else
+      {
+         return super.equals(other);
+      }
+   }
+
+   @Override
+   protected int calculateHashCode()
+   {
+      return stringRepresentation.hashCode();
+   }
+
+   @Override
+   public boolean isChildOrEquals(Fqn parentFqn)
+   {
+      if (parentFqn.getClass().equals(StringFqn.class))
+      {
+         StringFqn stringParentFqn = (StringFqn) parentFqn;
+         return stringRepresentation.startsWith(stringParentFqn.stringRepresentation);
+      }
+      else
+      {
+         return super.isChildOrEquals(parentFqn);
+      }
+   }
+}

Modified: core/trunk/src/test/java/org/jboss/cache/FqnTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/FqnTest.java	2008-04-22 12:57:24 UTC (rev 5619)
+++ core/trunk/src/test/java/org/jboss/cache/FqnTest.java	2008-04-22 14:53:02 UTC (rev 5620)
@@ -8,11 +8,16 @@
 
 
 import org.jboss.cache.config.Configuration;
-import org.jgroups.util.Util;
+import org.jboss.cache.marshall.CacheMarshaller210;
+import org.jboss.cache.marshall.Marshaller;
 import org.testng.annotations.AfterTest;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.HashMap;
 
 /**
@@ -25,11 +30,13 @@
 public class FqnTest
 {
    private Cache<Object, Object> cache;
+   private Marshaller marshaller;
 
    @BeforeTest
    protected void setUp()
    {
       cache = null;
+      marshaller = new CacheMarshaller210();
    }
 
    @AfterTest
@@ -341,8 +348,13 @@
    @SuppressWarnings("unchecked")
          <T> Fqn<T> marshalAndUnmarshal(Fqn<T> fqn) throws Exception
    {
-      byte[] buf = Util.objectToByteBuffer(fqn);
-      return (Fqn<T>) Util.objectFromByteBuffer(buf);
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      ObjectOutputStream out = new ObjectOutputStream(baos);
+      marshaller.objectToObjectStream(fqn, out);
+      out.close();
+      baos.close();
+      ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
+      return (Fqn<T>) marshaller.objectFromObjectStream(in);
    }
 
    // testing generics
@@ -393,6 +405,7 @@
 //   }
 
    //
+
    public void testGenerations()
    {
       Fqn<Integer> f = Fqn.fromElements(1, 2, 3, 4, 5, 6, 7);
@@ -433,4 +446,24 @@
    {
       System.out.println("-- " + msg);
    }
+
+   public void testUnescapedString()
+   {
+      Fqn f1 = Fqn.fromString("/a/b/c/d"); // an Fqn containing elements "a", "b", "c", "d".
+      Fqn f2 = Fqn.fromElements("a", "b", "c", "d");
+
+      assert f1.equals(f2);
+      assert f2.equals(f1);
+
+      Fqn f3 = Fqn.fromElements("a", "b/c", "d");
+
+      assert !f1.equals(f3);
+      assert !f2.equals(f3);
+      assert !f3.equals(f1);
+      assert !f3.equals(f2);
+
+      System.out.println("F1: " + f1);
+      System.out.println("F2: " + f2);
+      System.out.println("F3: " + f3);
+   }
 }




More information about the jbosscache-commits mailing list