/* * 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; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.onecmdb.core.IAttribute; import org.onecmdb.core.IAttributeModifiable; import org.onecmdb.core.ICcb; import org.onecmdb.core.ICi; import org.onecmdb.core.ICiModifiable; import org.onecmdb.core.ICmdbTransaction; import org.onecmdb.core.IModelService; import org.onecmdb.core.IReferenceService; import org.onecmdb.core.IRfcResult; import org.onecmdb.core.ISession; import org.onecmdb.core.ITicket; import org.onecmdb.core.IValue; import org.onecmdb.core.internal.model.Path; import org.onecmdb.core.internal.model.QueryCriteria; import org.onecmdb.core.internal.model.QueryResult; import org.onecmdb.core.internal.storage.expression.OrderExpression; import org.onecmdb.core.internal.storage.expression.SourceRelationExpression; import org.onecmdb.core.internal.storage.expression.SourceTemplateRelationExpression; import org.onecmdb.core.internal.storage.expression.TemplateRelationExpression; /** * Simplify create/modification/retriving of ci's and attributes. * */ public class OnecmdbUtils { private ISession session; private static Log log = LogFactory.getLog(OnecmdbUtils.class); public OnecmdbUtils(ISession session) { this.session = session; } public ICi newInstance(ICi ci) { return(newInstance(ci, null)); } public ICi newInstance(ICi ci, String alias) { ICcb ccb = (ICcb) session.getService(ICcb.class); // Create a Blueprint that defines one IP Address. Set<ICi> beforeSet = ci.getOffsprings(); ICmdbTransaction tx = ccb.getTx(session); { ICiModifiable rootTemplate = tx.getTemplate(ci); ICiModifiable ipTemplate = rootTemplate.createOffspring(); ipTemplate.setIsBlueprint(false); if (alias != null) { ipTemplate.setAlias(alias); } } ITicket ticket = ccb.submitTx(tx); IRfcResult result = ccb.waitForTx(ticket); if (result.isRejected()) { log.error("Reject create instance of ci '" + ci.getAlias() +"' cause " + result.getRejectCause()); return(null); } // How can we retrive the new item!!! // The target id is stored in ipTemplate. Set<ICi> afterSet = ci.getOffsprings(); ICi newCi = null; for (ICi offspringCi : afterSet) { if (!beforeSet.contains(offspringCi)) { newCi = offspringCi; break; } } return (newCi); } public void setValue(ICi source, String aName, IValue value) { IAttribute theAttribute = null; for (IAttribute a : source.getAttributes()) { if (a.getDisplayName().equals(aName)) { theAttribute = a; break; } } setValue(theAttribute, value); } public IAttribute setValue(IAttribute theAttribute, IValue value) { ICcb ccb = (ICcb) session.getService(ICcb.class); ICmdbTransaction tx = ccb.getTx(session); { IAttributeModifiable aTemplate = tx .getAttributeTemplate(theAttribute); aTemplate.setValue(value); } ITicket ticket = ccb.submitTx(tx); IRfcResult result = ccb.waitForTx(ticket); IModelService model = (IModelService) session.getService(IModelService.class); IAttribute reload = (IAttribute) model.find(theAttribute.getId()); return(reload); } /** * Expression looks like this. * | delimiter between ci's * <> direction command * $attr{attAlias} reference to the attribute's value in current ci. * $template{alias}.$attr{attAlias} reference to an ci instance with attAlias poniting to current ci. * * @param origin * @param path * @return */ public Set<IValue> evaluate(IValue current, String path) { Set<IValue> values = new HashSet<IValue>(); if (path == null || path.trim().equals("")) { values.add(current); return(values); } String expressions[] = path.split("\\|",2); String expression = expressions[0]; Set<IValue> next = new HashSet<IValue>(); if (expression.startsWith(">")) { // Must be $attr if (!expression.startsWith(">$attr{")) { throw new IllegalArgumentException("Expressson '" + expression +"' not valid. < must be followed by $attr{attAlias}"); } String attrAlias = expression.substring(">$attr{".length(), expression.length()-1); log.debug(">" + attrAlias); if (!(current instanceof ICi)) { throw new IllegalArgumentException("Error in expression, trying to operate '" + expression + "' on a simple value '" + current + "'"); } List<IAttribute> attrs = ((ICi)current).getAttributesWithAlias(attrAlias); // Will now add all values. for (IAttribute a : attrs) { IValue value = a.getValue(); if (value != null) { next.add(value); } } } else if (expression.startsWith("<")) { // Must be $attr if (!expression.startsWith("<$template{")) { throw new IllegalArgumentException("Expressson '" + expression +"' not valid. < must be followed by $template{alias}.$attr[attrAlis}"); } String templates[] = expression.split("\\{", 3); int offset = templates[1].indexOf('}'); String template = templates[1].substring(0, offset); String attrAlias = null; if (templates.length > 2) { offset = templates[2].indexOf('}'); attrAlias = templates[2].substring(0, offset); } log.debug("<" + template + "." + attrAlias); if (!(current instanceof ICi)) { throw new IllegalArgumentException("Error in expression, trying to operate '" + expression + "' on a simple value '" + current + "'"); } IModelService modelSvc = (IModelService)this.session.getService(IModelService.class); ICi templateCi = modelSvc.findCi(new Path<String>(template)); if (templateCi == null) { throw new IllegalArgumentException("Template '" + template + "' is not found"); } List<ICi> candidates = getReferrersOfType((ICi) current, templateCi); // Add all candidates. // TODO: check attribute alias for (ICi candidate : candidates) { next.add(candidate); } } if (expressions.length < 2) { return(next); } String rest = expressions[1]; Set<IValue> result = new HashSet<IValue>(); for (IValue value : next) { result.addAll(evaluate(value, rest)); } return(result); } public QueryResult evaluate(IValue current, String path, QueryCriteria crit, boolean count) { QueryResult result = new QueryResult(); if (path == null || path.trim().equals("")) { return(result); } String expressions[] = path.split("\\|",2); String expression = expressions[0]; QueryResult next = new QueryResult(); if (expression.startsWith(">$attr")) { // Must be $attr String attrAlias = expression.substring(">$attr{".length(), expression.length()-1); log.debug(">" + attrAlias); if (!(current instanceof ICi)) { throw new IllegalArgumentException("Error in expression, trying to operate '" + expression + "' on a simple value '" + current + "'"); } List<IAttribute> attrs = ((ICi)current).getAttributesWithAlias(attrAlias); // Will now add all values. for (IAttribute a : attrs) { IValue value = a.getValue(); if (value != null) { next.add(value); } } } else if (expression.startsWith("<$template{")) { // Must be $attr String templates[] = expression.split("\\{", 3); int offset = templates[1].indexOf('}'); String template = templates[1].substring(0, offset); String attrAlias = null; if (templates.length > 2) { offset = templates[2].indexOf('}'); attrAlias = templates[2].substring(0, offset); } log.debug("<" + template + "." + attrAlias); if (!(current instanceof ICi)) { throw new IllegalArgumentException("Error in expression, trying to operate '" + expression + "' on a simple value '" + current + "'"); } IModelService modelSvc = (IModelService)this.session.getService(IModelService.class); SourceRelationExpression expr = new SourceRelationExpression(); if (!template.equals("*")) { ICi templateCi = modelSvc.findCi(new Path<String>(template)); if (templateCi == null) { throw new IllegalArgumentException("Template '" + template + "' is not found"); } expr.setSourceTemplateId(templateCi.getId().asLong()); if (crit != null) { if (crit.getOffspringDepth() != null) { expr.setSourceTemplatePathString(templateCi.getTemplatePath()); expr.setSourceTemplateId(null); } } } expr.setTargetId(((ICi)current).getId().asLong()); expr.setCount(count); if (expressions.length < 2 && crit != null) { expr.setMaxResult(crit.getMaxResult()); expr.setFirstResult(crit.getFirstResult()); expr.setTextMatch(crit.getText()); expr.setTextMatchAlias(crit.isTextMatchAlias()); expr.setTextMatchDescription(crit.isTextMatchDescription()); expr.setTextMatchValue(crit.isTextMatchValue()); if (crit.getOrderAttAlias() != null) { OrderExpression order = new OrderExpression(); order.setAttrType(crit.getOrderType()); order.setAttrAlias(crit.getOrderAttAlias()); order.setAscending(crit.isOrderAscending()); expr.setOrder(order); } } next = modelSvc.evalExpression(expr); } else if (expression.startsWith("<$referenceTemplate")) { // Find reference CI for a ci. if (!(current instanceof ICi)) { throw new IllegalArgumentException("Error in expression, trying to operate '" + expression + "' on a simple value '" + current + "'"); } IModelService modelSvc = (IModelService)this.session.getService(IModelService.class); TemplateRelationExpression expr = new TemplateRelationExpression(); expr.setTargetId(((ICi)current).getId().asLong()); expr.setCount(count); if (expressions.length < 2 && crit != null) { expr.setMaxResult(crit.getMaxResult()); expr.setFirstResult(crit.getFirstResult()); expr.setTextMatch(crit.getText()); expr.setTextMatchAlias(crit.isTextMatchAlias()); expr.setTextMatchDescription(crit.isTextMatchDescription()); expr.setTextMatchValue(crit.isTextMatchValue()); if (crit.getOrderAttAlias() != null) { OrderExpression order = new OrderExpression(); order.setAttrType(crit.getOrderType()); order.setAttrAlias(crit.getOrderAttAlias()); order.setAscending(crit.isOrderAscending()); expr.setOrder(order); } } next = modelSvc.evalExpression(expr); } else if (expression.startsWith("<$referenceSource{")) { // Find reference CI for a ci. if (!(current instanceof ICi)) { throw new IllegalArgumentException("Error in expression, trying to operate '" + expression + "' on a simple value '" + current + "'"); } String templates[] = expression.split("\\{", 3); int offset = templates[1].indexOf('}'); String template = templates[1].substring(0, offset); IModelService modelSvc = (IModelService)this.session.getService(IModelService.class); ICi referenceTemplateCi = modelSvc.findCi(new Path<String>(template)); if (referenceTemplateCi == null) { throw new IllegalArgumentException("Reference Template '" + template + "' is not found"); } SourceTemplateRelationExpression expr = new SourceTemplateRelationExpression(); expr.setTargetId(((ICi)current).getId().asLong()); expr.setReferenceTemplateId(referenceTemplateCi.getId().asLong()); expr.setCount(count); if (expressions.length < 2 && crit != null) { expr.setMaxResult(crit.getMaxResult()); expr.setFirstResult(crit.getFirstResult()); expr.setTextMatch(crit.getText()); expr.setTextMatchAlias(crit.isTextMatchAlias()); expr.setTextMatchDescription(crit.isTextMatchDescription()); expr.setTextMatchValue(crit.isTextMatchValue()); if (crit.getOrderAttAlias() != null) { OrderExpression order = new OrderExpression(); order.setAttrType(crit.getOrderType()); order.setAttrAlias(crit.getOrderAttAlias()); order.setAscending(crit.isOrderAscending()); expr.setOrder(order); } } next = modelSvc.evalExpression(expr); } else { if (expression.startsWith(">")) { throw new IllegalArgumentException("Expressson '" + expression +"' not valid. < must be followed by $attr{attAlias}"); } if (expression.startsWith("<")) { throw new IllegalArgumentException("Expressson '" + expression +"' not valid. < must be followed by $template{alias}.$attr[attrAlis}"); } throw new IllegalArgumentException("Illegal Expressson '" + expression +"'"); } if (expressions.length < 2) { return(next); } String rest = expressions[1]; for (Iterator iter = next.iterator(); iter.hasNext();) { Object value = iter.next(); if (value instanceof IValue) { result.addAll(evaluate((IValue)value, rest, crit, count)); } } return(result); } /** * Return the firts occurence of an attribute with alias. * * @param ci * @param attrAlias * @return null if not found or empty. */ public IAttribute getFirstAttribute(ICi ci, String attrAlias) { List<IAttribute> list = ci.getAttributesWithAlias(attrAlias); if (list == null) { return(null); } if (list.size() == 0) { return(null); } return(list.get(0)); } /** * Could/Should be moved to IReferenceService! */ public List<ICi> getReferrersOfType(ICi ci, ICi template) { IReferenceService refSvc = (IReferenceService)this.session.getService(IReferenceService.class); IModelService modelSvc = (IModelService)this.session.getService(IModelService.class); List<ICi> list = new ArrayList<ICi>(); Set<ICi> refs = refSvc.getOriginCiReferrers(ci); for (ICi ref : refs) { if (modelSvc.isOffspringOf(template, ref)) { list.add(ref); } } return(list); } public void deleteCi(ICi ci) { ICcb ccb = (ICcb) session.getService(ICcb.class); ICmdbTransaction tx = ccb.getTx(session); { ICiModifiable modifiable = tx.getTemplate(ci); modifiable.delete(); } ITicket ticket = ccb.submitTx(tx); IRfcResult result = ccb.waitForTx(ticket); } }