Author: gvanmatre
Date: Fri Sep  2 21:36:40 2005
New Revision: 267417

URL: http://svn.apache.org/viewcvs?rev=267417&view=rev
Log:
Bug#:  35839 [shale] Clay processes components inside HTML comments

Modified:
    
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/parser/Parser.java
    
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/parser/ParserTestCase.java

Modified: 
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/parser/Parser.java
URL: 
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/parser/Parser.java?rev=267417&r1=267416&r2=267417&view=diff
==============================================================================
--- 
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/parser/Parser.java
 (original)
+++ 
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/parser/Parser.java
 Fri Sep  2 21:36:40 2005
@@ -436,60 +436,115 @@
     }
     
     /**
+     * <p>Declare an array of [EMAIL PROTECTED] Rule}s that validate an ending 
[EMAIL PROTECTED] Token}.</p>
+     */
+    private static Rule[] END_TAG_RULES = {new Rule('<', true, 0, true),  
+        new Rule('/', true, 1, true),
+        new Rule('>', false, -1, true)};
+    
+    /**
+     * <p>Declare an array of [EMAIL PROTECTED] Rule}s that validate self 
terminating [EMAIL PROTECTED] Token}.</p>
+     */
+    private static Rule[] SELF_TERM_TAG_RULES = {new Rule('<', true, 0, true),
+        new Rule('/', false, -2, true),
+        new Rule('>', false, -1, true)};
+    /**
+     * <p>Declare an array of [EMAIL PROTECTED] Rule}s that validate self 
contained comment [EMAIL PROTECTED] Token}.</p>
+     */    
+    private static Rule[] SELF_CONTAINED_COMMENT_RULES = {new Rule('<', true, 
0, true),
+        new Rule('!', true, 1, true),
+        new Rule('-', true, 2, true),
+        new Rule('-', true, 3, true),
+        new Rule('>', false, -1, true),
+        new Rule('-', false, -2, true),
+        new Rule('-', false, -3, true),
+        new Rule(' ', false, -4, true)};
+    
+    /**
+     * <p>Declare an array of [EMAIL PROTECTED] Rule}s that validate a begin 
comment [EMAIL PROTECTED] Token}.</p>
+     */    
+    public static Rule[] BEGIN_COMMENT_TAG_RULES = {new Rule('<', true, 0, 
true),
+        new Rule('!', true, 1, true),
+        new Rule('-', true, 2, true),
+        new Rule('-', true, 3, true)};
+    
+    /**
+     * <p>Declare an array of [EMAIL PROTECTED] Rule}s that validate an end 
comment [EMAIL PROTECTED] Token}.</p>
+     */    
+    public static Rule[] END_COMMENT_TAG_RULES = {new Rule('>', false, -1, 
true),
+        new Rule('-', false, -2, true),
+        new Rule('-', false, -3, true),
+        new Rule(' ', false, -4, true)};
+    
+    /**
+     * <p>Declare an array of [EMAIL PROTECTED] Rule}s that validate document 
type [EMAIL PROTECTED] Token}.</p>
+     */    
+    public static Rule[] DOCTYPE_TAG_RULES = {new Rule('<', true, 0, true),
+        new Rule('!', true, 1, true),
+        new Rule('>', false, -1, true)};
+    
+    /**
+     * <p>Declare an array of [EMAIL PROTECTED] Rule}s that validate a 
begining [EMAIL PROTECTED] Token}.</p>
+     */        
+    public static Rule[] BEGIN_TAG_RULES = {new Rule('<', true, 0, true),
+        new Rule('-', true, 1, false),
+        new Rule('/', true, 1, false),
+        new Rule('?', true, 1, false),
+        new Rule('%', true, 1, false),
+        new Rule('>', false, -1, true)};
+    
+    /**
+     * <p>Declare an array of [EMAIL PROTECTED] Shape}s further defined by 
[EMAIL PROTECTED] Rule}s that 
+     * are used to determine the type of [EMAIL PROTECTED] Node} the [EMAIL 
PROTECTED] Token} defines.</p>
+     */
+    private static Shape[] NODE_SHAPES = {
+        new Shape(false, true, false, END_TAG_RULES),
+        new Shape(true, true, false, SELF_TERM_TAG_RULES),
+        new Shape(true, true, true, SELF_CONTAINED_COMMENT_RULES),
+        new Shape(true, false, true, BEGIN_COMMENT_TAG_RULES),
+        new Shape(false, true, true, END_COMMENT_TAG_RULES),
+        new Shape(true, true, true, DOCTYPE_TAG_RULES),
+        new Shape(true, false, false, BEGIN_TAG_RULES)};
+    
+    
+    /**
      * <p>Determine if the [EMAIL PROTECTED] Node} is a starting, ending, or 
body text
-     * tag.</p>
+     * tag. The array of [EMAIL PROTECTED] Shape}s are used to determine the 
type of 
+     * [EMAIL PROTECTED] Node} the [EMAIL PROTECTED] Token} representes.</p>
      */
     protected void discoverNodeShape(Node node) {
         Token token = node.getToken();
         
-        if (token.getDocument().charAt(token.getBeginOffset()) == '<'
-            && token.getDocument().charAt(token.getBeginOffset() + 1) == '/'
-                && token.getDocument().charAt(token.getEndOffset() - 1) == 
'>') {
-            // ending tag found
-            node.setEnd(true);
-            node.setStart(false);
-        } else if (token.getDocument().charAt(token.getBeginOffset()) == '<'
-            && token.getDocument().charAt(token.getEndOffset() - 2) == '/'
-                && token.getDocument().charAt(token.getEndOffset() - 1) == 
'>') {
-            // self ending tag found
-            node.setEnd(true);
-            node.setStart(true);
-        } else if (token.getDocument().charAt(token.getBeginOffset()) == '<'
-            && token.getDocument().charAt(token.getBeginOffset() + 1) == '!'
-                && token.getDocument().charAt(token.getEndOffset() - 2) == '-'
-                    && token.getDocument().charAt(token.getEndOffset() - 1) == 
'>') {
-            // self contained comment tag found
-            node.setEnd(true);
-            node.setStart(true);
-            node.setComment(true);
-        } else if (token.getDocument().charAt(token.getBeginOffset()) == '<'
-            && token.getDocument().charAt(token.getBeginOffset() + 1) == '!'
-                && token.getDocument().charAt(token.getBeginOffset() + 2) == 
'-') {
-            // begin comment tag found
-            node.setEnd(false);
-            node.setStart(true); 
-            node.setComment(true);      
-        } else if (token.getDocument().charAt(token.getEndOffset() - 2) == '-'
-            && token.getDocument().charAt(token.getEndOffset() - 1) == '>') {
-            // ending comment tag found
-            node.setEnd(true);
-            node.setStart(false);
-            node.setComment(true);
-        } else if (token.getDocument().charAt(token.getBeginOffset()) == '<'
-            && token.getDocument().charAt(token.getBeginOffset() + 1) == '!'
-                && token.getDocument().charAt(token.getEndOffset() - 1) == 
'>') {
-            // DOCTYPE is treated like a self contained comment
-            node.setEnd(true);
-            node.setStart(true);
-            node.setComment(true);        
-        } else if (token.getDocument().charAt(token.getBeginOffset()) == '<'
-            && (token.getDocument().charAt(token.getBeginOffset() + 1) != '/'
-                && token.getDocument().charAt(token.getBeginOffset() + 1) != 
'?' 
-                    && token.getDocument().charAt(token.getBeginOffset() + 1) 
!= '%')
-                    && token.getDocument().charAt(token.getEndOffset() - 1) == 
'>') {
-            // beginning tag found
-            node.setEnd(false);
-            node.setStart(true);
+        nextShape: for (int i = 0; i < NODE_SHAPES.length; i++) {
+            
+            Shape shape = NODE_SHAPES[i];
+            
+            Rule[] rules = shape.getRules();
+            for (int j = 0; j < rules.length; j++ ) {
+                
+                // use the begin or end token offset 
+                int n = (rules[j].isBegin ? token.getBeginOffset() : 
token.getEndOffset()) + rules[j].getOffset();
+                
+                // if out of document range, look for the next shape
+                if (n > token.getDocument().length() || n < 0) 
+                    continue nextShape;
+                
+                // check the operator
+                boolean match = false;
+                if (rules[j].isEqual) 
+                    match = (token.getDocument().charAt(n) ==  
rules[j].getMnemonic());
+                else
+                    match = (token.getDocument().charAt(n) !=  
rules[j].getMnemonic());  
+                
+                if (!match) 
+                    continue nextShape;    
+            }
+            
+            node.setStart(shape.isStart());
+            node.setEnd(shape.isEnd());
+            node.setComment(shape.isComment());
+            
+            break nextShape;
         }
         
     }
@@ -581,4 +636,145 @@
         
     }
  
