1.1 restoration
[mir.git] / source / mir / generator / tal / template / CoreTemplateNodeLibrary.java
diff --git a/source/mir/generator/tal/template/CoreTemplateNodeLibrary.java b/source/mir/generator/tal/template/CoreTemplateNodeLibrary.java
new file mode 100755 (executable)
index 0000000..e806deb
--- /dev/null
@@ -0,0 +1,380 @@
+/*\r
+ * Copyright (C) 2001, 2002 The Mir-coders group\r
+ *\r
+ * This file is part of Mir.\r
+ *\r
+ * Mir is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Mir is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with Mir; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *\r
+ * In addition, as a special exception, The Mir-coders gives permission to link\r
+ * the code of this program with  any library licensed under the Apache Software License,\r
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library\r
+ * (or with modified versions of the above that use the same license as the above),\r
+ * and distribute linked combinations including the two.  You must obey the\r
+ * GNU General Public License in all respects for all of the code used other than\r
+ * the above mentioned libraries.  If you modify this file, you may extend this\r
+ * exception to your version of the file, but you are not obligated to do so.\r
+ * If you do not wish to do so, delete this exception statement from your version.\r
+ */\r
+\r
+package mir.generator.tal.template;\r
+\r
+import java.util.*;\r
+\r
+import mir.generator.tal.interfaces.TALExpressionParser;\r
+import mir.generator.tal.interfaces.TALLogger;\r
+import mir.util.HTMLRoutines;\r
+import mir.util.StringRoutines;\r
+import mir.util.xml.XMLName;\r
+import mir.util.xml.XMLParserExc;\r
+import mir.util.xml.XMLReaderTool;\r
+\r
+public class CoreTemplateNodeLibrary implements TemplateNodeLibrary {\r
+  private String prefix;\r
+  private String uri;\r
+\r
+  private boolean isOurTag(XMLName aName) {\r
+    return prefix.equals(aName.getPrefix()) || uri.equals(aName.getNamespaceURI());\r
+  }\r
+\r
+  public CoreTemplateNodeLibrary(String aPrefix, String aUri) {\r
+    prefix = aPrefix;\r
+    uri = aUri;\r
+  }\r
+\r
+  private static final String CONDITION_ATTRIBUTE = "condition";\r
+  private static final String REPEAT_ATTRIBUTE = "repeat";\r
+  private static final String CONTENT_ATTRIBUTE = "content";\r
+  private static final String ERROR_ATTRIBUTE = "on-error";\r
+  private static final String REPLACE_ATTRIBUTE = "replace";\r
+  private static final String DEFINITION_ATTRIBUTE = "define";\r
+  private static final String OMITTAG_ATTRIBUTE = "omit-tag";\r
+  private static final String ATTRIBUTE_ATTRIBUTE = "attributes";\r
+\r
+  public TemplateNode constructTemplateNode(TALExpressionParser aParser, XMLName aTag, Map anAttributes,\r
+      TemplateNode aChildTemplateNode, Map aTemplateContext) throws XMLParserExc {\r
+    TALBasicTemplateNode result = new TALBasicTemplateNode(XMLReaderTool.normalizeXMLName(aTag));\r
+    result.setBody(aChildTemplateNode);\r
+\r
+    if (isOurTag(aTag))\r
+      result.setOmitTag(aParser.preparseTRUE());\r
+\r
+    Iterator i = anAttributes.entrySet().iterator();\r
+    while (i.hasNext()) {\r
+      Map.Entry entry = (Map.Entry) i.next();\r
+      XMLName name = (XMLName) entry.getKey();\r
+\r
+      if (!isOurTag(name)) {\r
+        result.addFixedAttribute(XMLReaderTool.normalizeXMLName(name), (String) entry.getValue());\r
+      }\r
+      else {\r
+        if (name.getLocalName().equalsIgnoreCase(DEFINITION_ATTRIBUTE)) {\r
+          List definitions = StringRoutines.splitStringWithEscape((String) entry.getValue(), ';', '\\');\r
+\r
+          Iterator j = definitions.iterator();\r
+          while (j.hasNext())\r
+          {\r
+            List parts = StringRoutines.separateString((String) j.next(), " ");\r
+\r
+            if (parts.size()==2) {\r
+              result.addDefinition(aParser.preparseReferenceExpression((String) parts.get(0)), aParser.preparseExpression((String) parts.get(1)));\r
+            }\r
+          }\r
+        }\r
+        else if (name.getLocalName().equalsIgnoreCase(CONDITION_ATTRIBUTE)) {\r
+          result.setCondition(aParser.preparseBooleanExpression((String) entry.getValue()));\r
+        }\r
+        else if (name.getLocalName().equalsIgnoreCase(CONTENT_ATTRIBUTE)) {\r
+          result.setContent(aParser.preparseStringExpression((String) entry.getValue()));\r
+        }\r
+        else if (name.getLocalName().equalsIgnoreCase(ERROR_ATTRIBUTE)) {\r
+          result.setError(aParser.preparseStringExpression((String) entry.getValue()));\r
+        }\r
+        else if (name.getLocalName().equalsIgnoreCase(OMITTAG_ATTRIBUTE)) {\r
+          if (((String) entry.getValue()).trim().length()==0)\r
+            result.setOmitTag(aParser.preparseTRUE());\r
+          else\r
+            result.setOmitTag(aParser.preparseBooleanExpression((String) entry.getValue()));\r
+        }\r
+        else if (name.getLocalName().equalsIgnoreCase(REPLACE_ATTRIBUTE)) {\r
+          result.setOmitTag(aParser.preparseTRUE());\r
+          result.setContent(aParser.preparseStringExpression((String) entry.getValue()));\r
+        }\r
+        else if (name.getLocalName().equalsIgnoreCase(REPEAT_ATTRIBUTE)) {\r
+          List parts = StringRoutines.separateString((String) entry.getValue(), " ");\r
+\r
+          if (parts.size()==2) {\r
+            result.setRepeat(aParser.preparseReferenceExpression((String) parts.get(0)), aParser.preparseExpression((String) parts.get(1)));\r
+          }\r
+        }\r
+        else if (name.getLocalName().equalsIgnoreCase(ATTRIBUTE_ATTRIBUTE)) {\r
+          List attributes = StringRoutines.splitStringWithEscape((String) entry.getValue(), ';', '\\');\r
+\r
+          Iterator j = attributes.iterator();\r
+          while (j.hasNext()) {\r
+            String value = (String) j.next();\r
+            List parts = StringRoutines.separateString(value.trim(), " ");\r
+\r
+            if (parts.size()==2) {\r
+              result.addModifiedAttribute((String) parts.get(0), aParser.preparseExpression((String) parts.get(1)));\r
+            }\r
+            else {\r
+              throw new XMLParserExc(ATTRIBUTE_ATTRIBUTE + " tag should have exactly 2 parts ("+value+")");\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    return result;\r
+  }\r
+\r
+  public static class TALBasicTemplateNode implements TemplateNode {\r
+    private String tag;\r
+    private Map fixedAttributes;\r
+    private Map attributeModifiers;\r
+\r
+    private List definitions;\r
+    private Object condition;\r
+\r
+    private Object repeatVariable;\r
+    private Object repeatExpression;\r
+    private Object contentExpression;\r
+    private Object omitTagExpression;\r
+    private Object errorExpression;\r
+\r
+    private TemplateNode body;\r
+\r
+    public TALBasicTemplateNode(String aTag) {\r
+      tag = aTag;\r
+\r
+      fixedAttributes = new HashMap();\r
+      attributeModifiers = new HashMap();\r
+\r
+      definitions = new ArrayList();\r
+      condition = null;\r
+\r
+      repeatVariable = null;\r
+      repeatExpression = null;\r
+      contentExpression = null;\r
+      omitTagExpression = null;\r
+\r
+      body = null;\r
+    }\r
+\r
+    public void setBody(TemplateNode aBody) {\r
+      body = aBody;\r
+    }\r
+\r
+    public void addFixedAttribute(String aKey, String aValue) {\r
+      fixedAttributes.put(aKey, aValue);\r
+    }\r
+\r
+    public void addModifiedAttribute(String aKey, Object aValue) {\r
+      attributeModifiers.put(aKey, aValue);\r
+    }\r
+\r
+    public void addDefinition(Object aKey, Object aValue) {\r
+      definitions.add(new Definition(aKey, aValue));\r
+    }\r
+\r
+    public void setCondition(Object aCondition) {\r
+      condition = aCondition;\r
+    }\r
+\r
+    public void setRepeat(Object aRepeatVariable, Object aRepeatExpression) {\r
+      repeatVariable = aRepeatVariable;\r
+      repeatExpression = aRepeatExpression;\r
+    }\r
+\r
+    public void setContent(Object aContentExpression) {\r
+      contentExpression = aContentExpression;\r
+    }\r
+\r
+    public void setOmitTag(Object anOmitTagExpression) {\r
+      omitTagExpression = anOmitTagExpression;\r
+    }\r
+\r
+    public void setError(Object anErrorExpression) {\r
+      errorExpression = anErrorExpression;\r
+    }\r
+\r
+    public static class Definition {\r
+      private Object variable;\r
+      private Object expression;\r
+\r
+      public Definition(Object aVariable, Object anExpression) {\r
+        variable = aVariable;\r
+        expression = anExpression;\r
+      }\r
+\r
+      public Object getVariable() {\r
+        return variable;\r
+      }\r
+\r
+      public Object getExpression() {\r
+        return expression;\r
+      }\r
+    }\r
+\r
+    public void process(TALExpressionParser aParser, Object aContext,\r
+        StringBuffer aDestination, TALLogger aLogger, Map aTemplateContext,\r
+        TemplateLibrary aLibrary) throws TemplateProcessingException {\r
+      if (errorExpression != null) {\r
+        StringBuffer destination = new StringBuffer();\r
+\r
+        try {\r
+          outerProcess(aParser, aContext, destination, aLogger, aTemplateContext, aLibrary);\r
+        }\r
+        catch (Throwable t) {\r
+          try {\r
+//            destination.delete(0, destination.length());\r
+            aParser.processPseudoAssignment(aContext, "exception", t);\r
+            destination.insert(0, aParser.evaluateStringExpression(aContext, errorExpression));\r
+            destination.append(" >>>ERROR POSITION<<< ");\r
+          }\r
+          catch (Throwable s) {\r
+            throw new TemplateProcessingException(s);\r
+          }\r
+        }\r
+        finally {\r
+          aDestination.append(destination);\r
+        }\r
+      }\r
+      else {\r
+        outerProcess(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary);\r
+      }\r
+    }\r
+\r
+    public String getPlainText() {\r
+      return body.getPlainText();\r
+    }\r
+\r
+    public void outerProcess(TALExpressionParser aParser, Object aContext,\r
+        StringBuffer aDestination, TALLogger aLogger, Map aTemplateContext,\r
+        TemplateLibrary aLibrary) throws TemplateProcessingException {\r
+\r
+      Object oldAttributes = aParser.evaluatePseudoVariable(aContext, "tagattributes");\r
+      aParser.processPseudoAssignment(aContext, "tagattributes", Collections.unmodifiableMap(fixedAttributes));\r
+\r
+      Object oldContent = aParser.evaluatePseudoVariable(aContext, "tagcontent");\r
+      aParser.processPseudoAssignment(aContext, "tagcontent", body.getPlainText());\r
+\r
+      try {\r
+        Iterator i;\r
+\r
+        i = definitions.iterator();\r
+        while (i.hasNext()) {\r
+          Definition d = (Definition) i.next();\r
+          aParser.processAssignment(aContext, d.getVariable(), d.getExpression());\r
+        }\r
+\r
+        if (condition == null || aParser.evaluateBooleanExpression(aContext, condition)) {\r
+          if (repeatExpression != null) {\r
+            i = aParser.evaluateListExpression(aContext, repeatExpression);\r
+\r
+            while (i.hasNext()) {\r
+              aParser.processDirectAssignment(aContext, repeatVariable, i.next());\r
+              innerProcess(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary);\r
+            }\r
+          }\r
+          else {\r
+            innerProcess(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary);\r
+          }\r
+        }\r
+      }\r
+      finally {\r
+        try {\r
+          aParser.processPseudoAssignment(aContext, "tagattributes", oldAttributes);\r
+          aParser.processPseudoAssignment(aContext, "tagcontent", oldContent);\r
+        }\r
+        catch (Throwable t) {\r
+        }\r
+      }\r
+    };\r
+\r
+    private void innerProcess(TALExpressionParser aParser, Object aContext,\r
+        StringBuffer aDestination, TALLogger aLogger, Map aTemplateContext, TemplateLibrary aLibrary)\r
+        throws TemplateProcessingException {\r
+\r
+      boolean omitTag = false;\r
+      StringBuffer content = aDestination;\r
+\r
+      if (omitTagExpression != null)\r
+        omitTag = aParser.evaluateBooleanExpression(aContext, omitTagExpression);\r
+\r
+      if (!omitTag) {\r
+        content = new StringBuffer();\r
+        Map generatedAttributes = new HashMap(fixedAttributes);\r
+\r
+        Iterator i = attributeModifiers.entrySet().iterator();\r
+        while (i.hasNext()) {\r
+          Map.Entry entry = (Map.Entry) i.next();\r
+\r
+          generatedAttributes.put(entry.getKey(), aParser.evaluateStringExpression(aContext, entry.getValue()));\r
+        }\r
+\r
+        aDestination.append("<");\r
+        aDestination.append(tag);\r
+\r
+        i = generatedAttributes.entrySet().iterator();\r
+        while (i.hasNext()) {\r
+          Map.Entry entry = (Map.Entry) i.next();\r
+          aDestination.append(" ");\r
+          aDestination.append(entry.getKey());\r
+          aDestination.append("=");\r
+          aDestination.append("\"");\r
+          aDestination.append(HTMLRoutines.encodeHTML( (String) entry.getValue()));\r
+          aDestination.append("\"");\r
+        }\r
+      }\r
+\r
+      try{\r
+        if (contentExpression != null) {\r
+          content.append(aParser.evaluateStringExpression(aContext, contentExpression));\r
+        }\r
+        else {\r
+          if (body != null) {\r
+            body.process(aParser, aContext, content, aLogger, aTemplateContext, aLibrary);\r
+          }\r
+        }\r
+        if (!omitTag) {\r
+          if (content.length()==0) {\r
+            aDestination.append(" />");\r
+          }\r
+          else {\r
+            aDestination.append(">");\r
+            aDestination.append(content);\r
+            aDestination.append("</");\r
+            aDestination.append(tag);\r
+            aDestination.append(">");\r
+          }\r
+        }\r
+      }\r
+      catch (Throwable t) {\r
+        if (!omitTag) {\r
+          aDestination.append(content);\r
+        }\r
+\r
+        if (t instanceof TemplateProcessingException) {\r
+          throw (TemplateProcessingException) t;\r
+        }\r
+        else if (t instanceof RuntimeException) {\r
+          throw (RuntimeException) t;\r
+        }\r
+        else throw new TemplateProcessingException(t.toString());\r
+      }\r
+    }\r
+  }\r
+}\r