Package org.exist.xslt.expression

Source Code of org.exist.xslt.expression.Template

/*
*  eXist Open Source Native XML Database
*  Copyright (C) 2008-2010 The eXist Project
*  http://exist-db.org
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*  $Id$
*/
package org.exist.xslt.expression;

import java.util.HashMap;
import java.util.Map;

import org.exist.xquery.AnalyzeContextInfo;
import org.exist.xquery.Expression;
import org.exist.xquery.LocationStep;
import org.exist.xquery.NodeTest;
import org.exist.xquery.TextConstructor;
import org.exist.xquery.TypeTest;
import org.exist.xquery.Variable;
import org.exist.xquery.XPathException;
import org.exist.xquery.util.ExpressionDumper;
import org.exist.xquery.value.Item;
import org.exist.xquery.value.NodeValue;
import org.exist.xquery.value.Sequence;
import org.exist.xquery.value.SequenceIterator;
import org.exist.xquery.value.ValueSequence;
import org.exist.xslt.ErrorCodes;
import org.exist.xslt.XSLContext;
import org.exist.dom.QName;
import org.exist.interpreter.ContextAtExist;
import org.exist.xslt.expression.i.Parameted;
import org.exist.xslt.pattern.Pattern;
import org.exist.xslt.XSLExceptions;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;

/**
* <!-- Category: declaration -->
* <xsl:template
*   match? = pattern
*   name? = qname
*   priority? = number
*   mode? = tokens
*   as? = sequence-type>
*   <!-- Content: (xsl:param*, sequence-constructor) -->
* </xsl:template>
*
* @author <a href="mailto:shabanovd@gmail.com">Dmitriy Shabanov</a>
*
*/
public class Template extends Declaration implements Parameted, Comparable<Template> {

    private String attr_match = null;
    private String attr_priority = null;

    private XSLPathExpr match = null;
    private QName name = null;
    private QName[] mode = null;
    private Double priority = null;
    private String as = null;
   
    private Map<QName, org.exist.xquery.Variable> params = null;

    public Template(XSLContext context) {
    super(context);
  }

  public void setToDefaults() {
      attr_match = null;
      attr_priority = null;
     
      match = null;
      name = null;
      mode = null;
      priority = 0.5;//UNDERSTAND: what should be default
      as = "item()*";
  }

  public void prepareAttribute(ContextAtExist context, Attr attr) throws XPathException {
    String attr_name = attr.getLocalName();
     
    if (attr_name.equals(MATCH)) {
      attr_match = attr.getValue();
    } else if (attr_name.equals(NAME)) {
        name = new QName(attr.getValue());
    } else if (attr_name.equals(PRIORITY)) {
      attr_priority = attr.getValue();
    } else if (attr_name.equals(MODE)) {
//      mode = attr.getValue();//TODO: write
    } else if (attr_name.equals(AS)) {
        as = attr.getValue();
    }
  }
 
//    public void add(SimpleConstructor s) {
//      if (s instanceof Text) {
//      return; //ignore text nodes
//    }
//        steps.add(s);
//    }
//

  public void analyze(AnalyzeContextInfo contextInfo) throws XPathException {
    if (isRootMatch())
      contextInfo.addFlag(DOT_TEST);
   
    super.analyze(contextInfo);

      if (attr_match != null) {
        match = new XSLPathExpr(getXSLContext());
        Pattern.parse(contextInfo.getContext(), attr_match, match);

      _check_(match);
      }
      if (attr_priority != null)
        try {
          priority = Double.valueOf(attr_priority);
        } catch (NumberFormatException e) {
          compileError(XSLExceptions.ERR_XTSE0530);
        }
      else
        priority = computedPriority();
   
    setUseStaticContext(true);
  }

  public void validate() throws XPathException {
    boolean canBeParam = true;
    for (int pos = 0; pos < this.getLength(); pos++) {
      Expression expr = this.getExpression(pos);
     
      if (expr instanceof TextConstructor) {
        continue;//ignore text elements
      }

      //validate instruction order
      if (expr instanceof Param) {
        if (!canBeParam) {
          compileError(ErrorCodes.XTSE0010, "<xsl:param> must be before any other tag");
        }
      } else
        canBeParam = false;
     
      //validate sub-instructions
      if (expr instanceof XSLPathExpr) {
        XSLPathExpr xsl = (XSLPathExpr) expr;
        xsl.validate();
      }
    }
  }
 
  private double computedPriority() {
    double priority = 0.5;
    if (match != null)
      if (match.getLength() > 0) {
        Expression expr = match.getExpression(0);
        if (expr instanceof LocationStep) {
          LocationStep locationStep = (LocationStep) expr;
          NodeTest test = locationStep.getTest();
          if ((test.getName() == null)
              || (test.getName().getLocalName() == null))
            priority = -0.5;
          else if (locationStep.getPredicates().size() > 0)
            priority = 0.25;
          else
            priority = 0;
          //TODO: else (element(E,T) 0.25 (matches by name and type) ...)
        }
      }
    return priority;
  }
 