+    /**
+     * <p>Defines a parsing [EMAIL PROTECTED] Rule} used to determine
+     * the [EMAIL PROTECTED] Shape} of a [EMAIL PROTECTED] Node}.</p>
+     */
+    static class Rule {
+        /**
+         * <p>The target char to check for in the [EMAIL PROTECTED] Token} 
document.</p>
+         */
+        private char mnemonic = ' ';
+        
+        /**
+         * <p>A boolen flag that indicates if the <code>offset</code> is from 
+         * the begining of the [EMAIL PROTECTED] Token} offset or the ending 
offset.</p>
+         */
+        private boolean isBegin = false;
+        
+        /**
+         * <p>The offset from the start or end of the [EMAIL PROTECTED] Token} 
that the 
+         * <code>mnemonic</code> should be found.</p>
+         */
+        private int offset = 0;
+        /**
+         * <p>A boolean value that determines the relational operator used
+         * to compare the <code>mnemonic</code> to the [EMAIL PROTECTED] 
Token} begin
+         * or ending offset plus the [EMAIL PROTECTED] Rule} offset.  If the 
value
+         * is <code>true</code> the equals operator is used; otherwise,
+         * the not equals operator is used in the comparison.</p>
+         */
+        private boolean isEqual = false;
+        
+        /**
+         * <p>Overloaded constructor for the immutable object.</p> 
+         * @param mnemonic character looked for in the token
+         * @param isBegin boolean that determines if the begining or ending of 
the Token is used
+         * @param offset the offset from the begin or ending Token
+         * @param isEqual boolean that determines if the = or != operator is 
used to check the mnemonic
+         */
+        public Rule(char mnemonic, boolean isBegin, int offset, boolean 
isEqual) {
+            this.mnemonic = mnemonic;
+            this.isBegin = isBegin;
+            this.offset = offset;
+            this.isEqual = isEqual;
+        }
+        /**
+         * <p>Returns the character looked for in the [EMAIL PROTECTED] 
Token}.</p>
+         */
+        public char getMnemonic() {
+            return mnemonic;
+        }
+        /**
+         * <p>Returns <code>true</code> if the <code>mnemonic</code> is at the 
+         * begin or end of the token plus the <code>offset</code>.</p> 
+         */
+        public boolean isBegin() {
+            return isBegin;
+        }
+        /**
+         * <p>Returns a positive or negative offset from the begin or ending
+         * [EMAIL PROTECTED] Token} offset withing the document.</p>
+         */
+        public int getOffset() {
+            return offset;
+        }
+        
+        /**
+         * <p>Returns <code>true</code> if the equal relational operator is 
+         * used for the <code>mnemonic</code> comparison; otherwise the not
+         * equal operator is used.</p>
+         */
+        public boolean IsEqual() {
+            return isEqual;    
+        }
+    }
+    
+    /**
+     * <p>This class defines the shape of the [EMAIL PROTECTED] Node} by 
characterizing 
+     * if the [EMAIL PROTECTED] Token} is a begin, end or comment tag.</p>
+     */
+    static class Shape {
+        
+        /**
+         * <p>If <code>true</code> it indicates a starting node.</p>
+         */
+        private boolean isStart = false;
+        
+        /**
+         * <p>If <code>true</code> it indicates an ending node.</p>
+         */        
+        private boolean isEnd = false;
+        
+        /**
+         * <p>If <code>true</code> it indicates a comment node.</p>
+         */
+        private boolean isComment = false;
+        
+        /**
+         * <p>An array of [EMAIL PROTECTED] Rule}s used to determine if the 
[EMAIL PROTECTED] Node}
+         * matches the [EMAIL PROTECTED] Shape}.</p>
+         */
+        private Rule[] rules = null;
+        
+        /**
+         * <p>Overloaded constructor used to instantiate the immutable 
object.</p> 
+         */
+        public Shape(boolean isStart, boolean isEnd, boolean isComment, Rule[] 
rules) {
+            this.isStart = isStart;
+            this.isEnd = isEnd;
+            this.isComment = isComment;
+            this.rules = rules;
+        }
+        
+        /**
+         * <p>Returns <code>true</code> if the [EMAIL PROTECTED] Token} is a 
starting tag.</p>
+         */
+        public boolean isStart() {
+            return isStart;
+        }
+        /**
+         * <p>Returns <code>true</code> if the [EMAIL PROTECTED] Token} is an 
ending tag.</p>
+         */
+        public boolean isEnd() {
+            return isEnd;   
+        }
+        /**
+         * <p>Returns <code>true</code> if the [EMAIL PROTECTED] Token} is a 
comment tag.</p>
+         */
+        public boolean isComment() {
+            return isComment;    
+        }
+        /**
+         * <p>Returns the [EMAIL PROTECTED] Rule}s that define the 
<code>isStart</code>, 
+         * <code>isEnd</code> and <code>isComment</code> characteristics.</p>
+         */
+        public Rule[] getRules() {
+            return rules;
+        }
+    }
+    
+    
+    
+    
 }

