/*
* 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.transform;
import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.onecmdb.core.utils.IBeanProvider;
import org.onecmdb.core.utils.bean.CiBean;
import org.onecmdb.core.utils.bean.ValueBean;
/**
* Transform a easy understandable transform to transform model.
*
* @author niklas
*
*/
public class SimpleTransformProvider implements IBeanProvider {
private static final String XPATH_INSTANCE_SELECTOR = "XPathInstanceSelector";
private static final String XPATH_COMPLEX_ATTRIBUTE_SELECTOR = "XPathComplexAttributeSelector";
private String input;
private String name;
private String attributeSelectorType;
private String attrSelectorAlias;
private String complexAttributeSelectorType;
private String instanceSelectorType;
private HashMap<String, CiBean> beanMap = new HashMap<String, CiBean>();
private boolean transformed = false;
private Set<String> dataSets = new HashSet<String>();
private Set<String> referencedDataSets = new HashSet<String>();
private String attrSelectorNameAlias;
private String instanceSelectorTemplateAlias;
private String instanceSelectorTemplateNameAlias;
private Reader inputReader;
public void setInput(String input) {
this.input = input;
}
public Reader getInputReader() {
return inputReader;
}
public void setInputReader(Reader inputReader) {
this.inputReader = inputReader;
}
/**
* Currently allowed types are
* xml,csv,jdbc,excel.
*
* @param type
*/
public void setType(String type) {
if (type != null) {
if (type.equalsIgnoreCase("xml")) {
complexAttributeSelectorType = XPATH_COMPLEX_ATTRIBUTE_SELECTOR;
instanceSelectorType = XPATH_INSTANCE_SELECTOR;
attributeSelectorType = "XPathAttributeSelector";
attrSelectorAlias = "xpath";
instanceSelectorTemplateAlias = "templatePath";
return;
} else if (type.equalsIgnoreCase("csv") || type.equalsIgnoreCase("excel")) {
complexAttributeSelectorType = "ComplexAttributeSelector";
instanceSelectorType = "CSVInstanceSelector";
attributeSelectorType = "CSVAttributeSelector";
attrSelectorAlias = "colIndexStr";
instanceSelectorTemplateAlias = "templateColString";
attrSelectorNameAlias ="colName";
return;
} else if (type.equalsIgnoreCase("jdbc")) {
complexAttributeSelectorType = "ComplexAttributeSelector";
instanceSelectorType = "JDBCInstanceSelector";
attributeSelectorType = "JDBCAttributeSelector";
attrSelectorAlias = "colString";
attrSelectorNameAlias ="colName";
instanceSelectorTemplateAlias = "templateColString";
instanceSelectorTemplateNameAlias = "templateColName";
return;
}
}
throw new IllegalArgumentException("Type " + type + " not allowed. Require XML, CSV or JDBC");
}
public CiBean getBean(String alias) {
try {
transform();
} catch (Throwable t) {
throw new IllegalArgumentException("Error transforming: " + t.getMessage(), t);
}
CiBean bean = beanMap.get(alias);
return(bean);
}
public List<CiBean> getBeans() {
try {
transform();
} catch (Throwable t) {
throw new IllegalArgumentException("Error transforming: " + t.getMessage(), t);
}
List<CiBean> list = new ArrayList<CiBean>(beanMap.values());
return(list);
}
public Document getInputDocument() throws Exception {
SAXReader reader = new SAXReader();
Document document = null;
if (this.inputReader != null) {
document = reader.read(this.inputReader);
} else {
document = reader.read(new File(input));
}
return(document);
}
protected void transform() throws Exception {
if (transformed) {
return;
}
transformed = true;
beanMap.clear();
Document document = getInputDocument();
Element root = document.getRootElement();
//this.name = getAttributeValue(root, "name", true);
this.name = "primary-forward";
CiBean forward = newBean(name);
forward.setDerivedFrom("DataSet");
forward.setTemplate(false);
forward.addAttributeValue(new ValueBean("name", name, false));
// Add Dummy InstanceSelector
forward.addAttributeValue(new ValueBean("instanceSelector", getForwardInstanceSelector(name).getAlias(), true));
for (Element dataSetEl : (List<Element>)root.elements()) {
CiBean dataSet = getDataSet(dataSetEl);
if (dataSet == null) {
continue;
}
String exclude = getAttributeValue(dataSetEl, "exclude", false);
if (exclude != null && exclude.equalsIgnoreCase("true")) {
continue;
}
CiBean bean = newBean("fw-" + dataSet.getAlias());
bean.setDerivedFrom("ComplexAttributeSelector");
bean.addAttributeValue(new ValueBean("dataSet", dataSet.getAlias(), true));
forward.addAttributeValue(new ValueBean("attributeSelector", bean.getAlias(), true));
}
// Validate DataSet names.
StringBuffer errorMsg = new StringBuffer();
boolean error = false;
errorMsg.append("DataSet name '");
for (String refDataSet : referencedDataSets) {
if (dataSets.contains(refDataSet)) {
continue;
}
if (error) {
errorMsg.append(", ");
}
errorMsg.append(refDataSet);
error = true;
}
if (error) {
errorMsg.append("' not found");
throw new IllegalArgumentException(errorMsg.toString());
}
/*
for (Element dataSetEl : (List<Element>)root.elements("DataSetSelector")) {
CiBean dataSet = getDataSetSelector(dataSetEl);
}
*/
}
private CiBean newBean(String alias) {
CiBean bean = beanMap.get(alias);
if (bean == null) {
bean = new CiBean();
bean.setAlias(alias);
beanMap.put(alias, bean);
}
return(bean);
}
private CiBean getForwardInstanceSelector(String name) {
CiBean bean = newBean("fw-" + name);
bean.setDerivedFrom("ForwardInstanceSelector");
return(bean);
}
private CiBean getDataSet(Element dataSetEl) {
if (dataSetEl.getName().equals("DataSetSelector")) {
return(getDataSetSelector(dataSetEl));
}
if (!dataSetEl.getName().equals("DataSet")) {
return(null);
}
String name = getAttributeValue(dataSetEl, "name", true);
name = "DataSet-" + name;
dataSets.add(name);
CiBean ds = newBean(name);
ds.setDerivedFrom("DataSet");
ds.setTemplate(false);
ds.addAttributeValue(new ValueBean("name", name, false));
String parent = getAttributeValue(dataSetEl, "parent", false);
if (parent != null) {
ds.addAttributeValue(new ValueBean("parent", parent, true));
}
int count = 0;
for (Element el : (List<Element>)dataSetEl.elements()) {
if (el.getName().contains("ForwardInstanceSelector")) {
CiBean instance = getForwardInstanceSelector(name + count);
ds.addAttributeValue(new ValueBean("instanceSelector", instance.getAlias(), true));
} else if (el.getName().contains("InstanceSelector")) {
CiBean instance = getInstanceSelector(name, el);
ds.addAttributeValue(new ValueBean("instanceSelector", instance.getAlias(), true));
} else {
//if (el.getName().contains("AttributeSelector")) {
CiBean attr = getAttributeSelector(name + "-" + count, el);
ds.addAttributeValue(new ValueBean("attributeSelector", attr.getAlias(), true));
}
count++;
}
return(ds);
}
private CiBean getDataSetSelector(Element dataSetEl) {
String name = getAttributeValue(dataSetEl, "name", true);
CiBean ds = newBean(name);
ds.setDerivedFrom("DataSetSelector");
ds.setTemplate(false);
dataSets.add(name);
ds.addAttributeValue(new ValueBean("name", name, false));
int count = 0;
for (Element el : (List<Element>)dataSetEl.elements()) {
if (el.getName().contains("InstanceSelector")) {
CiBean instance = getInstanceSelector(name, el);
ds.addAttributeValue(new ValueBean("instanceSelector", instance.getAlias(), true));
}
if (el.getName().contains("RegExpMatcher")) {
CiBean regExpr = getRegExpr(name, el, count);
ds.addAttributeValue(new ValueBean("dataSetMatcher", regExpr.getAlias(), true));
count++;
}
}
return(ds);
}
private CiBean getRegExpr(String name, Element el, int count) {
CiBean ds = newBean("regExpr-" + name + "-" + count);
ds.setDerivedFrom("RegExprMatcher");
ds.setTemplate(false);
ds.addAttributeValue(new ValueBean("regExpr", getAttributeValue(el, "regExpr", true), false));
String lowerCase = getAttributeValue(el, "lowerCase", false);
if (lowerCase != null) {
ds.addAttributeValue(new ValueBean("lowerCase", lowerCase, false));
}
String value = getElementValue(el, "DataSet", true);
referencedDataSets.add(value);
ds.addAttributeValue(new ValueBean("dataSet", value, true));
Element attrSel = el.element("AttributeSelector");
if (attrSel == null) {
throw new IllegalArgumentException("Element <" + "AttributeSelector" + "> is missing in <" +
el.getName() + "> [" + el.getPath() + "]");
}
CiBean bean = getAttributeSelector(name + "-" + count, attrSel);
ds.addAttributeValue(new ValueBean("attributeSelector", bean.getAlias(), true));
return(ds);
}
private CiBean getInstanceSelector(String name, Element el) {
CiBean ds = newBean("instanceSelector-" + name);
String type = el.getName();
if (type.equals("EmptyInstanceSelector")) {
ds.setDerivedFrom("EmptyInstanceSelector");
ds.setTemplate(false);
return(ds);
}
ds.setDerivedFrom(instanceSelectorType);
ds.setTemplate(false);
String autoCreate = getAttributeValue(el, "auto-create", false);
if (autoCreate == null || autoCreate.length() == 0) {
autoCreate = "true";
}
ds.addAttributeValue(new ValueBean("autoCreate", autoCreate, false));
ds.addAttributeValue(new ValueBean("template", getAttributeValue(el, "template", true), false));
String templCol = getAttributeValue(el, "templateSelector", false);
if (templCol != null && templCol.length() > 0) {
ds.addAttributeValue(new ValueBean(instanceSelectorTemplateAlias, templCol, false));
}
String templNameCol = getAttributeValue(el, "templateNameSelector", false);
if (templNameCol != null && templNameCol.length() > 0) {
ds.addAttributeValue(new ValueBean(instanceSelectorTemplateNameAlias, templNameCol, false));
}
if (instanceSelectorType.equals(XPATH_INSTANCE_SELECTOR)) {
String match = getAttributeValue(el, "match", true);
ds.addAttributeValue(new ValueBean("xpath", match, false));
}
return(ds);
}
private CiBean getAttributeSelector(String name, Element el) {
String attrAliasName = getAttributeValue(el, "name", true);
String key = getAttributeValue(el, "naturalKey", false);
String defaultValue = getAttributeValue(el, "defaultValue", false);
if (key == null) {
key = "false";
}
String selector = getAttributeValue(el, "selector", false);
String selectorName = getAttributeValue(el, "selectorName", false);
CiBean bean = newBean(name + "-" + attrAliasName);
if (el.getName().equals("ComplexAttributeSelector")) {
bean.setDerivedFrom(complexAttributeSelectorType);
String dsName = getAttributeValue(el, "dataSet", false);
String ds = "DataSet-" + dsName;
referencedDataSets.add(ds);
bean.addAttributeValue(new ValueBean("dataSet", ds, true));
if (complexAttributeSelectorType.equals(XPATH_COMPLEX_ATTRIBUTE_SELECTOR)) {
String xpath = getAttributeValue(el, "selector", true);
bean.addAttributeValue(new ValueBean("xpath", xpath, false));
}
} else if (el.getName().equals("DefaultAttributeSelector")){
bean.setDerivedFrom("DefaultAttributeSelector");
String value = getAttributeValue(el, "value", true);
bean.addAttributeValue(new ValueBean("value", value, false));
String complex = getAttributeValue(el, "complex", false);
if (complex != null) {
bean.addAttributeValue(new ValueBean("complex", complex, false));
}
} else if (el.getName().equals("AttributeExpressionSelector")){
bean.setDerivedFrom("AttributeExpressionSelector");
String expr = getElementValue(el, "Expression", true);
bean.addAttributeValue(new ValueBean("expression", expr, false));
for (Element child : (List<Element>)el.elements()) {
int count = 0;
if (child.getName().equals("AttributeSelector")) {
CiBean aSel = getAttributeSelector(attrAliasName + "-" + name + "-" + count, child);
bean.addAttributeValue(new ValueBean("selector", aSel.getAlias(), true));
count++;
}
}
} else {
bean.setDerivedFrom(attributeSelectorType);
// Fix to support names insted of index in jdbc queries.
if (selectorName != null && attrSelectorNameAlias != null) {
bean.addAttributeValue(new ValueBean(attrSelectorNameAlias, selectorName, false));
} else {
bean.addAttributeValue(new ValueBean(attrSelectorAlias, selector, false));
}
}
bean.addAttributeValue(new ValueBean("name", attrAliasName, false));
bean.addAttributeValue(new ValueBean("naturalKey", key, false));
bean.addAttributeValue(new ValueBean("defaultValue", defaultValue, false));
return(bean);
}
/**
* XML helper functions
*/
private String getElementValue(Element sel,
String elementName, boolean requiered) {
Element el = sel.element(elementName);
if (el == null) {
if (requiered) {
throw new IllegalArgumentException("Element <" + elementName + "> is missing in <" +
sel.getName() + "> [" + sel.getPath() + "]");
}
return(null);
}
String text = el.getTextTrim();
if (requiered && (text == null || text.length() == 0)) {
throw new IllegalArgumentException("Element <" + elementName + "> has no value in <" +
sel.getName() + "> [" + sel.getPath() + "]");
}
return(text);
}
private String getAttributeValue(Element sel,
String attributeName, boolean requiered) {
Attribute el = sel.attribute(attributeName);
if (el == null) {
if (requiered) {
throw new IllegalArgumentException("Attribute <" + attributeName + "> is missing in <" +
sel.getName() + "> [" + sel.getPath() + "]");
}
return(null);
}
String text = el.getText();
if (requiered && (text == null || text.length() == 0)) {
throw new IllegalArgumentException("Element <" + attributeName + "> has no value in <" +
sel.getName() + "> [" + sel.getPath() + "]");
}
return(text);
}
}