/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library 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.1 of the License, or (at your option) any later version. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.query.processor.xml; import java.util.Properties; import org.teiid.core.TeiidComponentException; import org.teiid.query.QueryPlugin; import org.teiid.query.mapping.xml.MappingAttribute; import org.teiid.query.mapping.xml.MappingElement; import org.teiid.query.mapping.xml.MappingNode; import org.teiid.query.mapping.xml.MappingNodeConstants; import org.teiid.query.sql.symbol.ElementSymbol; /** * THis class contains the information of an element or an attribute. * @since 4.3 */ public class NodeDescriptor { public static final String DEFAULT_NAMESPACE_URI = ""; //$NON-NLS-1$ //namespace prefix private String namespacePrefix; //namespace URI private String namespaceURI; //name without prefix private String name; //name with prefix private String qName; //declared namespace URIs //The property names should be String namespace prefixes, and the //corresponding values should be String namespace uri's. A default //namespace may be contained within this Properties object by mapping the //DEFAULT_NAMESPACE_PREFIX constant to a String uri. An empty default namespace //may be contained by mapping that constant to an empty String - this //has the effect of locally having NO namespace by default. //These namespace declarations hold for the scope of this element (the element itself and its contents). private Properties namespaceURIs; //For element, it indicates that this element is not nillable or //has a min occurs of zero, and may not have to be output in the final document (unless //it has string content or child elements that must be in the document). //For attribute, it indicates that this attribute should be considered //optional and does not have to be output if the element containing this //attribute is also optional and ends up with no child content. This //is to enable fragments with attributes but no child element content to be //trimmed from the result document. private boolean isOptional; //true if it is element private boolean isElement; //default value private String defaultValue; // text normalization mode // and can be one of the following // preserve, replace and collapse. private String textNormalizationMode; private Class runtimeType; private String docBuiltInType; public NodeDescriptor(String name, String qName, String namespacePrefix, String namespaceURI, Properties namespaceURIs, String defaultValue, boolean isOptional, boolean isElement, String textNormalizationMode, Class runtimeType, String docBuiltInType) { this.name = name; this.qName = qName; this.namespaceURI = namespaceURI; this.namespaceURIs = namespaceURIs; this.isOptional = isOptional; this.namespacePrefix = namespacePrefix; this.defaultValue = defaultValue; this.isElement = isElement; this.textNormalizationMode = textNormalizationMode; this.runtimeType = runtimeType; this.docBuiltInType = docBuiltInType; } /** * @return Returns the isOptional. * @since 4.3 */ public boolean isOptional() { return this.isOptional; } /** * @return Returns the name. * @since 4.3 */ public String getName() { return this.name; } /** * @return Returns the namespaceURI. * @since 4.3 */ public String getNamespaceURI() { return this.namespaceURI; } /** * @return Returns the namespaceURIs. * @since 4.3 */ public Properties getNamespaceURIs() { return this.namespaceURIs; } /** * @return Returns the qName. * @since 4.3 */ public String getQName() { return this.qName; } /** * @return Returns the isElement. * @since 4.3 */ public boolean isElement() { return this.isElement; } /** * @return Returns the defaultValue. * @since 4.3 */ public String getDefaultValue() { return this.defaultValue; } /** * @return Returns the namespacePrefix. * @since 4.3 */ public String getNamespacePrefix() { return this.namespacePrefix; } /** * @return Returns the textNormalizationMode. * @since 4.3 */ public String getTextNormalizationMode() { return this.textNormalizationMode; } /** * @param textNormalizationMode The textNormalizationMode to set. * @since 4.3 */ public void setTextNormalizationMode(String textNormalizationMode) { this.textNormalizationMode = textNormalizationMode; } public Class getRuntimeType() { return this.runtimeType; } public String getDocBuiltInType() { return this.docBuiltInType; } public static NodeDescriptor createNodeDescriptor(MappingElement element) { // should't this be if nillable it is optional ? boolean isOptional = false; if (element.getMinOccurence() == 0 && !element.isNillable()){ isOptional = true; } String docBuiltInType = element.getType(); if(docBuiltInType == MappingNodeConstants.NO_TYPE) { docBuiltInType = null; } ElementSymbol symbol = element.getElementSymbol(); NodeDescriptor descriptor = new NodeDescriptor(element.getName(), getQName(element.getName(),element.getNamespacePrefix()), element.getNamespace().getPrefix(), element.getNamespace().getUri(), element.getNamespacesAsProperties(), ((symbol != null)?element.getDefaultValue():element.getValue()), isOptional, true, element.getNormalizeText(), ((symbol != null)?symbol.getType():null), docBuiltInType); return descriptor; } public static NodeDescriptor createNillableNode() { return new NodeDescriptor("nil", //$NON-NLS-1$ getQName("nil", MappingNodeConstants.INSTANCES_NAMESPACE_PREFIX), //$NON-NLS-1$ MappingNodeConstants.INSTANCES_NAMESPACE_PREFIX, MappingNodeConstants.INSTANCES_NAMESPACE, null, "true", //$NON-NLS-1$ false, // is optional false, // is element MappingNodeConstants.NORMALIZE_TEXT_PRESERVE, null, null); } public static NodeDescriptor createNodeDescriptor(MappingAttribute attribute) { ElementSymbol symbol = attribute.getElementSymbol(); // create processing instruction based on the info NodeDescriptor descriptor = new NodeDescriptor(attribute.getName(), getQName(attribute.getName(), attribute.getNamespacePrefix()), attribute.getNamespace().getPrefix(), attribute.getNamespace().getUri(), null, ((symbol != null)?attribute.getDefaultValue():attribute.getValue()), attribute.isOptional(), false, attribute.getNormalizeText(), ((symbol != null)?symbol.getType():null), null); return descriptor; } public static NodeDescriptor createNodeDescriptor(String name, String namespacePrefix, boolean isElement, String defaultValue, Properties namespaceDeclarations, Properties parentNamespaceDeclarations,boolean isOptional, MappingNode node, String textNormalizationMode) throws TeiidComponentException{ return createNodeDescriptor(name, namespacePrefix, isElement, defaultValue, namespaceDeclarations, parentNamespaceDeclarations, isOptional, node, textNormalizationMode, null, null); } public static NodeDescriptor createNodeDescriptor(String name, String namespacePrefix, boolean isElement, String defaultValue, Properties namespaceDeclarations, Properties parentNamespaceDeclarations,boolean isOptional, MappingNode node, String textNormalizationMode, Class runtimeType, String docBuiltInType) throws TeiidComponentException{ //get namespace uri String uri = null; if(namespacePrefix == null) { namespacePrefix = MappingNodeConstants.DEFAULT_NAMESPACE_PREFIX; }else { if(namespaceDeclarations != null) { uri = namespaceDeclarations.getProperty(namespacePrefix); } if(parentNamespaceDeclarations != null) { uri = parentNamespaceDeclarations.getProperty(namespacePrefix); } if(uri == null){ //look for namespace in ancester nodes MappingNode parent; while((parent = node.getParent()) != null){ parentNamespaceDeclarations= (Properties)parent.getProperty(MappingNodeConstants.Properties.NAMESPACE_DECLARATIONS); if(parentNamespaceDeclarations != null) { uri = parentNamespaceDeclarations.getProperty(namespacePrefix); if(uri != null) { break; } } node = parent; } } } if(uri == null) { if(namespacePrefix.equals(MappingNodeConstants.DEFAULT_NAMESPACE_PREFIX)) { uri = NodeDescriptor.DEFAULT_NAMESPACE_URI; } else if(namespacePrefix.equals(MappingNodeConstants.INSTANCES_NAMESPACE_PREFIX)) { uri = MappingNodeConstants.INSTANCES_NAMESPACE; }else { String msg = QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30213, new Object[] {namespacePrefix, name}); throw new TeiidComponentException(QueryPlugin.Event.TEIID30213, msg); } } //create NodeDescriptor NodeDescriptor descriptor = new NodeDescriptor(name, getQName(name, namespacePrefix), namespacePrefix, uri, namespaceDeclarations, defaultValue, isOptional, isElement, textNormalizationMode, runtimeType, docBuiltInType); return descriptor; } //get qualified name (with namespace) private static String getQName(String name, String prefix){ if(prefix != null && prefix.length() > 0){ name = prefix + ":" + name; //$NON-NLS-1$ } return name; } }