directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r746607 - in /directory/shared/trunk/ldap/src: main/java/org/apache/directory/shared/ldap/filter/ test/java/org/apache/directory/shared/ldap/filter/
Date Sun, 22 Feb 2009 01:17:40 GMT
Author: elecharny
Date: Sun Feb 22 01:17:39 2009
New Revision: 746607

URL: http://svn.apache.org/viewvc?rev=746607&view=rev
Log:
o Implemented the clone() method for the Nodes. Added the associated tests. 
o Fix the equals() method for the AndNode
Fix DIRSHARED-26 and DIRSHARED-24

Added:
    directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterCloneTest.java
Modified:
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AbstractExprNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AndNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ApproximateNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/Assertion.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitor.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/EqualityNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExprNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExtensibleNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/GreaterEqNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LeafNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LessEqNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/NotNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/OrNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/PresenceNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ScopeNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SimpleNode.java
    directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SubstringNode.java
    directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitorTest.java

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AbstractExprNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AbstractExprNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AbstractExprNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AbstractExprNode.java
Sun Feb 22 01:17:39 2009
@@ -210,13 +210,45 @@
     {
         throw new UnsupportedOperationException( "ScopeNode can't be part of a refinement"
);
     }
+    
+    
+    /**
+     * Clone the object
+     */
+    @Override public ExprNode clone()
+    {
+        try
+        {
+            ExprNode clone = (ExprNode)super.clone();
+            
+            if ( annotations != null )
+            {
+                for ( String key:annotations.keySet() )
+                {
+                    Object value = annotations.get( key );
+                    
+                    // Note : the value aren't cloned ! 
+                    ((AbstractExprNode)clone).annotations.put( key, value );
+                }
+            }
+            
+            return clone;
+        }
+        catch ( CloneNotSupportedException cnse )
+        {
+            return null;
+        }
+    }
 
 
+    /**
+     * @see Object#toString()
+     */
     public String toString()
     {
-        if ( ( null != getAnnotations() ) && getAnnotations().containsKey( "count"
) )
+        if ( ( null != annotations ) && annotations.containsKey( "count" ) )
         {
-            return ":[" + getAnnotations().get( "count" ) + "]";
+            return ":[" + annotations.get( "count" ) + "]";
         }
         else 
         {

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AndNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AndNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AndNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AndNode.java
Sun Feb 22 01:17:39 2009
@@ -41,7 +41,6 @@
         super( AssertionType.AND, childList );
     }
 
-
     /**
      * Creates a AndNode using a logical operator and a list of children.
      * 
@@ -52,6 +51,15 @@
         super( AssertionType.AND, childList );
     }
 
+    
+    /**
+     * Clone the AndNode
+     */
+    @Override public ExprNode clone()
+    {
+        return super.clone();
+    }
+
 
     /**
      * Creates an empty AndNode
@@ -209,7 +217,7 @@
         for ( int i = 0; i < children.size(); i++ )
         {
             ExprNode child = children.get( i );
-            ExprNode otherChild = children.get( i );
+            ExprNode otherChild = otherChildren.get( i );
             
             if ( !child.equals( otherChild ) )
             {

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ApproximateNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ApproximateNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ApproximateNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ApproximateNode.java
Sun Feb 22 01:17:39 2009
@@ -40,7 +40,15 @@
         super( attribute, value, AssertionType.APPROXIMATE );
     }
 
-
+    
+    /**
+     * Return a cloned node
+     */
+    @Override public ExprNode clone()
+    {
+        return super.clone();
+    }
+    
     
     /**
      * @see Object#toString()

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/Assertion.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/Assertion.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/Assertion.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/Assertion.java
Sun Feb 22 01:17:39 2009
@@ -32,7 +32,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Revision$
  */
-public interface Assertion
+public interface Assertion extends Cloneable
 {
     /**
      * Checks to see if a candidate is valid by asserting an arbitrary predicate

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionNode.java
Sun Feb 22 01:17:39 2009
@@ -30,7 +30,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Revision$
  */
-public class AssertionNode extends AbstractExprNode
+public abstract class AssertionNode extends AbstractExprNode
 {
     /** The assertion or predicate to apply */
     private final Assertion assertion;
@@ -76,6 +76,17 @@
         set( "count", Long.MAX_VALUE );
     }
 
+    /**
+     * Makes a full clone in new memory space of the current node and children
+     * 
+     * @return the clone
+     */
+    @Override public ExprNode clone()
+    {
+        return (ExprNode)super.clone();
+    }
+    
+
 
     /**
      * Gets the Assertion used by this assertion node.
@@ -89,7 +100,7 @@
 
 
     // ------------------------------------------------------------------------
-    // A B S T R A C T    M E T H O D    I M P L E M E N T A T I O N S
+    // A B S T R A C T M E T H O D I M P L E M E N T A T I O N S
     // ------------------------------------------------------------------------
 
     

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNode.java
Sun Feb 22 01:17:39 2009
@@ -100,6 +100,29 @@
         return false;
     }
 
+    /**
+     * Makes a full clone in new memory space of the current node and children
+     * 
+     * @return the clone
+     */
+    @Override public ExprNode clone()
+    {
+        ExprNode clone = (ExprNode)super.clone();
+        
+        // Clone the children
+        if ( children != null )
+        {
+            ((BranchNode)clone).children = new ArrayList<ExprNode>();
+            
+            for ( ExprNode child : children )
+            {
+                ((BranchNode)clone).children.add( (ExprNode)child.clone() );
+            }
+        }
+        
+        return clone;
+    }
+
 
     /**
      * Adds a child node to this branch node node

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitor.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitor.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitor.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitor.java
Sun Feb 22 01:17:39 2009
@@ -52,11 +52,6 @@
 
         BranchNode branch = ( BranchNode ) node;
 
-        if ( branch instanceof NotNode )
-        {
-            return null;
-        }
-
         Comparator<ExprNode> nodeComparator = new NodeComparator();
 
         Set<ExprNode> set = new TreeSet<ExprNode>( nodeComparator );

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/EqualityNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/EqualityNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/EqualityNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/EqualityNode.java
Sun Feb 22 01:17:39 2009
@@ -42,6 +42,16 @@
         super( attribute, value, AssertionType.EQUALITY );
     }
 
+    /**
+     * Makes a full clone in new memory space of the current node and children
+     * 
+     * @return the clone
+     */
+    @Override public ExprNode clone()
+    {
+        return super.clone();
+    }
+
 
     /**
      * Creates a new Equality object.

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExprNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExprNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExprNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExprNode.java
Sun Feb 22 01:17:39 2009
@@ -28,7 +28,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Revision$
  */
-public interface ExprNode
+public interface ExprNode extends Cloneable
 {
     /**
      * Gets an annotation on the tree by key.
@@ -86,4 +86,11 @@
      * @return the modified element
      */
     Object accept( FilterVisitor visitor );
+    
+    
+    /**
+     * Clone the object
+     * @return
+     */
+    ExprNode clone();
 }

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExtensibleNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExtensibleNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExtensibleNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExtensibleNode.java
Sun Feb 22 01:17:39 2009
@@ -93,6 +93,23 @@
         this.dnAttributes = dnAttributes;
     }
 
+    /**
+     * Makes a full clone in new memory space of the current node and children
+     * 
+     * @return the clone
+     */
+    @Override public ExprNode clone()
+    {
+        ExprNode clone = (ExprNode)super.clone();
+        
+        // Copy the value
+        if ( value != null )
+        {
+            ((ExtensibleNode)clone).value = value.clone();
+        }
+        
+        return clone;
+    }
 
     /**
      * Gets the Dn attributes.

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/GreaterEqNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/GreaterEqNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/GreaterEqNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/GreaterEqNode.java
Sun Feb 22 01:17:39 2009
@@ -42,6 +42,15 @@
         super( attribute, value, AssertionType.GREATEREQ );
     }
 
+    /**
+     * Makes a full clone in new memory space of the current node and children
+     * 
+     * @return the clone
+     */
+    @Override public ExprNode clone()
+    {
+        return super.clone();
+    }
 
     /**
      * @see Object#toString()

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LeafNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LeafNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LeafNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LeafNode.java
Sun Feb 22 01:17:39 2009
@@ -43,7 +43,17 @@
         super( assertionType );
         this.attribute = attribute;
     }
-
+    
+    /**
+     * Makes a full clone in new memory space of the current node and children
+     * 
+     * @return the clone
+     */
+    @Override public ExprNode clone()
+    {
+        return super.clone();
+    }
+    
 
     /**
      * Gets whether this node is a leaf - the answer is always true here.
@@ -135,7 +145,7 @@
         {
             return false;
         }
-
+            
         return attribute.equals( ( ( LeafNode ) other ).getAttribute() );
     }
 }

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LessEqNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LessEqNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LessEqNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LessEqNode.java
Sun Feb 22 01:17:39 2009
@@ -33,7 +33,7 @@
 {
     /**
      * Creates a new LessEqNode object.
-     *
+     * 
      * @param attribute the attribute name
      * @param value the value to test for
      */
@@ -42,6 +42,15 @@
         super( attribute, value, AssertionType.LESSEQ );
     }
 
