2 Copyright (C) 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu
.xml
.transform
;
40 import java
.util
.ArrayList
;
41 import java
.util
.Collection
;
42 import java
.util
.Collections
;
43 import java
.util
.Iterator
;
44 import java
.util
.LinkedHashSet
;
45 import java
.util
.LinkedList
;
46 import java
.util
.List
;
47 import javax
.xml
.namespace
.QName
;
48 import javax
.xml
.xpath
.XPathFunction
;
49 import javax
.xml
.xpath
.XPathFunctionException
;
50 import org
.w3c
.dom
.Document
;
51 import org
.w3c
.dom
.Node
;
52 import gnu
.xml
.xpath
.Expr
;
53 import gnu
.xml
.xpath
.Function
;
54 import gnu
.xml
.xpath
.Pattern
;
57 * The XSLT <code>key()</code>function.
59 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
61 final class KeyFunction
63 implements XPathFunction
, Function
66 final Stylesheet stylesheet
;
69 KeyFunction(Stylesheet stylesheet
)
71 this.stylesheet
= stylesheet
;
74 public Object
evaluate(List args
)
75 throws XPathFunctionException
78 return Collections
.EMPTY_SET
;
81 public void setArguments(List args
)
86 public boolean matches(Node context
)
88 Object ret
= evaluate(context
, 1, 1);
89 return !((Collection
) ret
).isEmpty();
92 public Object
evaluate(Node context
, int pos
, int len
)
95 int arity
= args
.size();
96 List values
= new ArrayList(arity
);
97 for (int i
= 0; i
< arity
; i
++)
99 Expr arg
= (Expr
) args
.get(i
);
100 values
.add(arg
.evaluate(context
, pos
, len
));
103 QName keyName
= QName
.valueOf(_string(context
, values
.get(0)));
104 // Expand qualified name
105 String uri
= keyName
.getNamespaceURI();
106 String prefix
= keyName
.getPrefix();
107 if ((uri
== null || uri
.length() == 0) &&
108 (prefix
!= null && prefix
.length() > 0))
110 uri
= stylesheet
.getNamespaceURI(prefix
);
111 if (uri
!= null && uri
.length() > 0)
113 String localName
= keyName
.getLocalPart();
114 keyName
= new QName(uri
, localName
, prefix
);
117 // Compute matching key set
118 Collection keySet
= new LinkedList();
119 for (Iterator i
= stylesheet
.keys
.iterator(); i
.hasNext(); )
121 Key key
= (Key
) i
.next();
122 if (key
.name
.equals(keyName
))
128 Object target
= values
.get(1);
129 Collection acc
= new LinkedHashSet();
130 Document doc
= (context
instanceof Document
) ?
(Document
) context
:
131 context
.getOwnerDocument();
132 if (target
instanceof Collection
)
134 for (Iterator i
= ((Collection
) target
).iterator(); i
.hasNext(); )
136 String val
= Expr
.stringValue((Node
) i
.next());
137 addKeyNodes(doc
, keySet
, val
, acc
);
142 String val
= Expr
._string(context
, target
);
143 addKeyNodes(doc
, keySet
, val
, acc
);
145 List ret
= new ArrayList(acc
);
146 Collections
.sort(ret
, documentOrderComparator
);
150 final void addKeyNodes(Node node
, Collection keySet
,
151 String value
, Collection acc
)
153 addKeyNodeIfMatch(node
, keySet
, value
, acc
);
155 for (Node ctx
= node
.getFirstChild(); ctx
!= null;
156 ctx
= ctx
.getNextSibling())
158 addKeyNodes(ctx
, keySet
, value
, acc
);
162 final void addKeyNodeIfMatch(Node node
, Collection keySet
,
163 String value
, Collection acc
)
165 for (Iterator i
= keySet
.iterator(); i
.hasNext(); )
167 Key key
= (Key
) i
.next();
168 if (key
.match
.matches(node
))
170 Object eval
= key
.use
.evaluate(node
, 1, 1);
171 if (eval
instanceof Collection
)
173 for (Iterator j
= ((Collection
) eval
).iterator();
176 String keyValue
= Expr
.stringValue((Node
) j
.next());
177 if (value
.equals(keyValue
))
186 String keyValue
= Expr
._string(node
, eval
);
187 if (value
.equals(keyValue
))
197 public Expr
clone(Object context
)
199 Stylesheet s
= stylesheet
;
200 if (context
instanceof Stylesheet
)
202 s
= (Stylesheet
) context
;
204 KeyFunction f
= new KeyFunction(s
);
205 int len
= args
.size();
206 List args2
= new ArrayList(len
);
207 for (int i
= 0; i
< len
; i
++)
209 args2
.add(((Expr
) args
.get(i
)).clone(context
));
211 f
.setArguments(args2
);
215 public boolean references(QName var
)
217 for (Iterator i
= args
.iterator(); i
.hasNext(); )
219 if (((Expr
) i
.next()).references(var
))