Package cambridge.model

Source Code of cambridge.model.TagNode

package cambridge.model;

import cambridge.BehaviorInstantiationException;
import cambridge.Cambridge;
import cambridge.behaviors.ConditionalTagBehavior;
import cambridge.DynamicAttributeKey;
import cambridge.ExpressionEvaluationException;
import cambridge.ExpressionParsingException;
import cambridge.LoopingTagBehavior;
import cambridge.ModifyingTagBehavior;
import cambridge.StaticBehavior;
import cambridge.TagBehavior;
import cambridge.TemplateEvaluationException;
import cambridge.TemplateLoader;
import cambridge.TemplateLoadingException;
import cambridge.TemplateParsingException;
import cambridge.behaviors.ForeachBehavior;
import cambridge.behaviors.IfBehavior;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* User: erdincyilmazel
* Date: Aug 17, 2008
* Time: 8:12:49 PM
*/
public class TagNode extends TemplateNode implements Fragment, Tag, ModifyableTag {
   private String indent = "";
   private String tagName;
   protected String nameSpace;

   private String closeText;
   private String tagEndText;

   private ArrayList<TemplateNode> children;
   private ArrayList<TagPart> tagParts;
   private HashMap<AttributeKey, Attribute> attributes;

   private String id;

   private FragmentList fragments;

   private static final Pattern indentPattern = Pattern.compile(".*(\n[ \t]*)$");

   private ArrayList<ModifyingTagBehavior> modifyingBehaviors;
   private ConditionalTagBehavior conditionalBehavior;
   private LoopingTagBehavior looping;

   private boolean dynamic;
   protected boolean hidden;
   private boolean indented = true;

   public TagNode() {
   }

   public String getTextContents() {
      if (children.size() >= 1) {
         TemplateNode n = children.get(0);
         if (n instanceof TextNode) {
            return ((TextNode) n).getContents();
         }
      }

      return "";
   }

   public void removeChild(TemplateNode node) {
      if (children != null) {
         children.remove(node);
      }
   }

   public void replaceChild(TemplateNode search, TemplateNode replace) {
      if (children == null) {
         return;
      }

      int index = children.indexOf(search);
      if (index != -1) {
         children.set(index, replace);
      }
   }

   public void removeAllChildren() {
      if (children != null) {
         children.clear();
      }
      children = null;
   }

   public void removeChild(int index) {
      if (children != null) {
         children.remove(index);
      }
   }

   public void addInclude(TemplateLoader loader, String template, String selector) {
      IncludeNode node = null;
      try {
         node = new IncludeNode(loader, template, selector);
      } catch (BehaviorInstantiationException e) {
         throw new TemplateLoadingException("Could not include " + template, e);
      }
      addChild(node);
   }

   public void addInclude(TemplateLoader loader, String template) {
      addInclude(loader, template, null);
   }

   public void insertChild(TemplateNode node) {
      children.add(0, node);
   }

   public void insertChild(TemplateNode node, int index) {
      children.add(index, node);
   }

   public void insertChild(int index, TemplateNode node) {
      if (children == null) children = new ArrayList<TemplateNode>();
      node.setParent(this);
      children.add(index, node);
   }

   public void addChild(TemplateNode node) {
      if (children == null) children = new ArrayList<TemplateNode>();
      node.setParent(this);
      children.add(node);
   }

   public void setText(String text) {
      if (children == null) {
         children = new ArrayList<TemplateNode>();
      } else {
         children.clear();
      }

      children.add(new TextNode(text));
   }

   public void addChildren(List<TemplateNode> nodes) {
      if (children == null) children = new ArrayList<TemplateNode>();
      for (TemplateNode n : nodes) {
         n.setParent(this);
         children.add(n);
      }
   }

   public ArrayList<TemplateNode> getChildren() {
      return children;
   }

   public boolean hasChildren() {
      return children != null;
   }

   public TemplateNode getPreviousChild(TemplateNode node) {
      if (children == null) return null;
      int i = children.indexOf(node);
      if (i > 0) {
         return children.get(i - 1);
      }
      return null;
   }