+    /**
+     * Makes a full clone in new memory space of the current node and children
+     * 
+     * @return the clone
+     */
+    @Override public ExprNode clone()
+    {
+        return super.clone();
+    }
 
     /**
      * @see Object#toString()

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/NotNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/NotNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/NotNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/NotNode.java
Sun Feb 22 01:17:39 2009
@@ -64,6 +64,16 @@
         }
     }
 
+    
+    /**
+     * Clone the Node
+     */
+    @Override public ExprNode clone()
+    {
+        return super.clone();
+    }
+    
+
 
     /**
      * Creates an empty NotNode

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/OrNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/OrNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/OrNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/OrNode.java
Sun Feb 22 01:17:39 2009
@@ -52,6 +52,15 @@
         super( AssertionType.OR, childList );
     }
 
+    
+    /**
+     * Clone the Node
+     */
+    @Override public ExprNode clone()
+    {
+        return super.clone();
+    }
+
 
     /**
      * Creates an empty OrNode

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/PresenceNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/PresenceNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/PresenceNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/PresenceNode.java
Sun Feb 22 01:17:39 2009
@@ -39,6 +39,14 @@
         super( attribute, AssertionType.PRESENCE );
     }
 
+    
+    /**
+     * Clone the Node
+     */
+    @Override public ExprNode clone()
+    {
+        return super.clone();
+    }
 
     /**
      * @see java.lang.Object#toString()

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ScopeNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ScopeNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ScopeNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ScopeNode.java
Sun Feb 22 01:17:39 2009
@@ -57,6 +57,16 @@
         this.aliasDerefAliases = aliasDerefAliases;
     }
 
+    /**
+     * Makes a full clone in new memory space of the current node and children
+     * 
+     * @return the clone
+     */
+    @Override public ExprNode clone()
+    {
+        return super.clone();
+    }    
+
 
     /**
      * Always returns true since a scope node has no children.

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SimpleNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SimpleNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SimpleNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SimpleNode.java
Sun Feb 22 01:17:39 2009
@@ -57,6 +57,20 @@
         this.value = value;
     }
 
+    
+    /**
+     * Clone the Node
+     */
+    @Override public ExprNode clone()
+    {
+        ExprNode clone = super.clone();
+        
+        // Clone the value
+        ((SimpleNode<T>)clone).value = value.clone(); 
+        
+        return clone;
+    }
+
 
     /**
      * Gets the value.

Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SubstringNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SubstringNode.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SubstringNode.java
(original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SubstringNode.java
Sun Feb 22 01:17:39 2009
@@ -64,6 +64,26 @@
         this.initialPattern = initialPattern;
     }
 
+    
+    /**
+     * Clone the Node
+     */
+    @Override public ExprNode clone()
+    {
+        ExprNode clone = (ExprNode)super.clone();
+        
+        if ( anyPattern != null )
+        {
+            ((SubstringNode)clone).anyPattern = new ArrayList<String>();
+            
+            for ( String any:anyPattern )
+            {
+                ((SubstringNode)clone).anyPattern.add( any );
+            }
+        }
+        
+        return clone;
+    }
 
     /**
      * Creates a new SubstringNode object without any value

Modified: directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitorTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitorTest.java?rev=746607&r1=746606&r2=746607&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitorTest.java
(original)
+++ directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitorTest.java
Sun Feb 22 01:17:39 2009
@@ -114,4 +114,20 @@
 
         assertEquals( normalizedFilter1, normalizedFilter2 );
     }
+
+   public void testBranchNormalizedVisitor4() throws Exception
+   {
+       ExprNode ori = FilterParser.parse( "(&(!(sn=Bob))(ou=Human Resources)(uid=akarasulu))"
);
+
+       ExprNode altered = FilterParser.parse( "(&(ou=Human Resources)(uid=akarasulu)(!(sn=Bob)))"
);
+
+       BranchNormalizedVisitor visitor = new BranchNormalizedVisitor();
+
+       visitor.visit( altered );
+
+       assertTrue( ori.toString().equals( altered.toString() ) );
+       
+   }
+     
+    
 }

Added: directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterCloneTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterCloneTest.java?rev=746607&view=auto
==============================================================================
--- directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterCloneTest.java
(added)
+++ directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterCloneTest.java
Sun Feb 22 01:17:39 2009
@@ -0,0 +1,537 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.filter;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.text.ParseException;
+
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.junit.Test;
+
+
+/**
+ * Tests the FilterParserImpl class.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 575783 $
+ */
+public class FilterCloneTest
+{
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testItemFilter() throws ParseException
+    {
+        SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou~=people)" );
+        // just check that it doesnt throw for now
+        node = (SimpleNode)node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertEquals( "people", node.getValue().get() );
+        assertTrue( node instanceof ApproximateNode );
+    }
+
+    
+    @Test
+    public void testAndFilter() throws ParseException
+    {
+        BranchNode node = ( BranchNode ) FilterParser.parse( "(&(ou~=people)(age>=30))"
);
+        // just check that it doesnt throw for now
+        node = (BranchNode) node.clone();
+        assertEquals( 2, node.getChildren().size() );
+        assertTrue( node instanceof AndNode );
+    }
+
+    
+    @Test
+    public void testAndFilterOneChildOnly() throws ParseException
+    {
+        BranchNode node = ( BranchNode ) FilterParser.parse( "(&(ou~=people))" );
+        // just check that it doesnt throw for now
+        node = (BranchNode)node.clone();
+        assertEquals( 1, node.getChildren().size() );
+        assertTrue( node instanceof AndNode );
+    }
+
+
+    @Test
+    public void testOrFilter() throws ParseException
+    {
+        BranchNode node = ( BranchNode ) FilterParser.parse( "(|(ou~=people)(age>=30))"
);
+        // just check that it doesnt throw for now
+        node = (BranchNode)node.clone();
+        assertEquals( 2, node.getChildren().size() );
+        assertTrue( node instanceof OrNode );
+    }
+
+
+    @Test
+    public void testOrFilterOneChildOnly() throws ParseException
+    {
+        BranchNode node = ( BranchNode ) FilterParser.parse( "(|(age>=30))" );
+        // just check that it doesnt throw for now
+        node = (BranchNode) node.clone();
+        assertEquals( 1, node.getChildren().size() );
+        assertTrue( node instanceof OrNode );
+    }
+
+
+    @Test
+    public void testNotFilter() throws ParseException
+    {
+        BranchNode node = ( BranchNode ) FilterParser.parse( "(!(&(ou~= people)(age>=30)))"
);
+        // just check that it doesnt throw for now
+        node = (BranchNode)node.clone();
+        assertEquals( 1, node.getChildren().size() );
+        assertTrue( node instanceof NotNode );
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testOptionAndEscapesFilter() throws ParseException
+    {
+        SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou;lang-de>=\\23\\42asdl
fkajsd)" );
+        // just check that it doesnt throw for now
+        node = (SimpleNode)node.clone();
+        assertEquals( "ou;lang-de", node.getAttribute() );
+        assertEquals( "\\23\\42asdl fkajsd", node.getValue().get() );
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testOptionsAndEscapesFilter() throws ParseException
+    {
+        SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou;lang-de;version-124>=\\23\\42asdl
fkajsd)" );
+        // just check that it doesnt throw for now
+        node = (SimpleNode)node.clone();
+        assertEquals( "ou;lang-de;version-124", node.getAttribute() );
+        assertEquals( "\\23\\42asdl fkajsd", node.getValue().get() );
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testNumericoidOptionsAndEscapesFilter() throws ParseException
+    {
+        SimpleNode node = ( SimpleNode ) FilterParser.parse( "(1.3.4.2;lang-de;version-124>=\\23\\42asdl
fkajsd)" );
+        // just check that it doesnt throw for now
+        node = (SimpleNode)node.clone();
+        assertEquals( "1.3.4.2;lang-de;version-124", node.getAttribute() );
+        assertEquals( "\\23\\42asdl fkajsd", node.getValue().get() );
+    }
+
+
+    @Test
+    public void testPresentFilter() throws ParseException
+    {
+        PresenceNode node = ( PresenceNode ) FilterParser.parse( "(ou=*)" );
+        // just check that it doesnt throw for now
+        node = (PresenceNode) node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof PresenceNode );
+    }
+
+
+    @Test
+    public void testNumericoidPresentFilter() throws ParseException
+    {
+        PresenceNode node = ( PresenceNode ) FilterParser.parse( "(1.2.3.4=*)" );
+        // just check that it doesnt throw for now
+        node = ( PresenceNode )node.clone();
+        assertEquals( "1.2.3.4", node.getAttribute() );
+        assertTrue( node instanceof PresenceNode );
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testEqualsFilter() throws ParseException
+    {
+        SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou=people)" );
+        // just check that it doesnt throw for now
+        node = ( SimpleNode) node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertEquals( "people", node.getValue().get() );
+        assertTrue( node instanceof EqualityNode );
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testEqualsWithForwardSlashFilter() throws ParseException
+    {
+        SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou=people/in/my/company)"
);
+        // just check that it doesnt throw for now
+        node = (SimpleNode) node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertEquals( "people/in/my/company", node.getValue().get() );
+        assertTrue( node instanceof EqualityNode );
+    }
+
+
+    @Test
+    public void testExtensibleFilterForm1() throws ParseException
+    {
+        ExtensibleNode node = ( ExtensibleNode ) FilterParser.parse( "(ou:dn:stupidMatch:=dummyAssertion\\23\\ac)"
);
+        // just check that it doesnt throw for now
+        node = ( ExtensibleNode ) node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertEquals( "dummyAssertion\\23\\ac", StringTools.utf8ToString( node.getValue()
) );
+        assertEquals( "stupidMatch", node.getMatchingRuleId() );
+        assertTrue( node.hasDnAttributes() );
+        assertTrue( node instanceof ExtensibleNode );
+    }
+
+
+    @Test
+    public void testExtensibleFilterForm1WithNumericOid() throws ParseException
+    {
+        ExtensibleNode node = ( ExtensibleNode ) FilterParser.parse( "(1.2.3.4:dn:1.3434.23.2:=dummyAssertion\\23\\ac)"
);
+        // just check that it doesnt throw for now
+        node = ( ExtensibleNode )node.clone();
+        assertEquals( "1.2.3.4", node.getAttribute() );
+        assertEquals( "dummyAssertion\\23\\ac", StringTools.utf8ToString( node.getValue()
) );
+        assertEquals( "1.3434.23.2", node.getMatchingRuleId() );
+        assertTrue( node.hasDnAttributes() );
+        assertTrue( node instanceof ExtensibleNode );
+    }
+
+
+    @Test
+    public void testExtensibleFilterForm1NoDnAttr() throws ParseException
+    {
+        ExtensibleNode node = ( ExtensibleNode ) FilterParser.parse( "(ou:stupidMatch:=dummyAssertion\\23\\ac)"
);
+        // just check that it doesnt throw for now
+        node = ( ExtensibleNode ) node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertEquals( "dummyAssertion\\23\\ac", StringTools.utf8ToString( node.getValue()
) );
+        assertEquals( "stupidMatch", node.getMatchingRuleId() );
+        assertFalse( node.hasDnAttributes() );
+        assertTrue( node instanceof ExtensibleNode );
+    }
+
+
+ 
+    @Test
+    public void testExtensibleFilterForm1NoAttrNoMatchingRule() throws ParseException
+    {
+        ExtensibleNode node = ( ExtensibleNode ) FilterParser.parse( "(ou:=dummyAssertion\\23\\ac)"
);
+        // just check that it doesnt throw for now
+        node = (ExtensibleNode) node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertEquals( "dummyAssertion\\23\\ac", StringTools.utf8ToString( node.getValue()
) );
+        assertEquals( null, node.getMatchingRuleId() );
+        assertFalse( node.hasDnAttributes() );
+        assertTrue( node instanceof ExtensibleNode );
+    }
+
+
+    @Test
+    public void testExtensibleFilterForm2() throws ParseException
+    {
+        ExtensibleNode node = ( ExtensibleNode ) FilterParser.parse( "(:dn:stupidMatch:=dummyAssertion\\23\\ac)"
);
+        // just check that it doesnt throw for now
+        node = ( ExtensibleNode ) node.clone();
+        assertEquals( null, node.getAttribute() );
+        assertEquals( "dummyAssertion\\23\\ac", StringTools.utf8ToString( node.getValue()
) );
+        assertEquals( "stupidMatch", node.getMatchingRuleId() );
+        assertTrue( node.hasDnAttributes() );
+        assertTrue( node instanceof ExtensibleNode );
+    }
+
+
+    @Test
+    public void testExtensibleFilterForm2WithNumericOid() throws ParseException
+    {
+        ExtensibleNode node = ( ExtensibleNode ) FilterParser.parse( "(:dn:1.3434.23.2:=dummyAssertion\\23\\ac)"
);
+        assertEquals( null, node.getAttribute() );
+        assertEquals( "dummyAssertion\\23\\ac", StringTools.utf8ToString( node.getValue()
) );
+        assertEquals( "1.3434.23.2", node.getMatchingRuleId() );
+        assertTrue( node.hasDnAttributes() );
+        assertTrue( node instanceof ExtensibleNode );
+    }
+
+
+    @Test
+    public void testExtensibleFilterForm2NoDnAttr() throws ParseException
+    {
+        ExtensibleNode node1 = ( ExtensibleNode ) FilterParser.parse( "(:stupidMatch:=dummyAssertion\\23\\ac)"
);
+        // just check that it doesnt throw for now
+        ExtensibleNode node = ( ExtensibleNode )node1.clone();
+        assertEquals( null, node.getAttribute() );
+        assertEquals( "dummyAssertion\\23\\ac", StringTools.utf8ToString( node.getValue()
) );
+        assertEquals( "stupidMatch", node.getMatchingRuleId() );
+        assertFalse( node.hasDnAttributes() );
+        assertTrue( node instanceof ExtensibleNode );
+    }
+
+
+    @Test
+    public void testExtensibleFilterForm2NoDnAttrWithNumericOidNoAttr() throws ParseException
+    {
+        ExtensibleNode node = ( ExtensibleNode ) FilterParser.parse( "(:1.3434.23.2:=dummyAssertion\\23\\ac)"
);
+        // just check that it doesnt throw for now
+        node = ( ExtensibleNode) node.clone();
+        assertEquals( null, node.getAttribute() );
+        assertEquals( "dummyAssertion\\23\\ac", StringTools.utf8ToString( node.getValue()
) );
+        assertEquals( "1.3434.23.2", node.getMatchingRuleId() );
+        assertFalse( node.hasDnAttributes() );
+        assertTrue( node instanceof ExtensibleNode );
+    }
+
+
+    @Test
+    public void testSubstringNoAnyNoFinal() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=foo*)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode ) node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 0, node.getAny().size() );
+        assertFalse( node.getAny().contains( "" ) );
+        assertEquals( "foo", node.getInitial() );
+        assertEquals( null, node.getFinal() );
+    }
+
+
+    @Test
+    public void testSubstringNoAny() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=foo*bar)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode ) node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 0, node.getAny().size() );
+        assertFalse( node.getAny().contains( "" ) );
+        assertEquals( "foo", node.getInitial() );
+        assertEquals( "bar", node.getFinal() );
+    }
+
+
+    @Test
+    public void testSubstringNoAnyNoIni() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=*bar)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode )node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 0, node.getAny().size() );
+        assertFalse( node.getAny().contains( "" ) );
+        assertEquals( null, node.getInitial() );
+        assertEquals( "bar", node.getFinal() );
+    }
+
+
+    @Test
+    public void testSubstringOneAny() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=foo*guy*bar)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode )node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 1, node.getAny().size() );
+        assertFalse( node.getAny().contains( "" ) );
+        assertTrue( node.getAny().contains( "guy" ) );
+        assertEquals( "foo", node.getInitial() );
+        assertEquals( "bar", node.getFinal() );
+    }
+
+
+    @Test
+    public void testSubstringManyAny() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=a*b*c*d*e*f)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode )node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 4, node.getAny().size() );
+        assertFalse( node.getAny().contains( "" ) );
+        assertTrue( node.getAny().contains( "b" ) );
+        assertTrue( node.getAny().contains( "c" ) );
+        assertTrue( node.getAny().contains( "d" ) );
+        assertTrue( node.getAny().contains( "e" ) );
+        assertEquals( "a", node.getInitial() );
+        assertEquals( "f", node.getFinal() );
+    }
+
+
+    @Test
+    public void testSubstringNoIniManyAny() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=*b*c*d*e*f)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode )node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 4, node.getAny().size() );
+        assertFalse( node.getAny().contains( "" ) );
+        assertTrue( node.getAny().contains( "e" ) );
+        assertTrue( node.getAny().contains( "b" ) );
+        assertTrue( node.getAny().contains( "c" ) );
+        assertTrue( node.getAny().contains( "d" ) );
+        assertEquals( null, node.getInitial() );
+        assertEquals( "f", node.getFinal() );
+    }
+
+
+    @Test
+    public void testSubstringManyAnyNoFinal() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=a*b*c*d*e*)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode )node.clone();
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 4, node.getAny().size() );
+        assertFalse( node.getAny().contains( "" ) );
+        assertTrue( node.getAny().contains( "e" ) );
+        assertTrue( node.getAny().contains( "b" ) );
+        assertTrue( node.getAny().contains( "c" ) );
+        assertTrue( node.getAny().contains( "d" ) );
+        assertEquals( "a", node.getInitial() );
+        assertEquals( null, node.getFinal() );
+    }
+
+
+    @Test
+    public void testSubstringNoIniManyAnyNoFinal() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=*b*c*d*e*)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode ) node.clone();
+        
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 4, node.getAny().size() );
+        assertFalse( node.getAny().contains( "" ) );
+        assertTrue( node.getAny().contains( "e" ) );
+        assertTrue( node.getAny().contains( "b" ) );
+        assertTrue( node.getAny().contains( "c" ) );
+        assertTrue( node.getAny().contains( "d" ) );
+        assertEquals( null, node.getInitial() );
+        assertEquals( null, node.getFinal() );
+    }
+
+
+    @Test
+    public void testSubstringNoAnyDoubleSpaceStar() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=foo* *bar)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode )node.clone();
+        
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 1, node.getAny().size() );
+        assertFalse( node.getAny().contains( "" ) );
+        assertTrue( node.getAny().contains( " " ) );
+        assertEquals( "foo", node.getInitial() );
+        assertEquals( "bar", node.getFinal() );
+    }
+
+
+    @Test
+    public void testSubstringAnyDoubleSpaceStar() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=foo* a *bar)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode ) node.clone();
+        
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 1, node.getAny().size() );
+        assertFalse( node.getAny().contains( "" ) );
+        assertTrue( node.getAny().contains( " a " ) );
+        assertEquals( "foo", node.getInitial() );
+        assertEquals( "bar", node.getFinal() );
+    }
+
+
+    /**
+     * Enrique just found this bug with the filter parser when parsing substring
+     * expressions like *any*. Here's the JIRA issue: <a
+     * href="http://nagoya.apache.org/jira/browse/DIRLDAP-21">DIRLDAP-21</a>.
+     */
+    @Test
+    public void testSubstringStarAnyStar() throws ParseException
+    {
+        SubstringNode node = ( SubstringNode ) FilterParser.parse( "(ou=*foo*)" );
+        // just check that it doesnt throw for now
+        node = ( SubstringNode )node.clone();
+        
+        assertEquals( "ou", node.getAttribute() );
+        assertTrue( node instanceof SubstringNode );
+        assertEquals( 1, node.getAny().size() );
+        assertTrue( node.getAny().contains( "foo" ) );
+        assertNull( node.getInitial() );
+        assertNull( node.getFinal() );
+    }
+    
+    
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testEqualsFilterNullValue() throws ParseException
+    {
+        SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou=)" );
+        // just check that it doesnt throw for now
+        node = ( SimpleNode )node.clone();
+        
+        assertEquals( "ou", node.getAttribute() );
+        assertEquals( "", node.getValue().get() );
+        assertTrue( node instanceof EqualityNode );
+    }
+
+
+    /**
+     * test a filter with a # in value
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testEqualsFilterWithPoundInValue() throws ParseException
+    {
+        SimpleNode node = ( SimpleNode ) FilterParser.parse( "(uid=#f1)" );
+        // just check that it doesnt throw for now
+        node = ( SimpleNode ) node.clone();
+        assertEquals( "uid", node.getAttribute() );
+        assertEquals( "#f1", node.getValue().get() );
+        assertTrue( node instanceof EqualityNode );
+    }
+
+    
+    @Test
+    public void testLargeBusyFilter() throws ParseException
+    {
+        ExprNode node1 = FilterParser.parse( "(&(|(2.5.4.3=h*)(2.5.4.4=h*)(2.16.840.1.113730.3.1.241=h*)(2.5.4.42=h*))(!(objectClass=computer))(|(objectClass=person)(objectClass=group)(objectClass=organizationalUnit)(objectClass=domain))(!(&(userAccountControl:1.2.840.113556.1.4.803:=2))))"
);
+        // just check that it doesnt throw for now
+        ExprNode node = node1.clone();
+        assertTrue(node instanceof AndNode);
+        //TODO test full structure
+    }
+}



Mime
View raw message