sboag       99/12/16 03:19:20

  Modified:    src      makexslt4j
               src/org/apache/xalan/xpath/dtm DTMLiaison.java DTMProxy.java
               src/org/apache/xalan/xpath/xml FormatterToHTML.java
               src/org/apache/xalan/xslt Stylesheet.java
                        StylesheetHandler.java
  Added:       src/org/apache/xalan/xslt TemplateList.java
  Log:
  Fixed template conflicts when priority is different but pattern is the same.  
Also broke template handling into a TemplateList class, in order to make it 
easier to navigate around template management and template match resolution.
  
  Revision  Changes    Path
  1.5       +1 -0      xml-xalan/src/makexslt4j
  
  Index: makexslt4j
  ===================================================================
  RCS file: /home/cvs/xml-xalan/src/makexslt4j,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- makexslt4j        1999/12/03 08:43:11     1.4
  +++ makexslt4j        1999/12/16 11:19:18     1.5
  @@ -85,6 +85,7 @@
     $(XSLT4JDIR)$(PATHSEP)XSLProcessorVersion.java \
     $(XSLT4JDIR)$(PATHSEP)XSLTInputSource.java \
     $(XSLT4JDIR)$(PATHSEP)XSLTResultTarget.java \
  +  $(XSLT4JDIR)$(PATHSEP)TemplateList.java \
     $(XSLT4JDIR)$(PATHSEP)ResultNameSpace.java \
     $(TRACEDIR)$(PATHSEP)GenerateEvent.java \
     $(TRACEDIR)$(PATHSEP)SelectionEvent.java \
  
  
  
  1.8       +1 -1      xml-xalan/src/org/apache/xalan/xpath/dtm/DTMLiaison.java
  
  Index: DTMLiaison.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/dtm/DTMLiaison.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- DTMLiaison.java   1999/12/16 06:10:45     1.7
  +++ DTMLiaison.java   1999/12/16 11:19:19     1.8
  @@ -274,7 +274,7 @@
     {
       try
       {
  -      return ((org.apache.xalan.xpath.dtm.DTMProxy)n).getParentNode();
  +      return ((org.apache.xalan.xpath.dtm.DTMProxy)n).getOwnerNode();
       }
       catch(ClassCastException cce)
       {
  
  
  
  1.5       +7 -0      xml-xalan/src/org/apache/xalan/xpath/dtm/DTMProxy.java
  
  Index: DTMProxy.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/dtm/DTMProxy.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DTMProxy.java     1999/12/16 09:06:05     1.4
  +++ DTMProxy.java     1999/12/16 11:19:19     1.5
  @@ -224,6 +224,13 @@
     }
   
     /** @see org.w3c.dom.Node */
  +  public final Node               getOwnerNode()
  +  {
  +    int newnode=dtm.getParent(node);
  +    return (newnode==-1) ? null : dtm.getNode(newnode);
  +  }
  +
  +  /** @see org.w3c.dom.Node */
     public final NodeList           getChildNodes()
     {
       throw new DTMException(DTMException.NOT_SUPPORTED_ERR);
  
  
  
  1.17      +1 -2      
xml-xalan/src/org/apache/xalan/xpath/xml/FormatterToHTML.java
  
  Index: FormatterToHTML.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/src/org/apache/xalan/xpath/xml/FormatterToHTML.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- FormatterToHTML.java      1999/12/15 21:53:07     1.16
  +++ FormatterToHTML.java      1999/12/16 11:19:19     1.17
  @@ -356,8 +356,7 @@
       m_attrCharsMap[(int)'\n'] = 'S';
       // XSLT Spec: The html output method should not 
       // escape < characters occurring in attribute values.
  -    // (But I'll comment this out for Stefano for the moment.)
  -    // m_attrCharsMap[(int)'<'] = '\0';
  +    m_attrCharsMap[(int)'<'] = '\0';
       m_attrCharsMap[(int)'>'] = '\0';
       m_charsMap[0x0A] = 'S';
       m_charsMap[0x0D] = 'S';
  
  
  
  1.17      +22 -467   xml-xalan/src/org/apache/xalan/xslt/Stylesheet.java
  
  Index: Stylesheet.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/Stylesheet.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- Stylesheet.java   1999/12/16 03:50:35     1.16
  +++ Stylesheet.java   1999/12/16 11:19:19     1.17
  @@ -108,15 +108,6 @@
     }
   
     /**
  -   * This table is keyed on the target elements 
  -   * of patterns, and contains linked lists of
  -   * the actual patterns that match the target element
  -   * to some degree of specifity.
  -   * @serial
  -   */
  -  private Hashtable m_patternTable = new Hashtable();
  -
  -  /**
      * Table of attribute sets, keyed by set name.
      * @serial
      */
  @@ -165,19 +156,6 @@
      * @serial
      */
     boolean m_tablesAreInvalid = true;
  -
  -  /**
  -   * Tells if the stylesheet is without an xsl:stylesheet 
  -   * and xsl:template wrapper.
  -   * @serial
  -   */
  -  boolean m_isWrapperless = false;
  -  
  -  /**
  -   * The manufactured template if there is no wrapper.
  -   * @serial
  -   */
  -  ElemTemplate m_wrapperlessTemplate = null;
     
     /**
      * A dummy value for use in hash tables that have no use for the value.
  @@ -242,25 +220,24 @@
     Hashtable m_extensionNamespaces = new Hashtable();
     
     /**
  -   * The first template of the template children.
  -   * @serial
  -   */
  -  ElemTemplateElement m_firstTemplate = null;
  +   * The list of templates, and findTemplate support.
  +   */  
  +  private TemplateList m_templateList;
     
     /**
  -   * Get the first template of the template children.
  +   * Get the list of templates.
      */
  -  public ElemTemplateElement getFirstTemplate()
  +  public TemplateList getTemplateList()
     {
  -    return m_firstTemplate;
  +    return m_templateList;
     }
   
     /**
  -   * Set the first template of the template children.
  +   * Set the list of templates.
      */
  -  public void setFirstTemplate(ElemTemplateElement v)
  +  public void setTemplateList(TemplateList v)
     {
  -    m_firstTemplate = v;
  +    m_templateList = v;
     }
   
     /**
  @@ -445,35 +422,6 @@
     }
   
     /**
  -   * Keyed on string macro names, and holding values 
  -   * that are macro elements in the XSL DOM tree.
  -   * Initialized in initMacroLookupTable, and used in
  -   * findNamedTemplate.
  -   * @serial
  -   */
  -  Hashtable m_namedTemplates = new Hashtable();
  -  
  -  /**
  -   * Get table of named Templates.
  -   * These are keyed on string macro names, and holding values 
  -   * that are template elements in the XSL DOM tree.
  -   */
  -  public Hashtable getNamedTemplates()
  -  {
  -    return m_namedTemplates;
  -  }
  -
  -  /**
  -   * Set table of named Templates.
  -   * These are keyed on string macro names, and holding values 
  -   * that are template elements in the XSL DOM tree.
  -   */
  -  public void setNamedTemplates(Hashtable v)
  -  {
  -    m_namedTemplates = v;
  -  }
  -
  -  /**
      * Table for defined constants, keyed on the names.
      * @serial
      */
  @@ -679,6 +627,7 @@
       IOException,
       SAXException
     {
  +    m_templateList = new TemplateList(this);
       m_includeStack = new Stack();
       
m_includeStack.push(processor.m_parserLiaison.getURLFromString(this.m_baseIdent,
 null));
       initXPath(processor, null);
  @@ -1019,132 +968,6 @@
     }
     
     /**
  -   * Add a template to the template list.
  -   */
  -  void addTemplate(ElemTemplate template)
  -  {
  -    int pos = 0;
  -    if(null == m_firstTemplate)
  -    {
  -      m_firstTemplate = template;
  -    }
  -    else
  -    {
  -      ElemTemplateElement next = m_firstTemplate;
  -      while(null != next)
  -      {
  -        if(null == next.m_nextSibling)
  -        {
  -          next.m_nextSibling = template;
  -          template.m_nextSibling = null; // just to play it safe.
  -          break;
  -        }
  -        pos++;
  -        next = next.m_nextSibling;
  -      }
  -    }
  -    if(null != template.m_name)
  -    {
  -      m_namedTemplates.put(template.m_name, template);
  -    }
  -    
  -    if(null != template.m_matchPattern)
  -    {
  -      Vector strings = template.m_matchPattern.getTargetElementStrings();
  -      if(null != strings)
  -      {
  -        int nTargets = strings.size();
  -        for(int stringIndex = 0; stringIndex < nTargets; stringIndex++) 
  -        {
  -          String target = (String)strings.elementAt(stringIndex);
  -          
  -          Object newMatchPat = new 
MatchPattern2(template.m_matchPattern.m_currentPattern, 
  -                                                 template.m_matchPattern, 
  -                                                 template, pos, 
  -                                                 target, this);
  -          
  -          // See if there's already one there
  -          Object val = m_patternTable.get(target);
  -          if(null == val)
  -          {
  -            // System.out.println("putting: "+target);
  -            m_patternTable.put(target, newMatchPat);
  -          }
  -          else
  -          {
  -            // find the tail of the list
  -            MatchPattern2 matchPat = (MatchPattern2)val;
  -            ((MatchPattern2)newMatchPat).setNext(matchPat);
  -            m_patternTable.put(target, newMatchPat);
  -            /*
  -            MatchPattern2 next;
  -            while((next = matchPat.getNext()) != null)
  -            {
  -            matchPat = next;
  -            }
  -            // System.out.println("appending: "+target+" to 
"+matchPat.getPattern());
  -            matchPat.setNext((MatchPattern2)newMatchPat);
  -            */
  -          }
  -        }
  -      }
  -    }
  -  }
  -  
  -  /**
  -   * Locate a macro via the "name" attribute.
  -   * @exception XSLProcessorException thrown if the active ProblemListener 
and XMLParserLiaison decide 
  -   * the error condition is severe enough to halt processing.
  -   */
  -  ElemTemplateElement findNamedTemplate(String name)
  -    throws XSLProcessorException
  -  {
  -    QName qname = new QName(name, m_namespaces);
  -    
  -    return findNamedTemplate(qname);
  -  }
  -  
  -  /**
  -   * Locate a macro via the "name" attribute.
  -   * @exception XSLProcessorException thrown if the active ProblemListener 
and XMLParserLiaison decide 
  -   * the error condition is severe enough to halt processing.
  -   */
  -  ElemTemplateElement findNamedTemplate(QName qname)
  -    throws XSLProcessorException
  -  {
  -    ElemTemplateElement namedTemplate = null;
  -    Object obj = m_namedTemplates.get(qname);
  -    if(null == obj)
  -    {
  -      int nImports = m_imports.size();
  -      for(int i = 0; i < nImports; i++)
  -      {
  -        Stylesheet stylesheet = (Stylesheet)m_imports.elementAt(i);
  -        namedTemplate = stylesheet.findNamedTemplate(qname);
  -        if(null != namedTemplate)
  -        {
  -          break;
  -        }
  -      }
  -      if((null == namedTemplate) && (null != m_stylesheetParent))
  -      {
  -        Stylesheet stylesheet = m_stylesheetParent.getPreviousImport(this);
  -        if(null != stylesheet)
  -        {
  -          namedTemplate = stylesheet.findNamedTemplate(qname);
  -        }
  -      }
  -    }
  -    else
  -    {
  -      namedTemplate = (ElemTemplateElement)obj;
  -    }
  -    
  -    return namedTemplate;
  -  }
  -
  -  
  -  /**
      * Set a top level variable, to be serialized with the rest of 
      * the stylesheet.
      * @param var A top-level variable declared with xsl:variable or 
xsl:param-variable.
  @@ -1229,9 +1052,9 @@
              java.io.FileNotFoundException, 
              java.io.IOException
     {
  -    return findTemplate(transformContext, sourceTree, targetNode, null, 
false, null);
  +    return getTemplateList().findTemplate(transformContext, sourceTree, 
targetNode, null, false, null);
     }
  -  
  +
     /**
      * Given a target element, find the template that best 
      * matches in the given XSL document, according 
  @@ -1253,240 +1076,22 @@
                                      QName mode,
                                      boolean useImports,
                                      Stylesheet foundStylesheet[])
  -    throws SAXException, 
  -           java.net.MalformedURLException, 
  -           java.io.FileNotFoundException, 
  -           java.io.IOException
  -  {
  -    ElemTemplate bestMatchedRule = null;
  -    MatchPattern2 bestMatchedPattern =null; // Syncs with bestMatchedRule
  -    if(m_isWrapperless)
  -    {
  -      return m_wrapperlessTemplate;
  -    }
  -    Vector conflicts = null;
  -    if(!useImports)
  -    {
  -      double highScore = XPath.MATCH_SCORE_NONE;
  -      
  -      MatchPattern2 matchPat = null;
  -      int targetNodeType = targetNode.getNodeType();
  -      
  -      switch(targetNodeType)
  -      {
  -      case Node.ELEMENT_NODE:
  -        // String targetName = 
m_parserLiaison.getExpandedElementName((Element)targetNode);
  -        String targetName = 
transformContext.m_parserLiaison.getLocalNameOfNode(targetNode);
  -        matchPat = locateMatchPatternList2(targetName, true);
  -        break;
  -        
  -      case Node.PROCESSING_INSTRUCTION_NODE:
  -      case Node.ATTRIBUTE_NODE:
  -        matchPat = locateMatchPatternList2(targetNode.getNodeName(), true);
  -        break;
  -
  -      case Node.CDATA_SECTION_NODE:
  -      case Node.TEXT_NODE:
  -        matchPat = locateMatchPatternList2(XPath.PSEUDONAME_TEXT, false);
  -        break;
  -
  -      case Node.COMMENT_NODE:
  -        matchPat = locateMatchPatternList2(XPath.PSEUDONAME_COMMENT, false);
  -        break;
  -
  -      case Node.DOCUMENT_NODE:
  -        matchPat = locateMatchPatternList2(XPath.PSEUDONAME_ROOT, false);
  -        break;
  -
  -      case Node.DOCUMENT_FRAGMENT_NODE:
  -        matchPat = locateMatchPatternList2(XPath.PSEUDONAME_ANY, false);
  -        break;
  -        
  -      default:
  -        {
  -          matchPat = locateMatchPatternList2(targetNode.getNodeName(), 
false);
  -        }
  -      }
  -      
  -      String prevPat = null;
  -      while(null != matchPat)
  -      {
  -        ElemTemplate rule = matchPat.getTemplate();
  -        // We'll be needing to match rules according to what 
  -        // mode we're in.
  -        QName ruleMode = rule.m_mode;
  -        
  -        // The logic here should be that if we are not in a mode AND
  -        // the rule does not have a node, then go ahead.
  -        // OR if we are in a mode, AND the rule has a node, 
  -        // AND the rules match, then go ahead.
  -        if(((null == mode) && (null == ruleMode)) || 
  -           ((null != ruleMode) && (null != mode) && ruleMode.equals(mode)))
  -        {
  -          String patterns = matchPat.getPattern();
  -
  -          if((null != patterns) && !((prevPat != null) && 
prevPat.equals(patterns)))
  -          {
  -            prevPat = patterns;
  -            
  -            // Date date1 = new Date();
  -            XPath xpath = matchPat.getExpression();
  -            // System.out.println("Testing score for: 
"+targetNode.getNodeName()+
  -            //                   " against '"+xpath.m_currentPattern);
  -            double score = 
xpath.getMatchScore(transformContext.getExecContext(), targetNode);
  -            // System.out.println("Score for: "+targetNode.getNodeName()+
  -            //                   " against '"+xpath.m_currentPattern+
  -            //                   "' returned "+score);
  -
  -            if(XPath.MATCH_SCORE_NONE != score)
  -            {
  -              double priorityOfRule 
  -                = (XPath.MATCH_SCORE_NONE != rule.m_priority) 
  -                  ? rule.m_priority : score;
  -              matchPat.m_priority = priorityOfRule;
  -              double priorityOfBestMatched = (null != bestMatchedPattern) ?
  -                                             bestMatchedPattern.m_priority : 
  -                                             XPath.MATCH_SCORE_NONE;
  -              // System.out.println("priorityOfRule: "+priorityOfRule+", 
priorityOfBestMatched: "+priorityOfBestMatched);
  -              if(priorityOfRule > priorityOfBestMatched)
  -              {
  -                if(null != conflicts)
  -                  conflicts.removeAllElements();
  -                highScore = score;
  -                bestMatchedRule = rule;
  -                bestMatchedPattern = matchPat;
  -              }
  -              else if(priorityOfRule == priorityOfBestMatched)
  -              {
  -                if(null == conflicts)
  -                  conflicts = new Vector(10);
  -                addObjectIfNotFound(bestMatchedPattern, conflicts);
  -                conflicts.addElement(matchPat);
  -                highScore = score;
  -                bestMatchedRule = rule;
  -                bestMatchedPattern = matchPat;
  -              }
  -            }
  -            // Date date2 = new Date();
  -            // m_totalTimePatternMatching+=(date2.getTime() - 
date1.getTime());
  -          } // end if(null != patterns)            
  -        } // end if if(targetModeString.equals(mode))
  -        
  -        MatchPattern2 nextMatchPat = matchPat.getNext();
  -
  -        // We also have to consider wildcard matches.
  -        if((null == nextMatchPat) && !matchPat.m_targetString.equals("*") && 
  -           ((Node.ELEMENT_NODE == targetNodeType) || 
  -            (Node.ATTRIBUTE_NODE == targetNodeType) ||
  -            (Node.PROCESSING_INSTRUCTION_NODE == targetNodeType)))
  -        {
  -          nextMatchPat = (MatchPattern2)m_patternTable.get("*");
  -        }
  -        matchPat = nextMatchPat;
  -      }
  -    } // end if(!useImports)
  -    
  -    if(null == bestMatchedRule)
  -    {
  -      int nImports = m_imports.size();
  -      for(int i = 0; i < nImports; i++)
  -      {
  -        Stylesheet stylesheet = (Stylesheet)m_imports.elementAt(i);
  -        bestMatchedRule = stylesheet.findTemplate(transformContext, 
sourceTree, targetNode, mode, 
  -                                                  false, foundStylesheet);
  -        if(null != bestMatchedRule)
  -        {
  -          break;
  -        }
  -      }
  -    }
  -
  -    if(null != conflicts)
  -    {
  -      int nConflicts = conflicts.size();
  -      // System.out.println("nConflicts: "+nConflicts);
  -      String conflictsString = (!transformContext.m_quietConflictWarnings) 
  -                               ? "Specificity conflicts found: " : null;
  -      for(int i = 0; i < nConflicts; i++)
  -      {
  -        MatchPattern2 conflictPat = (MatchPattern2)conflicts.elementAt(i);
  -        if(0 != i)
  -        {
  -          if(!transformContext.m_quietConflictWarnings)
  -            conflictsString += ", ";
  -          
  -          // Find the furthest one towards the bottom of the document.
  -          if(conflictPat.m_posInStylesheet > 
bestMatchedPattern.m_posInStylesheet)
  -          {
  -            bestMatchedPattern = conflictPat;
  -          }
  -        }
  -        else
  -        {
  -          bestMatchedPattern = conflictPat;
  -        }
  -        if(!transformContext.m_quietConflictWarnings)
  -          conflictsString += "\""+conflictPat.getPattern()+"\"";
  -      }
  -      bestMatchedRule = bestMatchedPattern.getTemplate();
  -      if(!transformContext.m_quietConflictWarnings)
  -      {
  -        //conflictsString += " ";
  -        //conflictsString += "Last found in stylesheet will be used.";
  -        transformContext.warn(XSLTErrorResources.WARNING0012, new Object[] 
{conflictsString});
  -      }
  -    }
  -
  -    if((null != bestMatchedPattern) && (null != foundStylesheet))
  -    {
  -      foundStylesheet[0] = bestMatchedPattern.m_stylesheet;
  -    }
  -    
  -    return bestMatchedRule;
  -  } // end findTemplate
  -  
  -  /**
  -   * Add object to vector if not already there.
  -   */
  -  void addObjectIfNotFound(Object obj, Vector v)
  +    throws SAXException
     {
  -    int n = v.size();
  -    boolean addIt = true;
  -    for(int i = 0; i < n; i++)
  -    {
  -      if(v.elementAt(i) == obj)
  -      {
  -        addIt = false;
  -        break;
  -      }
  -    }
  -    if(addIt)
  -    {
  -      v.addElement(obj);
  -    }
  +    return getTemplateList().findTemplate(transformContext,
  +                                   sourceTree, targetNode, 
  +                                   mode, useImports, foundStylesheet);
     }
     
     /**
  -   * Given an element type, locate the start of a linked list of 
  -   * possible template matches.
  +   * Locate a macro via the "name" attribute.
  +   * @exception XSLProcessorException thrown if the active ProblemListener 
and XMLParserLiaison decide 
  +   * the error condition is severe enough to halt processing.
      */
  -  private MatchPattern2 locateMatchPatternList2(String sourceElementType, 
boolean tryWildCard)
  +  ElemTemplateElement findNamedTemplate(QName qname)
  +    throws XSLProcessorException
     {
  -    MatchPattern2 startMatchList = null;
  -    Object val = m_patternTable.get(sourceElementType);
  -    if(null != val)
  -    {
  -      startMatchList = (MatchPattern2)val;
  -    }
  -    else if(tryWildCard)
  -    {
  -      val = m_patternTable.get("*");
  -      if(null != val)
  -      {
  -        startMatchList = (MatchPattern2)val;
  -      }
  -    }
  -    return startMatchList;
  +    return getTemplateList().findNamedTemplate(qname);
     }
     
     /**
  @@ -1548,56 +1153,6 @@
         }
       }
     }  
  -  
  -  /**
  -   * A class to contain a match pattern and it's corresponding template.
  -   * This class also defines a node in a match pattern linked list.
  -   */
  -  class MatchPattern2 implements Serializable
  -  {
  -    /**
  -     * Construct a match pattern from a pattern and template.
  -     * @param pat For now a Nodelist that contains old-style element 
patterns.
  -     * @param template The node that contains the template for this pattern.
  -     * @param isMatchPatternsOnly tells if pat param contains only match 
  -     * patterns (for compatibility with old syntax).
  -     */
  -    MatchPattern2(String pat, XPath exp, ElemTemplate template, int 
posInStylesheet, 
  -                  String targetString, Stylesheet stylesheet)
  -    {
  -      m_pattern = pat;
  -      m_template = template;
  -      m_posInStylesheet = posInStylesheet;
  -      m_targetString = targetString;
  -      m_stylesheet = stylesheet;
  -      m_expression = exp;
  -    }
  -    
  -    Stylesheet m_stylesheet;
  -
  -    String m_targetString;
  -    
  -    XPath m_expression;
  -    public XPath getExpression() { return m_expression; }
  -
  -    int m_posInStylesheet;
  -    
  -    /**
  -     * Transient... only used to track priority while 
  -     * processing.
  -     */
  -    double m_priority = XPath.MATCH_SCORE_NONE;
  -    
  -    private String m_pattern;
  -    public String getPattern() { return m_pattern; }
  -    
  -    private ElemTemplate m_template; // ref to the corrisponding template
  -    public ElemTemplate getTemplate() { return m_template; }
  -
  -    private MatchPattern2 m_next = null; // null when at end of list.
  -    public MatchPattern2 getNext() { return m_next; }
  -    public void setNext(MatchPattern2 mp) { m_next = mp; }
  -  }
     
     /**
      * Given a valid element key, return the corresponding node list.
  
  
  
  1.11      +6 -6      
xml-xalan/src/org/apache/xalan/xslt/StylesheetHandler.java
  
  Index: StylesheetHandler.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/src/org/apache/xalan/xslt/StylesheetHandler.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- StylesheetHandler.java    1999/12/14 00:21:55     1.10
  +++ StylesheetHandler.java    1999/12/16 11:19:19     1.11
  @@ -415,7 +415,7 @@
         {
           m_stylesheet.initXSLTKeys();
           m_stylesheet.m_stylesheetRoot.initDefaultRule();
  -        m_stylesheet.m_isWrapperless = false;
  +        m_stylesheet.getTemplateList().setIsWrapperless(false);
         }
         
         Object obj = m_stylesheet.m_elementKeys.get(localName);
  @@ -435,7 +435,7 @@
                                           name, atts, lineNumber, 
columnNumber);
             m_elems.push(m_template);
             m_inTemplate = true;
  -          m_stylesheet.addTemplate(m_template);
  +          m_stylesheet.getTemplateList().addTemplate(m_template);
             break;
   
           case Constants.ELEMNAME_CSSSTYLECONVERSION:
  @@ -563,7 +563,7 @@
             // break;
   
           case Constants.ELEMNAME_STYLESHEET:
  -          m_stylesheet.m_isWrapperless = false;
  +          m_stylesheet.getTemplateList().setIsWrapperless(false);
             m_foundStylesheet = true;
             int nAttrs = atts.getLength();
             boolean didSpecifiyIndent = false;
  @@ -616,7 +616,7 @@
               }
               else if(!(isAttrOK(aname, atts, i) || processSpaceAttr(aname, 
atts, i)))
               {
  -              if(false == m_stylesheet.m_isWrapperless)
  +              if(false == m_stylesheet.getTemplateList().getIsWrapperless())
                 {
                   throw new 
SAXException(XSLMessages.createMessage(XSLTErrorResources.ERROR0066, new 
Object[]{name, aname})); //"(StylesheetHandler) "+name+" has an illegal 
attribute: "+aname);
                 }      
  @@ -1134,9 +1134,9 @@
       m_template.appendChild(elem);
       m_inTemplate = true;
   
  -    m_stylesheet.m_wrapperlessTemplate = m_template;
  +    m_stylesheet.getTemplateList().setWrapperlessTemplate(m_template);
  +    m_stylesheet.getTemplateList().setIsWrapperless(true);
       m_foundStylesheet = true;
  -    m_stylesheet.m_isWrapperless = true;
       if(name.equals("HTML"))
       {
         m_stylesheet.m_stylesheetRoot.m_indentResult = true;
  
  
  
  1.1                  xml-xalan/src/org/apache/xalan/xslt/TemplateList.java
  
  Index: TemplateList.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "XSLT4J" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xalan.xslt;
  
  import java.util.Hashtable;
  import org.w3c.dom.Node;
  import org.apache.xalan.xpath.xml.QName;
  import org.xml.sax.SAXException;
  import java.util.Vector;
  import java.io.Serializable;
  import org.apache.xalan.xpath.XPath;
  import org.apache.xalan.xslt.res.XSLTErrorResources;
  
  /**
   * This class segregates the template list, and performs template 
   * finding services.
   */
  public class TemplateList
  {
    /**
     * Construct a TemplateList object.
     */
    TemplateList(Stylesheet stylesheet)
    {
      m_stylesheet = stylesheet;
    }
    
    /**
     * The stylesheet owner of the list.
     */
    Stylesheet m_stylesheet;
    
    /**
     * The first template of the template children.
     * @serial
     */
    ElemTemplateElement m_firstTemplate = null;
  
    /**
     * Get the first template of the template children.
     */
    public ElemTemplateElement getFirstTemplate()
    {
      return m_firstTemplate;
    }
  
    /**
     * Set the first template of the template children.
     */
    public void setFirstTemplate(ElemTemplateElement v)
    {
      m_firstTemplate = v;
    }
  
    /**
     * Keyed on string macro names, and holding values 
     * that are macro elements in the XSL DOM tree.
     * Initialized in initMacroLookupTable, and used in
     * findNamedTemplate.
     * @serial
     */
    Hashtable m_namedTemplates = new Hashtable();
    
    /**
     * Tells if the stylesheet is without an xsl:stylesheet 
     * and xsl:template wrapper.
     * @serial
     */
    private boolean m_isWrapperless = false;
    
    /**
     * The manufactured template if there is no wrapper.
     * @serial
     */
    private ElemTemplate m_wrapperlessTemplate = null;
    
    /**
     * This table is keyed on the target elements 
     * of patterns, and contains linked lists of
     * the actual patterns that match the target element
     * to some degree of specifity.
     * @serial
     */
    private Hashtable m_patternTable = new Hashtable();
    
    /**
     * Set if the stylesheet is without an xsl:stylesheet 
     * and xsl:template wrapper.
     */
    void setIsWrapperless(boolean b)
    {
      m_isWrapperless = b;
    }
  
    /**
     * Get if the stylesheet is without an xsl:stylesheet 
     * and xsl:template wrapper.
     */
    boolean getIsWrapperless()
    {
      return m_isWrapperless;
    }
  
    /**
     * Set the manufactured template if there is no wrapper.
     * and xsl:template wrapper.
     */
    void setWrapperlessTemplate(ElemTemplate t)
    {
      m_wrapperlessTemplate = t;
    }
  
    /**
     * Get the manufactured template if there is no wrapper.
     * and xsl:template wrapper.
     */
    ElemTemplate getWrapperlessTemplate()
    {
      return m_wrapperlessTemplate;
    }
  
    /**
     * Get table of named Templates.
     * These are keyed on string macro names, and holding values 
     * that are template elements in the XSL DOM tree.
     */
    public Hashtable getNamedTemplates()
    {
      return m_namedTemplates;
    }
  
    /**
     * Set table of named Templates.
     * These are keyed on string macro names, and holding values 
     * that are template elements in the XSL DOM tree.
     */
    public void setNamedTemplates(Hashtable v)
    {
      m_namedTemplates = v;
    }
    
    /**
     * Given a target element, find the template that best 
     * matches in the given XSL document, according 
     * to the rules specified in the xsl draft. 
     * @param stylesheetTree Where the XSL rules are to be found.
     * @param sourceTree Where the targetElem is to be found.
     * @param targetElem The element that needs a rule.
     * @param mode A string indicating the display mode.
     * @param useImports means that this is an xsl:apply-imports commend.
     * @param foundStylesheet If non-null, the Stylesheet that the found 
template
     * belongs to will be returned in the foundStylesheet[0].
     * @return Rule that best matches targetElem.
     * @exception XSLProcessorException thrown if the active ProblemListener 
and XMLParserLiaison decide 
     * the error condition is severe enough to halt processing.
     */
    public ElemTemplate findTemplate(XSLTEngineImpl transformContext,
                                     Node sourceTree, 
                                     Node targetNode, 
                                     QName mode,
                                     boolean useImports,
                                     Stylesheet foundStylesheet[])
      throws SAXException
    {
      ElemTemplate bestMatchedRule = null;
      MatchPattern2 bestMatchedPattern =null; // Syncs with bestMatchedRule
      if(m_isWrapperless)
      {
        return m_wrapperlessTemplate;
      }
      Vector conflicts = null;
      if(!useImports)
      {
        double highScore = XPath.MATCH_SCORE_NONE;
        
        MatchPattern2 matchPat = null;
        int targetNodeType = targetNode.getNodeType();
        
        switch(targetNodeType)
        {
        case Node.ELEMENT_NODE:
          // String targetName = 
m_parserLiaison.getExpandedElementName((Element)targetNode);
          String targetName = 
transformContext.m_parserLiaison.getLocalNameOfNode(targetNode);
          matchPat = locateMatchPatternList2(targetName, true);
          break;
          
        case Node.PROCESSING_INSTRUCTION_NODE:
        case Node.ATTRIBUTE_NODE:
          matchPat = locateMatchPatternList2(targetNode.getNodeName(), true);
          break;
  
        case Node.CDATA_SECTION_NODE:
        case Node.TEXT_NODE:
          matchPat = locateMatchPatternList2(XPath.PSEUDONAME_TEXT, false);
          break;
  
        case Node.COMMENT_NODE:
          matchPat = locateMatchPatternList2(XPath.PSEUDONAME_COMMENT, false);
          break;
  
        case Node.DOCUMENT_NODE:
          matchPat = locateMatchPatternList2(XPath.PSEUDONAME_ROOT, false);
          break;
  
        case Node.DOCUMENT_FRAGMENT_NODE:
          matchPat = locateMatchPatternList2(XPath.PSEUDONAME_ANY, false);
          break;
          
        default:
          {
            matchPat = locateMatchPatternList2(targetNode.getNodeName(), false);
          }
        }
        
        String prevPat = null;
        MatchPattern2 prevMatchPat = null;
        
        while(null != matchPat)
        {
          ElemTemplate rule = matchPat.getTemplate();
          // We'll be needing to match rules according to what 
          // mode we're in.
          QName ruleMode = rule.m_mode;
          
          // The logic here should be that if we are not in a mode AND
          // the rule does not have a node, then go ahead.
          // OR if we are in a mode, AND the rule has a node, 
          // AND the rules match, then go ahead.
          if(((null == mode) && (null == ruleMode)) || 
             ((null != ruleMode) && (null != mode) && ruleMode.equals(mode)))
          {
            String patterns = matchPat.getPattern();
            
            if((null != patterns) && !((prevPat != null) && 
prevPat.equals(patterns) && 
                                       (prevMatchPat.getTemplate().m_priority 
                                        == matchPat.getTemplate().m_priority)) )
            {
              prevMatchPat = matchPat;
              prevPat = patterns;
              
              // Date date1 = new Date();
              XPath xpath = matchPat.getExpression();
              // System.out.println("Testing score for: 
"+targetNode.getNodeName()+
              //                   " against '"+xpath.m_currentPattern);
              double score = 
xpath.getMatchScore(transformContext.getExecContext(), targetNode);
              // System.out.println("Score for: "+targetNode.getNodeName()+
              //                   " against '"+xpath.m_currentPattern+
              //                   "' returned "+score);
  
              if(XPath.MATCH_SCORE_NONE != score)
              {
                double priorityOfRule 
                  = (XPath.MATCH_SCORE_NONE != rule.m_priority) 
                    ? rule.m_priority : score;
                matchPat.m_priority = priorityOfRule;
                double priorityOfBestMatched = (null != bestMatchedPattern) ?
                                               bestMatchedPattern.m_priority : 
                                               XPath.MATCH_SCORE_NONE;
                // System.out.println("priorityOfRule: "+priorityOfRule+", 
priorityOfBestMatched: "+priorityOfBestMatched);
                if(priorityOfRule > priorityOfBestMatched)
                {
                  if(null != conflicts)
                    conflicts.removeAllElements();
                  highScore = score;
                  bestMatchedRule = rule;
                  bestMatchedPattern = matchPat;
                }
                else if(priorityOfRule == priorityOfBestMatched)
                {
                  if(null == conflicts)
                    conflicts = new Vector(10);
                  addObjectIfNotFound(bestMatchedPattern, conflicts);
                  conflicts.addElement(matchPat);
                  highScore = score;
                  bestMatchedRule = rule;
                  bestMatchedPattern = matchPat;
                }
              }
              // Date date2 = new Date();
              // m_totalTimePatternMatching+=(date2.getTime() - 
date1.getTime());
            } // end if(null != patterns)            
          } // end if if(targetModeString.equals(mode))
          
          MatchPattern2 nextMatchPat = matchPat.getNext();
  
          // We also have to consider wildcard matches.
          if((null == nextMatchPat) && !matchPat.m_targetString.equals("*") && 
             ((Node.ELEMENT_NODE == targetNodeType) || 
              (Node.ATTRIBUTE_NODE == targetNodeType) ||
              (Node.PROCESSING_INSTRUCTION_NODE == targetNodeType)))
          {
            nextMatchPat = (MatchPattern2)m_patternTable.get("*");
          }
          matchPat = nextMatchPat;
        }
      } // end if(!useImports)
      
      if(null == bestMatchedRule)
      {
        int nImports = m_stylesheet.m_imports.size();
        for(int i = 0; i < nImports; i++)
        {
          Stylesheet stylesheet = 
(Stylesheet)m_stylesheet.m_imports.elementAt(i);
          bestMatchedRule = stylesheet.findTemplate(transformContext, 
sourceTree, targetNode, mode, 
                                                    false, foundStylesheet);
          if(null != bestMatchedRule)
          {
            break;
          }
        }
      }
  
      if(null != conflicts)
      {
        int nConflicts = conflicts.size();
        // System.out.println("nConflicts: "+nConflicts);
        String conflictsString = (!transformContext.m_quietConflictWarnings) 
                                 ? "" : null;
        for(int i = 0; i < nConflicts; i++)
        {
          MatchPattern2 conflictPat = (MatchPattern2)conflicts.elementAt(i);
          if(0 != i)
          {
            if(!transformContext.m_quietConflictWarnings)
              conflictsString += ", ";
            
            // Find the furthest one towards the bottom of the document.
            if(conflictPat.m_posInStylesheet > 
bestMatchedPattern.m_posInStylesheet)
            {
              bestMatchedPattern = conflictPat;
            }
          }
          else
          {
            bestMatchedPattern = conflictPat;
          }
          if(!transformContext.m_quietConflictWarnings)
            conflictsString += "\""+conflictPat.getPattern()+"\"";
        }
        bestMatchedRule = bestMatchedPattern.getTemplate();
        if(!transformContext.m_quietConflictWarnings)
        {
          //conflictsString += " ";
          //conflictsString += "Last found in stylesheet will be used.";
          transformContext.warn(XSLTErrorResources.WARNING0012, new Object[] 
{conflictsString});
        }
      }
  
      if((null != bestMatchedPattern) && (null != foundStylesheet))
      {
        foundStylesheet[0] = bestMatchedPattern.m_stylesheet;
      }
      
      return bestMatchedRule;
    } // end findTemplate
    
    /**
     * Add object to vector if not already there.
     */
    void addObjectIfNotFound(Object obj, Vector v)
    {
      int n = v.size();
      boolean addIt = true;
      for(int i = 0; i < n; i++)
      {
        if(v.elementAt(i) == obj)
        {
          addIt = false;
          break;
        }
      }
      if(addIt)
      {
        v.addElement(obj);
      }
    }
    
    /**
     * Given an element type, locate the start of a linked list of 
     * possible template matches.
     */
    private MatchPattern2 locateMatchPatternList2(String sourceElementType, 
boolean tryWildCard)
    {
      MatchPattern2 startMatchList = null;
      Object val = m_patternTable.get(sourceElementType);
      if(null != val)
      {
        startMatchList = (MatchPattern2)val;
      }
      else if(tryWildCard)
      {
        val = m_patternTable.get("*");
        if(null != val)
        {
          startMatchList = (MatchPattern2)val;
        }
      }
      return startMatchList;
    }
    
    /**
     * Add a template to the template list.
     */
    void addTemplate(ElemTemplate template)
    {
      int pos = 0;
      if(null == m_firstTemplate)
      {
        m_firstTemplate = template;
      }
      else
      {
        ElemTemplateElement next = m_firstTemplate;
        while(null != next)
        {
          if(null == next.m_nextSibling)
          {
            next.m_nextSibling = template;
            template.m_nextSibling = null; // just to play it safe.
            break;
          }
          pos++;
          next = next.m_nextSibling;
        }
      }
      if(null != template.m_name)
      {
        m_namedTemplates.put(template.m_name, template);
      }
      
      if(null != template.m_matchPattern)
      {
        Vector strings = template.m_matchPattern.getTargetElementStrings();
        if(null != strings)
        {
          int nTargets = strings.size();
          for(int stringIndex = 0; stringIndex < nTargets; stringIndex++) 
          {
            String target = (String)strings.elementAt(stringIndex);
            
            Object newMatchPat = new 
MatchPattern2(template.m_matchPattern.m_currentPattern, 
                                                   template.m_matchPattern, 
                                                   template, pos, 
                                                   target, m_stylesheet);
            
            // See if there's already one there
            Object val = m_patternTable.get(target);
            if(null == val)
            {
              // System.out.println("putting: "+target);
              m_patternTable.put(target, newMatchPat);
            }
            else
            {
              // find the tail of the list
              MatchPattern2 matchPat = (MatchPattern2)val;
              ((MatchPattern2)newMatchPat).setNext(matchPat);
              m_patternTable.put(target, newMatchPat);
              /*
              MatchPattern2 next;
              while((next = matchPat.getNext()) != null)
              {
              matchPat = next;
              }
              // System.out.println("appending: "+target+" to 
"+matchPat.getPattern());
              matchPat.setNext((MatchPattern2)newMatchPat);
              */
            }
          }
        }
      }
    }
    
    /**
     * Locate a macro via the "name" attribute.
     * @exception XSLProcessorException thrown if the active ProblemListener 
and XMLParserLiaison decide 
     * the error condition is severe enough to halt processing.
     */
    ElemTemplateElement findNamedTemplate(String name)
      throws XSLProcessorException
    {
      QName qname = new QName(name, m_stylesheet.m_namespaces);
      
      return findNamedTemplate(qname);
    }
    
    /**
     * Locate a macro via the "name" attribute.
     * @exception XSLProcessorException thrown if the active ProblemListener 
and XMLParserLiaison decide 
     * the error condition is severe enough to halt processing.
     */
    ElemTemplateElement findNamedTemplate(QName qname)
      throws XSLProcessorException
    {
      ElemTemplateElement namedTemplate = null;
      Object obj = m_namedTemplates.get(qname);
      if(null == obj)
      {
        int nImports = m_stylesheet.m_imports.size();
        for(int i = 0; i < nImports; i++)
        {
          Stylesheet stylesheet = 
(Stylesheet)m_stylesheet.m_imports.elementAt(i);
          namedTemplate = stylesheet.findNamedTemplate(qname);
          if(null != namedTemplate)
          {
            break;
          }
        }
        if((null == namedTemplate) && (null != m_stylesheet.m_stylesheetParent))
        {
          Stylesheet stylesheet = 
m_stylesheet.m_stylesheetParent.getPreviousImport(m_stylesheet);
          if(null != stylesheet)
          {
            namedTemplate = stylesheet.findNamedTemplate(qname);
          }
        }
      }
      else
      {
        namedTemplate = (ElemTemplateElement)obj;
      }
      
      return namedTemplate;
    }
    
    /**
     * A class to contain a match pattern and it's corresponding template.
     * This class also defines a node in a match pattern linked list.
     */
    class MatchPattern2 implements Serializable
    {
      /**
       * Construct a match pattern from a pattern and template.
       * @param pat For now a Nodelist that contains old-style element patterns.
       * @param template The node that contains the template for this pattern.
       * @param isMatchPatternsOnly tells if pat param contains only match 
       * patterns (for compatibility with old syntax).
       */
      MatchPattern2(String pat, XPath exp, ElemTemplate template, int 
posInStylesheet, 
                    String targetString, Stylesheet stylesheet)
      {
        m_pattern = pat;
        m_template = template;
        m_posInStylesheet = posInStylesheet;
        m_targetString = targetString;
        m_stylesheet = stylesheet;
        m_expression = exp;
      }
      
      Stylesheet m_stylesheet;
  
      String m_targetString;
      
      XPath m_expression;
      public XPath getExpression() { return m_expression; }
  
      int m_posInStylesheet;
      
      /**
       * Transient... only used to track priority while 
       * processing.
       */
      double m_priority = XPath.MATCH_SCORE_NONE;
      
      private String m_pattern;
      public String getPattern() { return m_pattern; }
      
      private ElemTemplate m_template; // ref to the corrisponding template
      public ElemTemplate getTemplate() { return m_template; }
  
      private MatchPattern2 m_next = null; // null when at end of list.
      public MatchPattern2 getNext() { return m_next; }
      public void setNext(MatchPattern2 mp) { m_next = mp; }
    }
  
  }
  
  
  

Reply via email to