Modified: 
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/parser/ParserTestCase.java
URL: 
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/parser/ParserTestCase.java?rev=267417&r1=267416&r2=267417&view=diff
==============================================================================
--- 
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/parser/ParserTestCase.java
 (original)
+++ 
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/parser/ParserTestCase.java
 Fri Sep  2 21:36:40 2005
@@ -55,12 +55,13 @@
 
         doc1.append("<p><!-- self contained comment -->").append(
                 "<!--<input type=text size=10 maxsize=10 id=username>").append(
-                "<input type=text size=10 maxsize=10 id=password>-->").append(
-                "</p>").append("<!--This is a test.  Just a test-->").append(
-                "<!--<p>Testing <b>123</b></p>-->");
+                "<input type=text size=10 maxsize=10 id=password> -->").append(
+                "</p>").append("<!--This is a test.  Just a test -->").append(
+                "<!--<p>Testing <b>123</b></p> -->" +
+                "<!---> -->");
 
         List nodes1 = p.parse(doc1);
-        assertTrue("Has 3 root nodes", nodes1.size() == 3);
+        assertTrue("Has 4 root nodes", nodes1.size() == 4);
 
         Node node = (Node) nodes1.get(0);
         assertTrue("first paragraph has 2 node", node.getChildren().size() == 
2);
@@ -73,6 +74,11 @@
         assertTrue("third comment has 7 child nodes", node.getChildren()
                 .size() == 7);
 
+        node = (Node) nodes1.get(3);
+        assertTrue("forth comment has 1 child node", node.getChildren()
+                .size() == 1);
+
+        
         // truncate the buffer
         doc1.setLength(0);
         doc1



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to