/* * 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 static org.teiid.query.analysis.AnalysisRecord.*; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Properties; import org.teiid.client.plan.PlanNode; import org.teiid.common.buffer.BlockedException; import org.teiid.core.TeiidComponentException; import org.teiid.core.TeiidProcessingException; import org.teiid.logging.LogManager; import org.teiid.query.QueryPlugin; import org.teiid.query.sql.symbol.ElementSymbol; /** */ public class AddNodeInstruction extends ProcessorInstruction { public static final boolean ELEMENT = true; public static final boolean ATTRIBUTE = false; private NodeDescriptor descriptor; private ElementSymbol symbol; private NodeDescriptor nillableDescriptor; /** * Constructor for AddElementInstruction. * @param tag Tag name * @param namespacePrefix String prefix that maps to a namespace (optional, may be null) * @param isElement indicates an element or an attribute * @param fixedValue * @param namespaceDeclarations * @param isOptional */ public AddNodeInstruction(NodeDescriptor descriptor) { this.descriptor = descriptor; } /** * Constructor for AddElementInstruction. * @param tag Tag name * @param namespacePrefix String prefix that maps to a namespace (optional, may be null) * @param isElement indicates an element or an attribute * @param resultSetName * @param resultSetColumn * @param type * @param defaultValue * @param namespaceDeclarations * @param isOptional */ public AddNodeInstruction(NodeDescriptor descriptor, ElementSymbol symbol) { this.descriptor = descriptor; this.symbol = symbol; } /** * Outputs an element or an attribute, or nothing, based on the state of the instruction. * @see ProcessorInstruction#process(ProcessorEnvironment) */ public XMLContext process(XMLProcessorEnvironment env, XMLContext context) throws BlockedException, TeiidComponentException, TeiidProcessingException{ DocumentInProgress doc = env.getDocumentInProgress(); boolean success = true; boolean isElement = descriptor.isElement(); String defaultValue = descriptor.getDefaultValue(); if(symbol == null) { if (defaultValue != null){ if(isElement) { success = doc.addElement(descriptor, defaultValue); LogManager.logTrace(org.teiid.logging.LogConstants.CTX_XML_PLAN, new Object[]{"TAG elem",descriptor.getName(),"fixed value",defaultValue}); //$NON-NLS-1$ //$NON-NLS-2$ } else { success = doc.addAttribute(descriptor, defaultValue); LogManager.logTrace(org.teiid.logging.LogConstants.CTX_XML_PLAN, new Object[]{"TAG attr",descriptor.getName(),"fixed value",defaultValue}); //$NON-NLS-1$ //$NON-NLS-2$ } } else { if(isElement) { success = doc.addElement(descriptor, nillableDescriptor); LogManager.logTrace(org.teiid.logging.LogConstants.CTX_XML_PLAN, new Object[]{"TAG elem",descriptor.getName()}); //$NON-NLS-1$ } //else nothing gets outputted for attribute with no content } } else { Object value = context.getVariableContext().getValue(symbol); String valueStr = XMLValueTranslator.translateToXMLValue(value, descriptor.getRuntimeType(), descriptor.getDocBuiltInType(), env.getProcessorContext()); if (valueStr != null){ if(isElement) { success = doc.addElement(descriptor, valueStr); LogManager.logTrace(org.teiid.logging.LogConstants.CTX_XML_PLAN, new Object[]{"TAG elem",descriptor.getName(),"value",valueStr}); //$NON-NLS-1$ //$NON-NLS-2$ } else { success = doc.addAttribute(descriptor, valueStr); LogManager.logTrace(org.teiid.logging.LogConstants.CTX_XML_PLAN, new Object[]{"TAG attr",descriptor.getName(),"value",valueStr}); //$NON-NLS-1$ //$NON-NLS-2$ } } else { if (defaultValue != null){ if(isElement) { success = doc.addElement(descriptor, defaultValue); LogManager.logTrace(org.teiid.logging.LogConstants.CTX_XML_PLAN, new Object[]{"TAG elem",descriptor.getName(),"default value",defaultValue}); //$NON-NLS-1$ //$NON-NLS-2$ } else { success = doc.addAttribute(descriptor, defaultValue); LogManager.logTrace(org.teiid.logging.LogConstants.CTX_XML_PLAN, new Object[]{"TAG attr",descriptor.getName(),"default value",defaultValue}); //$NON-NLS-1$ //$NON-NLS-2$ } } else { if(isElement) { success = doc.addElement(descriptor, nillableDescriptor); LogManager.logTrace(org.teiid.logging.LogConstants.CTX_XML_PLAN, new Object[]{"TAG elem",descriptor.getName(),"no value"}); //$NON-NLS-1$ //$NON-NLS-2$ } //else nothing gets outputted for attribute with no content } } } if (!success){ String elem = (isElement ? QueryPlugin.Util.getString("AddNodeInstruction.element__1" ) : QueryPlugin.Util.getString("AddNodeInstruction.attribute__2")); //$NON-NLS-1$ //$NON-NLS-2$ Object[] params = new Object[]{elem, this.descriptor.getQName(), this.descriptor.getNamespaceURI(), this.descriptor.getNamespaceURIs()}; String msg = QueryPlugin.Util.getString("AddNodeInstruction.Unable_to_add_xml_{0}_{1},_namespace_{2},_namespace_declarations_{3}_3", params); //$NON-NLS-1$ throw new TeiidComponentException(QueryPlugin.Event.TEIID30206, msg); } env.incrementCurrentProgramCounter(); return context; } public String toString() { StringBuffer str = new StringBuffer(); if(descriptor.isElement()) { str.append("ELEM "); //$NON-NLS-1$ } else { str.append("ATTR "); //$NON-NLS-1$ } str.append(descriptor.getQName()); if(symbol != null) { str.append(" "); //$NON-NLS-1$ str.append(symbol); } if (descriptor.getDefaultValue() != null){ str.append(" (default " + descriptor.getDefaultValue() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ } Properties namespaceDeclarations = descriptor.getNamespaceURIs(); if (namespaceDeclarations != null){ str.append(" (namespaces "); //$NON-NLS-1$ Enumeration e = namespaceDeclarations.propertyNames(); while (e.hasMoreElements()){ String prefix = (String)e.nextElement(); str.append(prefix); str.append("=>"); //$NON-NLS-1$ str.append(namespaceDeclarations.getProperty(prefix)); if (e.hasMoreElements()) str.append(", "); //$NON-NLS-1$ } str.append(")"); //$NON-NLS-1$ } return str.toString(); } public PlanNode getDescriptionProperties() { PlanNode props = null; if(descriptor.isElement()) { props = new PlanNode("ADD ELEMENT"); //$NON-NLS-1$ } else { props = new PlanNode("ADD ATTRIBUTE"); //$NON-NLS-1$ } props.addProperty(PROP_TAG, this.descriptor.getName()); if(descriptor.isOptional()) { props.addProperty(PROP_OPTIONAL, ""+descriptor.isOptional()); //$NON-NLS-1$ } if(this.symbol != null) { props.addProperty(PROP_DATA_COL, this.symbol.toString()); } if(descriptor.getNamespacePrefix() != null) { props.addProperty(PROP_NAMESPACE, descriptor.getNamespacePrefix()); } Properties namespaceDeclarations = descriptor.getNamespaceURIs(); if(namespaceDeclarations != null) { List<String> nsDecl = new ArrayList<String>(namespaceDeclarations.size()); Enumeration e = namespaceDeclarations.propertyNames(); while (e.hasMoreElements()){ String prefix = (String)e.nextElement(); String ns = namespaceDeclarations.getProperty(prefix); nsDecl.add(prefix + "=\"" + ns + "\""); //$NON-NLS-1$ //$NON-NLS-2$ } props.addProperty(PROP_NAMESPACE_DECL, nsDecl); } if(descriptor.getDefaultValue() != null) { props.addProperty(PROP_DEFAULT, descriptor.getDefaultValue()); } return props; } /** * @param nillableDescriptor The nillableDescriptor to set. * @since 4.3 */ public void setNillableDescriptor(NodeDescriptor nillableDescriptor) { this.nillableDescriptor = nillableDescriptor; } }