  public boolean isSmallWildcard() {
    if (match != null)
      if (match.getLength() > 0) {
        Expression expr = match.getExpression(0);
        if (expr instanceof LocationStep) {
          LocationStep locationStep = (LocationStep) expr;
          NodeTest test = locationStep.getTest();
          if (test instanceof TypeTest) {
            if (test.getName() == null)
            return true;
          }
        }
      }
    return false;
  }
 
//  private void _check_(PathExpr path) {
//    for (int pos = 0; pos < path.getLength(); pos++) {
//      Expression expr = path.getExpression(pos);
//      if ((pos == 0) && (expr instanceof LocationStep)) {
//        LocationStep location = (LocationStep) expr;
//        if (location.getAxis() == Constants.CHILD_AXIS) {
//          location.setAxis(Constants.SELF_AXIS);
//        }
//      } else if (expr instanceof PathExpr) {
//        _check_((PathExpr) expr);
//      }
//    }
//  }

  public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
      context.pushDocumentContext();
      try {
      return super.eval(contextSequence, contextItem);
      } finally {
        context.popDocumentContext();
      }
  }
//  public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
//    Sequence result = new ValueSequence();
//   
//    if ((contextItem == null) && (isSmallWildcard()))
//      return result; //UNDERSTAND: is it ok??? maybe better null or check at XSLComp
//   
////    if ((contextSequence == null) && (isBigWildcard()))
////      return result; //UNDERSTAND: is it ok??? maybe better null or check at XSLComp
//
//    Sequence matched = match.eval(contextSequence, contextItem);
//    for (Item item : matched) {
//      Sequence answer = super.eval(item.toSequence(), item);//item
//      result.addAll(answer);
//    }
//   
//    return result;
//  }
 
  public int compareTo(Template template) {
    if (priority == null)
      throw new RuntimeException("Priority can't be null.");
    if (template.priority == null)
      throw new RuntimeException("Priority can't be null.");

    //-compareTo  to make order from high to low
    int compared = priority.compareTo(template.priority);
    if (compared == 0) {
      int thisVal = getExpressionId();
      int anotherVal = template.getExpressionId();
      return (thisVal<anotherVal ? +1 : (thisVal==anotherVal ? 0 : -1));
    }
    return -compared;
  }

  /* (non-Javadoc)
     * @see org.exist.xquery.Expression#dump(org.exist.xquery.util.ExpressionDumper)
     */
    public void dump(ExpressionDumper dumper) {
        dumper.display("<xsl:template");
        if (match != null) {
          dumper.display(" match = ");
          match.dump(dumper);
        }
        if (name != null)
          dumper.display(" name = "+name);
        if (mode != null)
          dumper.display(" mode = "+mode);
        if (attr_priority != null)
          dumper.display(" priority = "+attr_priority);
        if (as != null)
          dumper.display(" as = "+as);

        dumper.display("> ");
       
        super.dump(dumper);

        dumper.display("</xsl:template>");
    }
   
    public String toString() {
      StringBuilder result = new StringBuilder();
      result.append("<xsl:template");
       
      if (match != null)
          result.append(" match = "+match.toString());   
        if (name != null)
          result.append(" name = "+name.getStringValue());   
        if (mode != null)
          result.append(" mode = "+mode);   
        if (attr_priority != null)
          result.append(" priority = "+attr_priority);   
        if (as != null)
          result.append(" as = "+as);   

        result.append("> ");
       
//        result.append(super.toString());

//        result.append("</xsl:template> ");
        return result.toString();
    }

  public boolean matched(Sequence contextSequence, Item item) throws XPathException {
    if (match == null)
      return false;
   
    boolean matched = false;
    for (int i = match.getLength()-1; i >= 0; i--) {
      Expression expr = match.getExpression(i);
      if (!expr.match(contextSequence, item))
        return false;
      if (expr instanceof LocationStep) {
       
        item = (Item)((NodeValue)item).getNode().getParentNode();
      }
      matched = true;
    }
    return matched;
  }
 
  public boolean isRootMatch() {
    return ("/".equals(attr_match));
  }
 
  public boolean isPrioritySet() {
    return attr_priority != null;
  }

  public double getPriority() {
    return priority;
  }

    public Map<QName, org.exist.xquery.Variable> getXSLParams() {
      if (params == null)
        params = new HashMap<QName, org.exist.xquery.Variable>();
     
      return params;
    }

    /* (non-Javadoc)
   * @see org.exist.xslt.expression.i.Parameted#addXSLParam(org.exist.xslt.expression.Param)
   */
  public void addXSLParam(Param param) throws XPathException {
    Map<QName, org.exist.xquery.Variable> params = getXSLParams();
   
    if (params.containsKey(param.getName()))
      compileError(XSLExceptions.ERR_XTSE0580);
   
     Variable variable = context.declareVariable(param.getName(), param);
     params.put(param.getName(), variable);
  }
 
  public QName getName() {
    return name;
  }
 
  /**
   * @deprecated Use {@link #process(XSLContext,SequenceIterator)} instead
   */
  public void process(SequenceIterator sequenceIterator, XSLContext context) {
    process(context, sequenceIterator);
  }

  public void process(XSLContext context, SequenceIterator sequenceIterator) {
    super.process(context, sequenceIterator);
  }
}
TOP

Related Classes of org.exist.xslt.expression.Template

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.