   public TemplateNode getNextChild(TemplateNode node) {
      if (children == null) return null;
      int i = children.indexOf(node);
      if (i + 1 < children.size()) {
         return children.get(i + 1);
      }
      return null;
   }

   public ArrayList<Tag> getElementsByTagName(String tagName) {
      ArrayList<Tag> list = new ArrayList<Tag>();
      if (children != null) {
         for (TemplateNode t : children) {
            t.addElementsbyTagName(tagName, list);
         }
      }

      return list;
   }

   public void addTagPart(TagPart e) {
      if (tagParts == null) tagParts = new ArrayList<TagPart>();
      tagParts.add(e);
   }

   public void setTagParts(ArrayList<TagPart> tagParts) {
      this.tagParts = tagParts;
   }

   public void addText(TextTagPart t) {
      addTagPart(t);
   }

   public void addExpression(ExpressionTagPart e) {
      addTagPart(e);
   }

   public Tag addAttribute(Attribute a) {
      if (attributes == null) {
         attributes = new HashMap<AttributeKey, Attribute>();
      }

      AttributeKey key = new AttributeKey(a.getAttributeNameSpace(), a.getAttributeName());

      attributes.put(key, a);

      if ("id".equals(a.getAttributeName())) {
         id = a.getValue();
      }

      Cambridge bindings = Cambridge.getInstance();

      tagParts.add(a);

      if (a.isDynamic()) {
         DynamicAttributeKey attributeKey = new DynamicAttributeKey(a.getNamespaceUri(), a.getAttributeNameSpace(), a.getAttributeName());
         if (bindings.getStaticBehavior(attributeKey) == null) {
            dynamic = true;
         }
      }

      return this;
   }

   public boolean hasAttribute(String namespace, String attributeName) {
      AttributeKey key = new AttributeKey(namespace, attributeName);
      return attributes.containsKey(key);
   }

   public Attribute getAttribute(String namespace, String attributeName) {
      return attributes.get(new AttributeKey(namespace, attributeName));
   }

   public boolean hasAttribute(String attributeName) {
      AttributeKey key = new AttributeKey(null, attributeName);
      return attributes.containsKey(key);
   }

   public Attribute getAttribute(String attributeName) {
      return attributes.get(new AttributeKey(null, attributeName));
   }

   public Attribute getDynamicAttribute(DynamicAttributeKey key) {
      for (Attribute a : attributes.values()) {
         if (a.getAttributeName().equals(key.getAttribute()) &&
            key.getUri().equals(a.getNamespaceUri())) {
            return a;
         }
      }

      return null;
   }

   public List<Attribute> getAttributes() {
      return null;
   }

   public void removeTagPart(int e) {
      if (tagParts != null)
         tagParts.remove(e);
   }

   public String getCloseText() {
      return closeText;
   }

   public void setCloseText(String closeText) {
      this.closeText = closeText;
   }

   public String getTagName() {
      return tagName;
   }

   public void setTagName(String tagName) {
      this.tagName = tagName;
   }

   public String getNameSpace() {
      return nameSpace;
   }

   public void setNameSpace(String nameSpace) {
      this.nameSpace = nameSpace;
   }

   public String tagNameString;

   public void setTagNameString(String tn) {
      tagNameString = tn;
   }

   public String getTagNameString() {
      return tagNameString;
   }

   public String getTagEndText() {
      return tagEndText;
   }

   public void setTagEndText(String tagEndText) {
      this.tagEndText = tagEndText;
   }

   public void setDynamic(Boolean dynamic) {
      this.dynamic = dynamic;
   }

   public boolean isDynamic() {
      return dynamic;
   }

