1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 #if !defined(XALANQNAME_HEADER_GUARD_1357924680)
19 #define XALANQNAME_HEADER_GUARD_1357924680
20
21
22
23 // Base header file. Must be first.
24 #include <xalanc/XPath/XPathDefinitions.hpp>
25
26
27
28 #include <xalanc/Include/XalanMap.hpp>
29 #include <xalanc/Include/XalanDeque.hpp>
30 #include <xalanc/Include/STLHelper.hpp>
31
32
33
34 #include <xalanc/XalanDOM/XalanDOMString.hpp>
35
36
37
38 #include <xalanc/PlatformSupport/DOMStringHelper.hpp>
39 #include <xalanc/PlatformSupport/PrefixResolver.hpp>
40
41
42
43 #include <xalanc/XPath/NameSpace.hpp>
44 #include <xalanc/XPath/XalanXPathException.hpp>
45
46
47
48 namespace XALAN_CPP_NAMESPACE {
49
50
51
52 class XalanElement;
53 class XPathEnvSupport;
54
55
56
57 /**
58 * Class to represent a qualified name. The name of an internal XSLT object,
59 * specifically a named template (see [7 Named Templates]), a mode (see [6.7 Modes]),
60 * an attribute set (see [8.1.4 Named Attribute Sets]), a key (see [14.2 Keys]),
61 * a locale (see [14.3 Number Formatting]), a variable or a parameter (see
62 * [12 Variables and Parameters]) is specified as a QName. If it has a prefix,
63 * then the prefix is expanded into a URI reference using the namespace declarations
64 * in effect on the attribute in which the name occurs. The expanded name
65 * consisting of the local part of the name and the possibly null URI reference
66 * is used as the name of the object. The default namespace is not used for
67 * unprefixed names.
68 */
69
70 class XALAN_XPATH_EXPORT XalanQName
71 {
72 public:
73
74 typedef XalanDeque<NameSpace, ConstructWithMemoryManagerTraits<NameSpace> >
75 NamespaceVectorType;
76 typedef XalanDeque<NamespaceVectorType, ConstructWithMemoryManagerTraits<NamespaceVectorType> >
77 NamespacesStackType;
78
79 /**
80 * Construct an empty XalanQName.
81 *
82 */
83 explicit
XalanQName()84 XalanQName()
85 {
86 }
87
88 virtual
~XalanQName()89 ~XalanQName()
90 {
91 }
92
XalanQName(const XalanQName &)93 XalanQName(const XalanQName&)
94 {
95 }
96
97 /**
98 * Retrieve the local part of qualified name.
99 *
100 * @return local part string
101 */
102 virtual const XalanDOMString&
103 getLocalPart() const = 0;
104
105 /**
106 * Retrieve the namespace of qualified name.
107 *
108 * @return namespace string
109 */
110 virtual const XalanDOMString&
111 getNamespace() const = 0;
112
113 /**
114 * Determine if the qualified name is valid.
115 *
116 * @return true if the instance is a valid QName, false if not.
117 */
118 bool
isValid() const119 isValid() const
120 {
121 return isValidNCName(getLocalPart());
122 }
123
124 /**
125 * Whether the qualified name is empty.
126 *
127 * @return true if namespace and local part are both empty
128 */
129 bool
isEmpty() const130 isEmpty() const
131 {
132 return getNamespace().empty() && getLocalPart().empty();
133 }
134
135 /**
136 * Override equals and agree that we're equal if the passed object is a
137 * string and it matches the name of the arg.
138 *
139 * @param theRHS namespace to compare
140 * @return true if namespace and local part are both empty
141 */
142 bool
equals(const XalanQName & theRHS) const143 equals(const XalanQName& theRHS) const
144 {
145 // Note that we do not use our member variables here. See
146 // class QNameReference for details...
147 return getLocalPart() == theRHS.getLocalPart() &&
148 getNamespace() == theRHS.getNamespace();
149 }
150
151 /**
152 * Format the QName using the notation "{namespace-uri}local-part" or
153 * "local-part" if the namespace URI is empty. The result is appended
154 * to the provided string.
155 *
156 * @param theString The string to format with the
157 * @return A reference to the parameter.
158 */
159 XalanDOMString&
160 format(XalanDOMString& theString) const;
161
162 size_t
hash() const163 hash() const
164 {
165 return getLocalPart().hash() % (getNamespace().hash() + 1);
166 }
167
168 class XALAN_XPATH_EXPORT PrefixResolverProxy : public PrefixResolver
169 {
170 public:
171
172 /**
173 * Construct a PrefixResolver from a NamespacesStackType
174 * instance.
175 *
176 * @param theStack The stack to use for prefix resolution
177 * @param theURI The namespace URI of the resolver, if any. Only a reference is kept, so this cannot be a temporary
178 * @return pointer to the string value if found, otherwise 0.
179 */
180 PrefixResolverProxy(
181 const NamespacesStackType& theStack,
182 const XalanDOMString& theURI);
183
184 virtual
185 ~PrefixResolverProxy();
186
187 virtual const XalanDOMString*
188 getNamespaceForPrefix(const XalanDOMString& prefix) const;
189
190 virtual const XalanDOMString&
191 getURI() const;
192
193 private:
194
195 const NamespacesStackType& m_stack;
196
197 const XalanDOMString& m_uri;
198 };
199
200 /**
201 * Get the namespace for a prefix by searching a vector of namespaces.
202 *
203 * @param namespaces vector of namespaces to search
204 * @param prefix namespace prefix to find
205 * @return pointer to the string value if found, otherwise null.
206 */
207 static const XalanDOMString*
208 getNamespaceForPrefix(
209 const NamespaceVectorType& namespaces,
210 const XalanDOMString& prefix);
211
212 /**
213 * Get the namespace for a prefix by searching a stack of namespace
214 * vectors.
215 *
216 * @param nsStack stack of namespace vectors to search
217 * @param prefix namespace prefix to find
218 * @return pointer to the string value if found, otherwise null.
219 */
220 static const XalanDOMString*
221 getNamespaceForPrefix(
222 const NamespacesStackType& nsStack,
223 const XalanDOMString& prefix);
224
225 static const XalanDOMString*
226 getNamespaceForPrefix(
227 const NamespacesStackType& nsStack,
228 const XalanDOMChar* prefix);
229
230 /**
231 * Get the namespace for a prefix by searching a range of iterators.
232 * The search is done in reverse, from the end of the range to the
233 * beginning.
234 *
235 * @param theBegin The beginning iterator for the range
236 * @param theBegin The ending iterator for the range
237 * @param prefix namespace prefix to find
238 * @return pointer to the string value if found, otherwise null.
239 */
240 static const XalanDOMString*
241 getNamespaceForPrefix(
242 NamespacesStackType::const_iterator theBegin,
243 NamespacesStackType::const_iterator theEnd,
244 const XalanDOMString& prefix);
245
246 /**
247 * Get the prefix for a namespace by searching a vector of namespaces.
248 *
249 * @param namespaces vector of namespaces to search
250 * @param uri URI string for namespace to find
251 * @param reverse true to search vector from last to first, default true
252 * @return pointer to the string value if found, otherwise null.
253 */
254 static const XalanDOMString*
255 getPrefixForNamespace(
256 const NamespaceVectorType& namespaces,
257 const XalanDOMString& uri);
258
259 static const XalanDOMString*
260 getNamespaceForPrefix(
261 const NamespaceVectorType& namespaces,
262 const XalanDOMChar* prefix);
263
264 /**
265 * Get the prefix for a namespace by searching a stack of namespace
266 * vectors.
267 *
268 * @param nsStack stack of namespace vectors to search
269 * @param uri URI string for namespace to find
270 * @return pointer to the string value if found, otherwise null.
271 */
272 static const XalanDOMString*
273 getPrefixForNamespace(
274 const NamespacesStackType& nsStack,
275 const XalanDOMString& uri);
276
277 /**
278 * Get the prefix for a namespace by searching a range of iterators.
279 * The search is done in reverse, from the end of the range to the
280 * beginning.
281 *
282 * @param theBegin The beginning iterator for the range to search
283 * @param theBegin The ending iterator for the range to search
284 * @param uri URI string for namespace to find
285 * @return pointer to the string value if found, otherwise null.
286 */
287 static const XalanDOMString*
288 getPrefixForNamespace(
289 NamespacesStackType::const_iterator theBegin,
290 NamespacesStackType::const_iterator theEnd,
291 const XalanDOMString& uri);
292
293 static const XalanDOMString*
294 getNamespaceForPrefix(
295 NamespacesStackType::const_iterator theBegin,
296 NamespacesStackType::const_iterator theEnd,
297 const XalanDOMChar* prefix);
298 /**
299 * Determine if the string supplied satisfies the grammar for
300 * an XML NCName.
301 *
302 * @param theNCName The string to check
303 * @return bool true if the string is a valid NCName, false if not.
304 */
305 static bool
306 isValidNCName(const XalanDOMString& theNCName);
307
308 /**
309 * Determine if the string supplied satisfies the grammar for
310 * an XML NCName.
311 *
312 * @param theNCName The string to check
313 * @param theLength The length of the string
314 * @return bool true if the string is a valid NCName, false if not
315 */
316 static bool
317 isValidNCName(
318 const XalanDOMChar* theNCName,
319 XalanDOMString::size_type theLength = XalanDOMString::npos);
320
321 /**
322 * Determine if the string supplied satisfies the grammar for
323 * an XML QName. Note that this function does not determine
324 * if any supplied prefix is bound to a namespace URI
325 *
326 * @param theQName The string to check
327 * @return bool true if the string is a valid QName, false if not
328 */
329 static bool
330 isValidQName(const XalanDOMString& theQName);
331
332 /**
333 * Determine if the string supplied satisfies the grammar for
334 * an XML QName. Note that this function does not determine
335 * if any supplied prefix is bound to a namespace URI
336 *
337 * @param theQName The string to check
338 * @param theLength The length of the string
339 * @return bool true if the string is a valid QName, false if not
340 */
341 static bool
342 isValidQName(
343 const XalanDOMChar* theQName,
344 XalanDOMString::size_type theLength = XalanDOMString::npos);
345
346 class InvalidQNameException : public XalanXPathException
347 {
348 public:
349
350 /**
351 * Constructor
352 *
353 * @param theQName The QName string that is not valid.
354 * @param theQNameLength The length of the string.
355 * @param theResult A temporary string for loading the error message.
356 */
357 InvalidQNameException(
358 const XalanDOMChar* theQName,
359 XalanDOMString::size_type theQNameLength,
360 XalanDOMString& theResult,
361 const Locator* theLocator);
362
363 /**
364 * Constructor
365 *
366 * @param theMessage The message for the exception
367 * @param theManager The MemoryManager instance to use when constructing the exception
368 */
369 InvalidQNameException(
370 const XalanDOMString& theMessage,
371 MemoryManager& theManager,
372 const Locator* theLocator);
373
374 InvalidQNameException(const InvalidQNameException& other);
375
376 virtual
377 ~InvalidQNameException();
378
379 virtual const XalanDOMChar*
380 getType() const;
381
382 private:
383
384 static const XalanDOMString&
385 format(
386 const XalanDOMChar* theQName,
387 XalanDOMString::size_type theQNameLength,
388 XalanDOMString& theResult);
389 };
390
391 protected:
392
393 static const XalanDOMString s_emptyString;
394 };
395
396
397 inline bool
operator ==(const XalanQName & theLHS,const XalanQName & theRHS)398 operator==(
399 const XalanQName& theLHS,
400 const XalanQName& theRHS)
401 {
402 return theLHS.equals(theRHS);
403 }
404
405
406
407 inline bool
operator !=(const XalanQName & theLHS,const XalanQName & theRHS)408 operator!=(
409 const XalanQName& theLHS,
410 const XalanQName& theRHS)
411 {
412 return !(theLHS == theRHS);
413 }
414
415
416
417 inline bool
operator <(const XalanQName & theLHS,const XalanQName & theRHS)418 operator<(
419 const XalanQName& theLHS,
420 const XalanQName& theRHS)
421 {
422 if (theLHS.getNamespace() < theRHS.getNamespace())
423 {
424 return true;
425 }
426 else if (equals(theLHS.getNamespace(), theRHS.getNamespace()))
427 {
428 return theLHS.getLocalPart() < theRHS.getLocalPart();
429 }
430 else
431 {
432 return false;
433 }
434 }
435
436 template<>
437 struct XalanMapKeyTraits<XalanQName>
438 {
439 typedef XalanHashMemberReference<XalanQName> Hasher;
440 typedef std::equal_to<XalanQName> Comparator;
441 };
442
443 template<>
444 struct XalanMapKeyTraits<const XalanQName*>
445 {
446 typedef XalanHashMemberPointer<XalanQName> Hasher;
447 typedef pointer_equal<XalanQName> Comparator;
448 };
449
450
451 }
452
453
454
455 #endif // XALANQNAME_HEADER_GUARD_1357924680
456