/* * Lokomo OneCMDB - An Open Source Software for Configuration * Management of Datacenter Resources * * Copyright (C) 2006 Lokomo Systems AB * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. * * Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via * paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33 * Danderyd, Sweden. * */ package org.onecmdb.core.utils.xpath.generator; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import net.sf.cglib.beans.BeanMap; import org.apache.commons.jxpath.Pointer; import org.apache.commons.jxpath.ri.model.NodePointer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.onecmdb.core.ICi; import org.onecmdb.core.IValue; import org.onecmdb.core.internal.model.ItemId; import org.onecmdb.core.utils.bean.CiBean; import org.onecmdb.core.utils.bean.ValueBean; import org.onecmdb.core.utils.xml.OneCmdbBeanProvider; import org.onecmdb.core.utils.xpath.IOneCMDBContentGenerator; import org.onecmdb.core.utils.xpath.commands.QueryCommand; import org.onecmdb.core.utils.xpath.model.AttributeValueContext; import org.onecmdb.core.utils.xpath.model.InstanceCollectionContext; import org.onecmdb.core.utils.xpath.model.InstanceContext; import org.onecmdb.core.utils.xpath.model.TemplateCollectionContext; import org.onecmdb.core.utils.xpath.model.TemplateContext; /** * Generate XMLformat for query. * On Templates the full (with all attributes) xml is retuned. * On instnaces quiered attributes are returned. * */ public class XMLContentGenerator implements IOneCMDBContentGenerator { private QueryCommand cmd; private HashMap<String, Object> beanInternalMap = new HashMap<String, Object>(); private ArrayList<CiBean> templatesBeans = new ArrayList<CiBean>(); private ArrayList<CiBean> instancesBeans = new ArrayList<CiBean>(); private Log log = LogFactory.getLog(this.getClass()); public XMLContentGenerator() { // Setup Internal hashmap. beanInternalMap.put("id", Boolean.TRUE); beanInternalMap.put("alias", Boolean.TRUE); beanInternalMap.put("displayName", Boolean.TRUE); beanInternalMap.put("displayNameExpression", Boolean.TRUE); beanInternalMap.put("derivedFrom", Boolean.TRUE); beanInternalMap.put("description", Boolean.TRUE); } public void setCommand(QueryCommand cmd) { this.cmd = cmd; } public String getContentType() { return("text/xml"); } public void transfer(OutputStream out) { log.debug("Debug Query path <" + cmd.getPath() + ">"); PrintWriter text = new PrintWriter(new OutputStreamWriter(out), false); // Generate response beans. generateBeans(); // Generate Response. generateResponse(text); // Flush text. text.flush(); } private void generateBeans() { Iterator<Pointer> iter = cmd.getPathPointers(); boolean first = true; while(iter.hasNext()) { Pointer p = (Pointer)iter.next(); Object value = p.getValue(); if (value instanceof InstanceCollectionContext) { Iterator colIterator = cmd.getRelativePointers(p, "*"); while(colIterator.hasNext()) { Pointer instancePointer = (Pointer)colIterator.next(); Object instanceValue = instancePointer.getValue(); if (instanceValue instanceof InstanceContext) { generateInstanceXML(instancePointer, (InstanceContext)instanceValue); } } } if (value instanceof TemplateCollectionContext) { Iterator colIterator = cmd.getRelativePointers(p, "*"); while(colIterator.hasNext()) { Pointer templatePointer = (Pointer)colIterator.next(); Object templateValue = templatePointer.getValue(); if (templateValue instanceof TemplateContext) { generateTemplateXML(templatePointer, (TemplateContext)templateValue); } } } if (value instanceof TemplateContext) { generateTemplateXML(p, (TemplateContext)value); } if (value instanceof InstanceContext) { InstanceContext context = (InstanceContext)value; generateInstanceXML(p, context); } } } public List<CiBean> getBeans() { // Generate requested beans from the command. generateBeans(); // Collect all beans. List<CiBean> beans = new ArrayList<CiBean>(); beans.addAll(templatesBeans); beans.addAll(instancesBeans); return(beans); } private void generateResponse(PrintWriter text) { out(text, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); out(text, "<onecmdb>"); if (templatesBeans.size() > 0) { out(text, "\t<templates>"); for (CiBean bean : templatesBeans) { out(text, bean.toXML(2)); } out(text, "\t</templates>"); } if (instancesBeans.size() > 0) { out(text, "\t<instances>"); for (CiBean bean : instancesBeans) { out(text, bean.toXML(2)); } out(text, "\t</instances>"); } out(text, "</onecmdb>"); } private void generateTemplateXML(Pointer p, TemplateContext context) { ICi ci = context.getICi(); // Convert ci to a bean. OneCmdbBeanProvider provider = new OneCmdbBeanProvider(); CiBean bean = provider.convertCiToBean(ci); // Add bean to template list. templatesBeans.add(bean); } private void generateInstanceXML(Pointer p, InstanceContext context) { String[] outputAttributes = cmd.getOutputAttributeAsArray(); ArrayList<Iterator<Pointer>> resultSet = new ArrayList<Iterator<Pointer>>(); for (String outputAttribute : outputAttributes) { Iterator<Pointer> outputAttrPointersIter = cmd.getRelativePointers(p, outputAttribute); resultSet.add(outputAttrPointersIter); } generateOutput(context, (NodePointer)p, resultSet); } private void generateOutput(InstanceContext context, NodePointer root, List<Iterator<Pointer>> resultSet) { CiBean bean = new CiBean(); TemplateContext parent = (TemplateContext) context.getNewProperty("derivedFrom"); bean.setDerivedFrom(parent.getProperty("alias").toString()); bean.setAlias(context.getNewProperty("alias").toString()); Object id = context.getProperty("id"); if (id instanceof ItemId) { bean.setId(((ItemId)id).asLong()); } //bean.setDisplayNameExpression(context.getNewProperty("displayNameExpression").toString()); bean.setDisplayName(context.getNewProperty("displayName").toString()); bean.setTemplate(false); // Add attribute values. HashMap<String, CiBean> beanMap = new HashMap<String, CiBean>(); beanMap.put(bean.getAlias(), bean); for (Iterator<Pointer> pointers : resultSet) { while(pointers.hasNext()) { Pointer p = pointers.next(); fillBeanMap(beanMap, bean, root,(NodePointer)p); } } instancesBeans.add(bean); } private void fillBeanMap(HashMap<String, CiBean> map, CiBean currentBean, NodePointer root, NodePointer p) { // Get the attribute NodePointer name. NodePointer childToRoot = getChildToRoot(root, p); // Not a child of root, don't know what to do.. if (childToRoot == null) { return; } // add the value. Object value = childToRoot.getValue(); if (value instanceof AttributeValueContext) { AttributeValueContext attrValue = (AttributeValueContext)value; value = attrValue.getProperty("iValue"); } if (value instanceof InstanceContext) { InstanceContext instance = (InstanceContext)value; String alias = instance.getProperty("alias").toString(); CiBean instanceBean = map.get(alias); if (instanceBean == null) { instanceBean = new CiBean(); instanceBean.setDerivedFrom(instance.getProperty("derivedFrom").toString()); instanceBean.setAlias(alias); instanceBean.setDisplayName(instance.getNewProperty("displayName").toString()); instanceBean.setTemplate(false); instancesBeans.add(instanceBean); } String attAlias = childToRoot.getName().toString(); if (!isInternalState(attAlias)) { ValueBean vBean = new ValueBean(); vBean.setAlias(attAlias); vBean.setValue(instanceBean.getAlias()); vBean.setComplexValue(true); currentBean.addAttributeValue(vBean); map.put(alias, instanceBean); } fillBeanMap(map, instanceBean, childToRoot, p); } else { String attAlias = childToRoot.getName().toString(); if (!isInternalState(attAlias)) { ValueBean vBean = new ValueBean(); vBean.setAlias(attAlias); if (value != null) { vBean.setValue(value.toString()); } currentBean.addAttributeValue(vBean); } } } /** * A Ci has internal variables like alias, displayName(Expression) and id. * @param attAlias * @return */ public boolean isInternalState(String attAlias) { if (beanInternalMap.get(attAlias) == null) { return(false); } return(true); } private StringBuffer generateXMLTagForAttribute(PrintWriter text, NodePointer root, NodePointer p) { // Get the attribute NodePointer name. NodePointer childToRoot = getChildToRoot(root, p); StringBuffer sb = new StringBuffer(); // Not a child of root, don't know what to do.. if (childToRoot == null) { return(sb); } // start tag for attribute name sb.append("<" + childToRoot.getName() + ">\n"); // add the value. Object value = childToRoot.getValue(); if (value instanceof InstanceContext) { } else { sb.append("\t" + value.toString() + "\n"); } // End tag for attribute name sb.append("</" + childToRoot.getName() + ">\n"); return(sb); } private NodePointer getChildToRoot(NodePointer root, NodePointer p) { NodePointer parent = p.getParent(); if (parent == null) { return(null); } if (parent.equals(root)) { return(p); } return(getChildToRoot(root, parent)); } private void out(PrintWriter w, String text) { w.println(text); //System.out.println(text); } }