   boolean normalizeUntil(TemplateDocument doc, TemplateNode reference, FragmentList f, boolean inclusive) throws BehaviorInstantiationException {
      if (reference == this) {
         if (inclusive) {
            normalize(doc, f);
         }
         return true;
      } else {
         if (attributes != null) {
            Cambridge bindings = Cambridge.getInstance();
            boolean remove = false;
            HashSet<AttributeKey> staticAttributes = new HashSet<AttributeKey>();

            for (Attribute a : attributes.values()) {
               if (a.isDynamic()) {
                  DynamicAttributeKey key = new DynamicAttributeKey(a.getNamespaceUri(), a.getAttributeNameSpace(), a.getAttributeName());
                  StaticBehavior sb = bindings.getStaticBehavior(key);
                  if (sb != null) {
                     sb.modify(doc, a.getValue(), this);
                     staticAttributes.add(new AttributeKey(a.getAttributeNameSpace(), a.getAttributeName()));
                     if (sb.shouldRemove()) {
                        remove = true;
                     }
                  }
               }
            }

            for (AttributeKey key : staticAttributes) {
               attributes.remove(key);
            }

            if (remove) {
               return false;
            }
         }

         if (isDynamic()) {
            assignBehaviors();

            if (f.current instanceof StaticFragment) {
               StaticFragment st = (StaticFragment) f.current;
               Matcher matcher = indentPattern.matcher(st.contents);
               if (matcher.find()) {
                  indent = matcher.group(1);
                  int length = st.contents.length();
                  st.contents.delete(length - indent.length(), length);
               }
            }

            if (children == null) {
               f.addFragment(this);
            } else {
               fragments = new FragmentList();
               for (TemplateNode t : children) {
                  if (t.normalizeUntil(doc, reference, fragments, inclusive)) {
                     fragments.pack();
                     f.addFragment(this);
                     return true;
                  }
               }

               fragments.pack();

               f.addFragment(this);
            }
         } else {
            f.append("<");
            if (nameSpace != null) {
               f.append(nameSpace).append(":");
            }
            f.append(tagName);

            if (tagParts != null) {
               boolean whiteSpace = false;
               for (TagPart t : tagParts) {
                  if (t instanceof ExpressionTagPart) {
                     f.addFragment((ExpressionTagPart) t);
                  } else {
                     if (!t.isWhiteSpace()) {
                        if (!whiteSpace) {
                           f.append(" ");
                        }
                        whiteSpace = false;
                     } else {
                        whiteSpace = true;
                     }
                     if (t instanceof Attribute) {
                        if (t instanceof SimpleAttribute) {
                           f.append(t.getTextContent());
                        } else if (t instanceof ComplexAttribute) {
                           ComplexAttribute a = (ComplexAttribute) t;
                           if (a.attributeNameSpace != null) {
                              f.append(a.attributeNameSpace).append(":");
                           }

                           f.append(a.attributeName).append("=");
                           char q = a.getQuote();
                           if (q != 0) {
                              f.append("" + q);
                           }

                           for (AttributeFragment af : a.getFragments()) {
                              if (af instanceof StaticFragment) {
                                 f.append(((StaticFragment) af).contents.toString());
                              } else {
                                 f.addFragment(af);
                              }
                           }

                           if (q != 0) {
                              f.append("" + q);
                           }
                        }
                     } else {
                        f.append(t.getTextContent());
                     }
                  }
               }
            }

            f.append(tagEndText);

            if (children != null) {
               for (TemplateNode n : children) {
                  if (n.normalizeUntil(doc, reference, f, inclusive)) {
                     return true;
                  }
               }
            }

            if (closeText != null) {
               f.append(closeText);
            }
         }
         return false;
      }
   }

