001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: TemplateSubPatternAssociation.java 468643 2006-10-28 06:56:03Z minchau $
020     */
021    package org.apache.xalan.templates;
022    
023    import java.io.Serializable;
024    
025    import javax.xml.transform.TransformerException;
026    
027    import org.apache.xml.utils.QName;
028    import org.apache.xpath.XPath;
029    import org.apache.xpath.XPathContext;
030    import org.apache.xpath.patterns.StepPattern;
031    
032    /**
033     * A class to contain a match pattern and it's corresponding template.
034     * This class also defines a node in a match pattern linked list.
035     */
036    class TemplateSubPatternAssociation implements Serializable, Cloneable
037    {
038        static final long serialVersionUID = -8902606755229903350L;
039    
040      /** Step pattern           */
041      StepPattern m_stepPattern;
042    
043      /** Template pattern          */
044      private String m_pattern;
045    
046      /** The template element         */
047      private ElemTemplate m_template;
048    
049      /** Next pattern         */
050      private TemplateSubPatternAssociation m_next = null;
051    
052      /** Flag indicating whether this is wild card pattern          */
053      private boolean m_wild;
054    
055      /** Target string for this match pattern           */
056      private String m_targetString;
057    
058      /**
059       * Construct a match pattern from a pattern and template.
060       * @param template The node that contains the template for this pattern.
061       * @param pattern An executable XSLT StepPattern.
062       * @param pat For now a Nodelist that contains old-style element patterns.
063       */
064      TemplateSubPatternAssociation(ElemTemplate template, StepPattern pattern, String pat)
065      {
066    
067        m_pattern = pat;
068        m_template = template;
069        m_stepPattern = pattern;
070        m_targetString = m_stepPattern.getTargetString();
071        m_wild = m_targetString.equals("*");
072      }
073    
074      /**
075       * Clone this object.
076       *
077       * @return The cloned object.
078       *
079       * @throws CloneNotSupportedException
080       */
081      public Object clone() throws CloneNotSupportedException
082      {
083    
084        TemplateSubPatternAssociation tspa =
085          (TemplateSubPatternAssociation) super.clone();
086    
087        tspa.m_next = null;
088    
089        return tspa;
090      }
091    
092      /**
093       * Get the target string of the pattern.  For instance, if the pattern is
094       * "foo/baz/boo[@daba]", this string will be "boo".
095       *
096       * @return The "target" string.
097       */
098      public final String getTargetString()
099      {
100        return m_targetString;
101      }
102    
103      /**
104       * Set Target String for this template pattern  
105       *
106       *
107       * @param key Target string to set
108       */
109      public void setTargetString(String key)
110      {
111        m_targetString = key;
112      }
113    
114      /**
115       * Tell if two modes match according to the rules of XSLT.
116       *
117       * @param m1 mode to match
118       *
119       * @return True if the given mode matches this template's mode
120       */
121      boolean matchMode(QName m1)
122      {
123        return matchModes(m1, m_template.getMode());
124      }
125    
126      /**
127       * Tell if two modes match according to the rules of XSLT.
128       *
129       * @param m1 First mode to match
130       * @param m2 Second mode to match
131       *
132       * @return True if the two given modes match
133       */
134      private boolean matchModes(QName m1, QName m2)
135      {
136        return (((null == m1) && (null == m2))
137                || ((null != m1) && (null != m2) && m1.equals(m2)));
138      }
139    
140      /**
141       * Return the mode associated with the template.
142       *
143       *
144       * @param xctxt XPath context to use with this template
145       * @param targetNode Target node
146       * @param mode reference, which may be null, to the <a href="http://www.w3.org/TR/xslt#modes">current mode</a>.
147       * @return The mode associated with the template.
148       *
149       * @throws TransformerException
150       */
151      public boolean matches(XPathContext xctxt, int targetNode, QName mode)
152              throws TransformerException
153      {
154    
155        double score = m_stepPattern.getMatchScore(xctxt, targetNode);
156    
157        return (XPath.MATCH_SCORE_NONE != score)
158               && matchModes(mode, m_template.getMode());
159      }
160    
161      /**
162       * Tell if the pattern for this association is a wildcard.
163       *
164       * @return true if this pattern is considered to be a wild match.
165       */
166      public final boolean isWild()
167      {
168        return m_wild;
169      }
170    
171      /**
172       * Get associated XSLT StepPattern.
173       *
174       * @return An executable StepPattern object, never null.
175       *
176       */
177      public final StepPattern getStepPattern()
178      {
179        return m_stepPattern;
180      }
181    
182      /**
183       * Get the pattern string for diagnostic purposes.
184       *
185       * @return The pattern string for diagnostic purposes.
186       *
187       */
188      public final String getPattern()
189      {
190        return m_pattern;
191      }
192    
193      /**
194       * Return the position of the template in document
195       * order in the stylesheet.
196       *
197       * @return The position of the template in the overall template order.
198       */
199      public int getDocOrderPos()
200      {
201        return m_template.getUid();
202      }
203    
204      /**
205       * Return the import level associated with the stylesheet into which  
206       * this template is composed.
207       *
208       * @return The import level of this template.
209       */
210      public final int getImportLevel()
211      {
212        return m_template.getStylesheetComposed().getImportCountComposed();
213      }
214    
215      /**
216       * Get the assocated xsl:template.
217       *
218       * @return An ElemTemplate, never null.
219       *
220       */
221      public final ElemTemplate getTemplate()
222      {
223        return m_template;
224      }
225    
226      /**
227       * Get the next association.
228       *
229       * @return A valid TemplateSubPatternAssociation, or null.
230       */
231      public final TemplateSubPatternAssociation getNext()
232      {
233        return m_next;
234      }
235    
236      /**
237       * Set the next element on this association
238       * list, which should be equal or less in priority to
239       * this association, and, if equal priority, should occur
240       * before this template in document order.
241       *
242       * @param mp The next association to score if this one fails.
243       *
244       */
245      public void setNext(TemplateSubPatternAssociation mp)
246      {
247        m_next = mp;
248      }
249    }