   @Override
   void normalize(TemplateDocument doc, FragmentList f) throws BehaviorInstantiationException {
      if (attributes != null) {
         Cambridge bindings = Cambridge.getInstance();
         boolean remove = false;
         HashSet<AttributeKey> staticAttributes = new HashSet<AttributeKey>();

         for (Attribute a : attributes.values()) {
            if (a.isDynamic()) {
               DynamicAttributeKey key = new DynamicAttributeKey(a.getNamespaceUri(), a.getAttributeNameSpace(), a.getAttributeName());
               StaticBehavior sb = bindings.getStaticBehavior(key);
               if (sb != null) {
                  sb.modify(doc, a.getValue(), this);
                  staticAttributes.add(new AttributeKey(a.getAttributeNameSpace(), a.getAttributeName()));
                  if (sb.shouldRemove()) {
                     remove = true;
                  }
               }
            }
         }

         for (AttributeKey key : staticAttributes) {
            attributes.remove(key);
         }

         if (remove) {
            return;
         }
      }

      if (isDynamic()) {
         assignBehaviors();

         if (f.current instanceof StaticFragment) {
            StaticFragment st = (StaticFragment) f.current;
            Matcher matcher = indentPattern.matcher(st.contents);
            if (matcher.find()) {
               indent = matcher.group(1);
               int length = st.contents.length();
               st.contents.delete(length - indent.length(), length);
            }
         }

         if (children == null) {
            f.addFragment(this);
         } else {
            fragments = new FragmentList();
            for (TemplateNode t : children) {
               t.normalize(doc, fragments);
            }

            fragments.pack();

            f.addFragment(this);
         }
      } else {
         f.append("<");
         if (nameSpace != null) {
            f.append(nameSpace).append(":");
         }
         f.append(tagName);

         if (tagParts != null) {
            boolean whiteSpace = false;
            for (TagPart t : tagParts) {
               if (t instanceof ExpressionTagPart) {
                  f.addFragment((ExpressionTagPart) t);
               } else {
                  if (t.preserveWhitespace()) {
                     if (!t.isWhiteSpace()) {
                        if (!whiteSpace) {
                           f.append(" ");
                        }
                        whiteSpace = false;
                     } else {
                        whiteSpace = true;
                     }
                  }

                  if (t instanceof Attribute) {
                     if (t instanceof SimpleAttribute) {
                        f.append(t.getTextContent());
                     } else if (t instanceof ComplexAttribute) {
                        ComplexAttribute a = (ComplexAttribute) t;
                        if (a.attributeNameSpace != null) {
                           f.append(a.attributeNameSpace).append(":");
                        }

                        f.append(a.attributeName).append("=");
                        char q = a.getQuote();
                        if (q != 0) {
                           f.append("" + q);
                        }

                        for (AttributeFragment af : a.getFragments()) {
                           if (af instanceof StaticFragment) {
                              f.append(((StaticFragment) af).contents.toString());
                           } else {
                              f.addFragment(af);
                           }
                        }

                        if (q != 0) {
                           f.append("" + q);
                        }
                     }
                  } else {
                     f.append(t.getTextContent());
                  }
               }
            }
         }

         f.append(tagEndText);

         if (children != null) {
            for (TemplateNode n : children) {
               n.normalize(doc, f);
            }
         }

         if (closeText != null) {
            f.append(closeText);
         }
      }
   }

   @Override
   public Tag getElementById(String id) {
      if (this.id != null && this.id.equals(id)) {
         return this;
      }

      if (children != null) {
         for (TemplateNode t : children) {
            Tag n = t.getElementById(id);
            if (n != null) {
               return n;
            }
         }
      }
      return null;
   }

   public Tag addCondition(Expression expression) throws ExpressionParsingException {
      addBehavior(new IfBehavior(expression, getBeginLine(), getBeginColumn()));
      return this;
   }

   public Tag addExpression(Expression expression) throws ExpressionParsingException {
      addChild(new ExpressionNode("", expression));
      return this;
   }

   public Tag iterateOver(Expression expression, String as) throws ExpressionParsingException {
      addBehavior(new ForeachBehavior(expression, as, null, getBeginLine(), getBeginColumn()));
      return this;
   }

   public String toString() {
      return "<" + (nameSpace == null ? tagName : nameSpace + ":" + tagName) + "> @ " + getBeginLine() + ":" + getBeginColumn() + " - " + getEndLine() + ":" + getEndColumn();
   }

   @SuppressWarnings("unchecked")
   public void eval(Map<String, Object> bindings, Writer out) throws IOException, TemplateEvaluationException {
      try {
         if (!isDynamic()) {
            printFragments(bindings, out);
         } else {
            if (conditionsMet(bindings)) {
               if (looping == null) {
                  execute(bindings, out);
               } else {
                  looping.execute(bindings, this, out);
               }
            }
         }
      } catch (ExpressionEvaluationException e) {
         throw new TemplateEvaluationException(e, "Could not execute the expression: " +
                 e.getMessage() + ", on line: " + getBeginLine() + ", column: " +
                 getBeginColumn(), getBeginLine(), getBeginColumn(), getTagName());
      }
   }

   public void pack() {
   }

   public ArrayList<TagPart> getTagParts() {
      return tagParts;
   }

   public String getIndent() {
      return indent;
   }

   public void setIndent(String indent) {
      this.indent = indent;
   }

   public String getId() {
      return id;
   }

   public void setId(String id) {
      this.id = id;
   }

   public boolean isHidden() {
      return hidden;
   }

   public void setHidden(boolean hidden) {
      this.hidden = hidden;
   }

   public boolean isIndented() {
      return indented;
   }

   public void setIndented(boolean indented) {
      this.indented = indented;
   }

   class ModifyableCopy implements ModifyableTag {
      ArrayList<TagPart> tagParts;
      FragmentList fragments;

      ModifyableCopy(ArrayList<TagPart> tagParts, FragmentList fragments) {
         this.tagParts = tagParts;
         this.fragments = fragments;
      }

      public ArrayList<TagPart> getTagParts() {
         return tagParts;
      }

      public void setTagParts(ArrayList<TagPart> tagParts) {
         this.tagParts = tagParts;
      }

      public FragmentList getFragments() {
         return fragments;
      }

      public void setFragments(FragmentList fragments) {
         this.fragments = fragments;
      }
   }

   @SuppressWarnings("unchecked")
   public void execute(Map<String, Object> bindings, Writer out) throws IOException, TemplateEvaluationException {
      ModifyableTag tag;
      if (modifyingBehaviors != null) {
         tag = new ModifyableCopy(tagParts == null ? null : (ArrayList) tagParts.clone(), fragments == null ? null : (FragmentList) fragments.clone());

         for (ModifyingTagBehavior b : modifyingBehaviors) {
            try {
               b.modify(bindings, tag);
            } catch (ExpressionEvaluationException e) {
               throw new TemplateEvaluationException(e, "Could not execute the expression: " +
                       e.getMessage() + ", on line: " + getBeginLine() + ", column: " +
                       getBeginColumn(), getBeginLine(), getBeginColumn(), getTagName());
            }
         }
      } else {
         tag = this;
      }

      if (indented) {
         out.write(indent);
      }

      if (!hidden) {
         out.write("<");
         if (nameSpace != null) {
            out.write(nameSpace);
            out.write(":");
         }
         out.write(tagName);
         if (tag.getTagParts() != null) {
            boolean whiteSpace = false;
            for (TagPart t : tag.getTagParts()) {
               if (t instanceof ExpressionTagPart) {
                  ((ExpressionTagPart) t).eval(bindings, out);
               } else {
                  if (t.preserveWhitespace()) {
                     if (!t.isWhiteSpace()) {
                        if (!whiteSpace) {
                           out.write(" ");
                        }
                        whiteSpace = false;
                     } else {
                        whiteSpace = true;
                     }
                  }

                  if (t instanceof Attribute) {
                     if (t instanceof SimpleAttribute) {
                        out.write(t.getTextContent());
                     } else if (t instanceof ComplexAttribute) {
                        ComplexAttribute a = (ComplexAttribute) t;
                        if (a.attributeNameSpace != null) {
                           out.write(a.attributeNameSpace);
                           out.write(":");
                        }

                        out.write(a.attributeName);
                        out.write("=");
                        char q = a.getQuote();
                        if (q != 0) {
                           out.write("" + q);
                        }

                        for (AttributeFragment af : a.getFragments()) {
                           if (af instanceof StaticFragment) {
                              out.write(((StaticFragment) af).contents.toString());
                           } else if (af instanceof ExpressionNode) {
                              ExpressionNode ex = (ExpressionNode) af;
                              ex.eval(bindings, out);
                           }
                        }

                        if (q != 0) {
                           out.write("" + q);
                        }
                     }
                  } else {
                     out.write(t.getTextContent());
                  }
               }
            }
         }

         out.write(tagEndText);
      }

      if (tag.getFragments() != null) {
         for (Fragment f : tag.getFragments()) {
            f.eval(bindings, out);
         }
      }

      if (!hidden && closeText != null) {
         out.write(closeText);
      }
   }

   @Override
   void addElementsbyTagName(String tagName, ArrayList<Tag> tags) {
      if (tagName.equals(this.tagName)) {
         tags.add(this);
      }
      if (children != null) {
         for (TemplateNode t : children) {
            t.addElementsbyTagName(tagName, tags);
         }
      }
   }

   private boolean conditionsMet(Map<String, Object> bindings) throws ExpressionEvaluationException {
      return conditionalBehavior == null || conditionalBehavior.conditionMet(bindings);
   }

   private void assignBehaviors() throws BehaviorInstantiationException {
      Cambridge bindings = Cambridge.getInstance();
      if (attributes != null) {
         for (Attribute a : attributes.values()) {
            if (a.isDynamic()) {
               DynamicAttributeKey key = new DynamicAttributeKey(a.getNamespaceUri(), a.getAttributeNameSpace(), a.getAttributeName());
               TagBehavior behavior;
               try {
                  behavior = bindings.getBehavior(key, attributes, a.getLine(), a.getColumn());
               } catch (ExpressionParsingException e) {
                  throw new BehaviorInstantiationException("Error in parsing expression", e, getBeginLine(), getBeginColumn());
               }
               if (behavior != null) {
                  addBehavior(behavior);
               }
            }
         }
      }
   }

   public Tag addBehavior(TagBehavior behavior) {
      dynamic = true;
      if (behavior instanceof ConditionalTagBehavior) {
         if (conditionalBehavior != null) {
            throw new TemplateParsingException("Only one conditional behaviour be assigned to a tag. Tag: " + toString(), getBeginLine(), getBeginColumn());
         }
         conditionalBehavior = (ConditionalTagBehavior) behavior;
      } else if (behavior instanceof LoopingTagBehavior) {
         if (looping != null) {
            throw new TemplateParsingException("Only one looping behaviour be assigned to a tag. Tag: " + toString(), getBeginLine(), getBeginColumn());
         }
         looping = (LoopingTagBehavior) behavior;
      } else if (behavior instanceof ModifyingTagBehavior) {
         if (modifyingBehaviors == null) {
            modifyingBehaviors = new ArrayList<ModifyingTagBehavior>();
         }

         modifyingBehaviors.add((ModifyingTagBehavior) behavior);
      }

      return this;
   }

   public ConditionalTagBehavior getConditionalBehavior() {
      return conditionalBehavior;
   }

   public void removeConditionalBehavior() {
      conditionalBehavior = null;
   }

   public ArrayList<Tag> getChildrenByTagName(String tagName) {
      ArrayList<Tag> tags = new ArrayList<Tag>();
      for (TemplateNode t : children) {
         if ((t instanceof Tag) && tagName.equals(((Tag) t).getTagName())) {
            tags.add((Tag) t);
         }
      }

      return tags;
   }

   public Tag get(String tagName, int index) {
      if (children == null) {
         return null;
      }
      Tag tag = null;
      int j = 0;
      for (TemplateNode t : children) {
         if ((t instanceof Tag) && tagName.equals(((Tag) t).getTagName())) {
            if (j == index) {
               return (Tag) t;
            } else {
               tag = (Tag) t;
               j++;
            }
         }
      }

      if (index == -1) {
         return tag;
      }

      return null;
   }

   public Tag getFirst(String tagName) {
      return get(tagName, 0);
   }

   public Tag getLast(String tagName) {
      return get(tagName, -1);
   }

   private void printFragments(Map<String, Object> bindings, Writer out) throws IOException, TemplateEvaluationException {
      if (fragments != null) {
         for (Fragment f : fragments) {
            f.eval(bindings, out);
         }
      }
   }

   public FragmentList getFragments() {
      return fragments;
   }

   public void setFragments(FragmentList fragments) {
      this.fragments = fragments;
   }
}
TOP

Related Classes of cambridge.model.TagNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.