/*
* 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.graph.handler;
import java.awt.IllegalComponentStateException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Junction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.onecmdb.core.IAttribute;
import org.onecmdb.core.ICcb;
import org.onecmdb.core.ICi;
import org.onecmdb.core.ICmdbTransaction;
import org.onecmdb.core.IModelService;
import org.onecmdb.core.IRFC;
import org.onecmdb.core.IService;
import org.onecmdb.core.ISession;
import org.onecmdb.core.IType;
import org.onecmdb.core.IValue;
import org.onecmdb.core.internal.ccb.RFCSummaryDecorator;
import org.onecmdb.core.internal.model.BasicAttribute;
import org.onecmdb.core.internal.model.ConfigurationItem;
import org.onecmdb.core.internal.model.Path;
import org.onecmdb.core.internal.storage.hibernate.PageInfo;
import org.onecmdb.core.utils.graph.expression.AttributeExpression;
import org.onecmdb.core.utils.graph.expression.AttributeValueExpression;
import org.onecmdb.core.utils.graph.expression.ItemExpression;
import org.onecmdb.core.utils.graph.expression.OffspringExpression;
import org.onecmdb.core.utils.graph.expression.RFCExpression;
import org.onecmdb.core.utils.graph.expression.RFCRelationExpression;
import org.onecmdb.core.utils.graph.expression.RelationExpression;
import org.onecmdb.core.utils.graph.expression.ItemSecurityExpression;
import org.onecmdb.core.utils.graph.expression.TransactionExpression;
import org.onecmdb.core.utils.graph.expression.TransactionRelationExpression;
import org.onecmdb.core.utils.graph.query.GraphQuery;
import org.onecmdb.core.utils.graph.query.OrderInfo;
import org.onecmdb.core.utils.graph.query.constraint.AttributeSourceRelationConstraint;
import org.onecmdb.core.utils.graph.query.constraint.AttributeValueConstraint;
import org.onecmdb.core.utils.graph.query.constraint.ItemAndGroupConstraint;
import org.onecmdb.core.utils.graph.query.constraint.ItemConstraint;
import org.onecmdb.core.utils.graph.query.constraint.ItemGroupConstraint;
import org.onecmdb.core.utils.graph.query.constraint.ItemIdConstraint;
import org.onecmdb.core.utils.graph.query.constraint.ItemNotConstraint;
import org.onecmdb.core.utils.graph.query.constraint.ItemSecurityConstraint;
import org.onecmdb.core.utils.graph.query.constraint.RFCTargetConstraint;
import org.onecmdb.core.utils.graph.query.constraint.RelationConstraint;
import org.onecmdb.core.utils.graph.query.selector.ItemAliasSelector;
import org.onecmdb.core.utils.graph.query.selector.ItemOffspringSelector;
import org.onecmdb.core.utils.graph.query.selector.ItemRFCSelector;
import org.onecmdb.core.utils.graph.query.selector.ItemRelationSelector;
import org.onecmdb.core.utils.graph.query.selector.ItemSelector;
import org.onecmdb.core.utils.graph.query.selector.ItemTransactionSelector;
import org.onecmdb.core.utils.graph.query.selector.RFCItemRelationSelector;
import org.onecmdb.core.utils.graph.query.selector.TransactionRelationSelector;
import org.onecmdb.core.utils.graph.result.Graph;
import org.onecmdb.core.utils.graph.result.Template;
import org.onecmdb.core.utils.wsdl.RFCBean;
import org.onecmdb.core.utils.wsdl.TransactionBean;
import org.onecmdb.core.utils.xml.OneCmdbBeanProvider;
public class QueryHandler {
private IModelService msvc;
private ICcb ccb;
private ISession session;
private Log log = LogFactory.getLog(this.getClass());
//private boolean newSortPageAlgorithm;
class QueryResult {
public List matches;
public int totalCount;
}
class QueryExpression {
public DetachedCriteria criteria;
public boolean empty;
}
public QueryHandler(ISession session) {
this.session = session;
this.msvc = (IModelService)session.getService(IModelService.class);
this.ccb = (ICcb)session.getService(ICcb.class);
}
public Graph execute3(GraphQuery query) {
if (log.isDebugEnabled()) {
log.debug(toXML(query, 0));
}
Graph result = new Graph();
OneCmdbBeanProvider beanProvider = new OneCmdbBeanProvider();
beanProvider.setModelService((IModelService)session.getService(IModelService.class));
if (query.fetchSelectors().size() == 0) {
throw new IllegalArgumentException("No Selectors specified in query!");
}
for (ItemSelector sel : query.fetchOrderdItemSelectors()) {
if (sel.isExcludedInResultSet()) {
continue;
}
GraphQuery nQ = new GraphQuery();
// Resolve dependecies...
ItemSelector newSelector = buildGraph2(nQ, query, sel);
// Execute query..
QueryResult qRes = executeQuery(nQ, newSelector);
// Create Result Template
Template template = new Template();
template.setId(sel.getId());
if (newSelector.hasTemplate()) {
template.setTemplate(beanProvider.convertCiToBean(newSelector.fetchTemplate()));
}
template.setTotalCount(qRes.totalCount);
result.addNodes(template);
// Populate items...
List<Long> mIds = new ArrayList<Long>();
List<ICi> cis = new ArrayList<ICi>();
for (Object match : qRes.matches) {
if (match instanceof ICi) {
cis.add((ICi)match);
mIds.add(((ICi)match).getId().asLong());
} else if (match instanceof IRFC) {
template.addRFC(convert(ccb, (IRFC)match));
mIds.add(((IRFC)match).getTargetCIId());
} else if (match instanceof ICmdbTransaction) {
template.addTransaction(convert(ccb, (ICmdbTransaction)match));
mIds.add(((ICmdbTransaction)match).getId().asLong());
}
}
if (cis.size() > 0) {
template.setOffsprings(beanProvider.convertCIsToBeans(cis));
}
// Update Relation ids.
for (ItemRelationSelector rel : query.fetchRelationSelectors()) {
if (rel.getSource().equals(sel.getId())) {
rel.setSourceRange(mIds);
}
if (rel.getTarget().equals(sel.getId())) {
rel.setTargetRange(mIds);
}
}
}
for (ItemRelationSelector rel : query.fetchRelationSelectors()) {
if (rel instanceof RFCItemRelationSelector) {
continue;
}
if (rel instanceof TransactionRelationSelector) {
continue;
}
if (rel.isExcludedInResultSet()) {
continue;
}
QueryResult subRes = null;
subRes = executeQuery(query, rel);
Template temp = new Template();
temp.setId(rel.getId());
if (rel.hasTemplate()) {
temp.setTemplate(beanProvider.convertCiToBean(rel.fetchTemplate()));
}
temp.setTotalCount(subRes.totalCount);
List<ICi> cis = new ArrayList<ICi>();
for (Object match : subRes.matches) {
if (match instanceof IRFC) {
temp.addRFC(convert(ccb, (IRFC)match));
} else if (match instanceof ICi) {
temp.addOffspring(beanProvider.convertCiToBean((ICi)match));
} else if (match instanceof ICmdbTransaction) {
temp.addTransaction(convert(ccb, (ICmdbTransaction)match));
}
}
result.addEdges(temp);
}
return(result);
}
public Graph execute2(GraphQuery query) {
if (log.isDebugEnabled()) {
log.debug(toXML(query, 0));
}
Graph result = new Graph();
OneCmdbBeanProvider beanProvider = new OneCmdbBeanProvider();
ItemSelector primarySelector = query.fetchPrimarySelectors();
if (primarySelector == null) {
throw new IllegalArgumentException("No primary Selector found!");
}
// Setup dependencies...
GraphQuery nQ = new GraphQuery();
ItemSelector newSelector = buildGraph2(nQ, query, primarySelector);
QueryResult qRes = executeQuery(nQ, newSelector);
Template primaryTemplate = new Template();
primaryTemplate.setId(primarySelector.getId());
if (newSelector.hasTemplate()) {
primaryTemplate.setTemplate(beanProvider.convertCiToBean(newSelector.fetchTemplate()));
}
primaryTemplate.setTotalCount(qRes.totalCount);
if (primarySelector.reference()) {
result.addEdges(primaryTemplate);
} else {
result.addNodes(primaryTemplate);
}
List<Long> mIds = new ArrayList<Long>();
for (Object match : qRes.matches) {
if (match instanceof ICi) {
primaryTemplate.addOffspring(beanProvider.convertCiToBean((ICi)match));
mIds.add(((ICi)match).getId().asLong());
} else if (match instanceof IRFC) {
primaryTemplate.addRFC(convert(ccb, (IRFC)match));
mIds.add(((IRFC)match).getTargetCIId());
} else if (match instanceof ICmdbTransaction) {
primaryTemplate.addTransaction(convert(ccb, (ICmdbTransaction)match));
mIds.add(((ICmdbTransaction)match).getId().asLong());
}
}
// Update all references with this targets....
for (ItemRelationSelector rel : query.fetchRelationSelectors()) {
if (rel.getSource().equals(primarySelector.getId())) {
rel.setSourceRange(mIds);
}
if (rel.getTarget().equals(primarySelector.getId())) {
rel.setTargetRange(mIds);
}
}
for (ItemSelector sel : query.fetchSelectors()) {
if (sel.equals(primarySelector)) {
continue;
}
QueryResult subRes = null;
if (sel.reference()) {
if (sel instanceof RFCItemRelationSelector) {
continue;
}
if (sel instanceof TransactionRelationSelector) {
continue;
}
ItemRelationSelector rel = (ItemRelationSelector)sel;
subRes = executeQuery(query, sel);
} else {
GraphQuery subQuery = new GraphQuery();
sel = buildGraph2(subQuery, query, sel);
subRes = executeQuery(subQuery, sel);
}
Template temp = new Template();
temp.setId(sel.getId());
if (sel.hasTemplate()) {
temp.setTemplate(beanProvider.convertCiToBean(sel.fetchTemplate()));
}
temp.setTotalCount(subRes.totalCount);
for (Object match : subRes.matches) {
if (match instanceof IRFC) {
temp.addRFC(convert(ccb, (IRFC)match));
} else if (match instanceof ICi) {
temp.addOffspring(beanProvider.convertCiToBean((ICi)match));
} else if (match instanceof ICmdbTransaction) {
temp.addTransaction(convert(ccb, (ICmdbTransaction)match));
}
}
if (sel.reference()) {
result.addEdges(temp);
} else {
result.addNodes(temp);
}
}
return(result);
}
private TransactionBean convert(ICcb ccb2, ICmdbTransaction match) {
TransactionBean bean = new TransactionBean();
bean.setId(match.getId().asLong());
bean.setBeginTs(match.getBeginTs());
bean.setEndedTs(match.getEndTs());
bean.setCiAdded(match.getCiAdded());
bean.setCiDeleted(match.getCiDeleted());
bean.setCiModified(match.getCiModified());
bean.setIssuer(match.getIssuer());
return(bean);
}
private QueryResult executeQuery(GraphQuery query, ItemSelector selector) {
QueryResult result = new QueryResult();
if (log.isDebugEnabled()) {
log.debug(toXML(query, 0));
}
long t1 = System.currentTimeMillis();
QueryExpression expr = getExpression(query, selector);
if (expr.empty) {
log.debug("Selector:" + selector.getTemplateAlias() +
" Empty !");
result.matches = Collections.EMPTY_LIST;
result.totalCount = 0;
return(result);
}
DetachedCriteria crit = expr.criteria;
QueryExpression exprCopy = getExpression(query, selector);
DetachedCriteria critCopy = exprCopy.criteria;
// Special handling here for RFC...
if (selector instanceof ItemRFCSelector) {
crit.addOrder( Order.desc("ts") );
}
if (selector instanceof ItemTransactionSelector) {
crit.addOrder( Order.desc("endTs") );
}
boolean attributeOrder = false;
if (selector instanceof ItemOffspringSelector) {
if (selector.getOrderInfo() != null) {
OrderInfo info = selector.getOrderInfo();
if (info.getCiAttr() != null) {
if (info.getCiAttr().equals("displayName")) {
DetachedCriteria newCrit = getDisplayNameOrder(selector.getTemplateAlias(), crit, info);
if (newCrit != null) {
crit = newCrit;
attributeOrder = true;
} else {
info.setCiAttr("displayNameExpression");
}
}
if (!attributeOrder) {
if (info.isDescenden()) {
crit.addOrder(Order.desc(info.getCiAttr()));
} else {
crit.addOrder(Order.asc(info.getCiAttr()));
}
}
} else {
crit = getAttributeOrderCriteria(selector.getTemplateAlias(), crit, critCopy, info);
attributeOrder = true;
}
} else {
crit.addOrder(Order.desc("lastModified"));
}
}
List matches = null;
matches = this.msvc.queryCrtiteria(crit, selector.getPageInfo());
// Handle attribute order....
if (attributeOrder) {
final OrderInfo info = selector.getOrderInfo();
List ciMatches = new ArrayList();
if (info.getAttrType().equals("complex")) {
if (false) {
Collections.sort(matches, new Comparator<IAttribute>() {
public int compare(IAttribute o1, IAttribute o2) {
try {
IValue v1 = o1.getValue();
IValue v2 = o2.getValue();
String n1 = v1.getDisplayName();
String n2 = v2.getDisplayName();
if (info.isDescenden()) {
return(n2.compareTo(n1));
} else {
return(n1.compareTo(n2));
}
} catch (Throwable t) {
return(0);
}
}
});
for (Object o : matches) {
if (o instanceof IAttribute) {
ciMatches.add(((IAttribute)o).getOwner());
}
}
} else {
List<Long> targetIds = new ArrayList<Long>();
List<Long> targetAttrOwnerIds = new ArrayList<Long>();
for (Object o : matches) {
if (o instanceof BasicAttribute) {
targetAttrOwnerIds.add(((BasicAttribute)o).getOwnerId());
}
}
if (targetAttrOwnerIds.size() > 0) {
crit = getBackComplexAttributeOrder(targetAttrOwnerIds, critCopy, info);
matches = this.msvc.queryCrtiteria(crit, selector.getPageInfo());
Collections.sort(matches, new Comparator<IAttribute>() {
public int compare(IAttribute o1, IAttribute o2) {
try {
IValue v1 = o1.getValue();
IValue v2 = o2.getValue();
String n1 = v1.getDisplayName();
String n2 = v2.getDisplayName();
if (info.isDescenden()) {
return(n2.compareTo(n1));
} else {
return(n1.compareTo(n2));
}
} catch (Throwable t) {
return(0);
}
}
});
for (Object o : matches) {
if (o instanceof IAttribute) {
ciMatches.add(((IAttribute)o).getOwner());
}
}
}
}
} else {
// here we receives IAttribute in the correct order..
// Need to fetch it's parent.
for (Object o : matches) {
if (o instanceof IAttribute) {
ciMatches.add(((IAttribute)o).getOwner());
}
}
}
matches = ciMatches;
}
long t2 = System.currentTimeMillis();
int totalCount = -1;
if (selector.getPageInfo() != null) {
// Need to do this again else the criteria is already used...
// Don't count null values.
if (attributeOrder && selector.getOrderInfo().getAttrType().equals("complex")) {
ItemAndGroupConstraint and = new ItemAndGroupConstraint();
ItemNotConstraint not = new ItemNotConstraint();
AttributeValueConstraint aV = new AttributeValueConstraint();
aV.setOperation(AttributeValueConstraint.IS_NULL);
aV.setAlias(selector.getOrderInfo().getAttrAlias());
not.applyConstraint(aV);
and.add(not);
ItemSelector prim = query.fetchPrimarySelectors();
if (prim.fetchConstraint() != null) {
and.add(prim.fetchConstraint());
}
prim.applyConstraint(and);
}
QueryExpression expr2 = getExpression(query, selector);
totalCount = this.msvc.queryCrtiteriaCount(expr2.criteria);
}
long t3 = System.currentTimeMillis();
log.info("Selector:" + selector.getTemplateAlias() +
" Found " + matches.size() + "items, time:" + (t2-t1) +
"ms, totalCount=" + totalCount + ", time=" + (t3-t2) + "ms");
result.matches = matches;
result.totalCount = totalCount;
return(result);
}
private DetachedCriteria getDisplayNameOrder(String template, DetachedCriteria ciCrit, OrderInfo info) {
ICi templateCI = this.msvc.findCi(new Path(template));
String expr = templateCI.getDisplayNameExpression();
// Find first ${name}
if (expr == null) {
return(null);
}
int startIndexOf = expr.indexOf("${");
if (startIndexOf < 0) {
return(null);
}
int stopIndexOf = expr.indexOf("}");
if (stopIndexOf < 0) {
return(null);
}
String attrName = expr.substring(startIndexOf+2, stopIndexOf);
OrderInfo nInfo = new OrderInfo();
nInfo.setAttrAlias(attrName);
nInfo.setAttrType("valueAsString");
nInfo.setDescenden(info.isDescenden());
return(getAttributeOrderCriteria(template, ciCrit, null, nInfo));
}
private DetachedCriteria getAttributeOrderCriteria(String template, DetachedCriteria ciCrit, DetachedCriteria ci2Crit,
OrderInfo info) {
if (info.getAttrType().equals("complex")) {
return(getComplexAttributeOrderCriteria2(template, ciCrit, ci2Crit, info));
}
DetachedCriteria crit = DetachedCriteria.forClass(BasicAttribute.class);
DetachedCriteria ciIdProjection = ciCrit.setProjection(Projections.property("longId"));
crit.add(Property.forName("ownerId").in(ciIdProjection));
crit.add(Expression.eq("alias", info.getAttrAlias()));
if (info.isDescenden()) {
crit.addOrder(Order.desc(info.getAttrType()));
} else {
crit.addOrder(Order.asc(info.getAttrType()));
}
return(crit);
}
private DetachedCriteria getBackReferences(DetachedCriteria sourceCrit, List<Long> targetIds, OrderInfo info) {
// Find references that point to targetCrit
DetachedCriteria refCiCrit = DetachedCriteria.forClass(ConfigurationItem.class);
refCiCrit.add(Property.forName("sourceId").in(sourceCrit.setProjection(Projections.property("longId"))));
refCiCrit.add(Property.forName("targetId").in(targetIds));
return(refCiCrit);
}
private DetachedCriteria getBackReferenceCI(List<Long> sourceIds, OrderInfo info) {
DetachedCriteria ciCrit = DetachedCriteria.forClass(ConfigurationItem.class);
ciCrit.add(Property.forName("longId").in(sourceIds));
return(ciCrit);
}
/*
private DetachedCriteria getBackReferenceCI(List<Long> refIds, DetachedCriteria sourceCrit, OrderInfo info) {
// Find references that point to targetCrit
DetachedCriteria refCiCrit = DetachedCriteria.forClass(ConfigurationItem.class);
refCiCrit.add(Property.forName("targetId").in(targetIds));
// Find all attribute that points to the reference
DetachedCriteria sAttrCrit = DetachedCriteria.forClass(BasicAttribute.class);
sAttrCrit.add(Expression.eq("alias", info.getAttrAlias()));
sAttrCrit.add(Property.forName("valueAsLong").in(refCiCrit.setProjection(Projections.property("longId"))));
sourceCrit.add(Property.forName("longId").in(sAttrCrit.setProjection(Projections.property("ownerId"))));
return(sourceCrit);
}
*/
private DetachedCriteria getComplexAttributeOrderCriteria(String template, DetachedCriteria ciCrit,
OrderInfo info) {
DetachedCriteria crit = DetachedCriteria.forClass(BasicAttribute.class);
DetachedCriteria ciIdProjection = ciCrit.setProjection(Projections.property("longId"));
crit.add(Property.forName("ownerId").in(ciIdProjection));
crit.add(Expression.eq("alias", info.getAttrAlias()));
//crit.add(Expression.isNotEmpty("valueAsLong"));
ICi ci = this.msvc.findCi(new Path(template));
IAttribute attr = ci.getAttributeDefinitionWithAlias(info.getAttrAlias());
IType type = attr.getValueType();
String targetTemplate = type.getAlias();
DetachedCriteria refCrit = DetachedCriteria.forClass(ConfigurationItem.class);
refCrit.add(Property.forName("longId").in(crit.setProjection(Projections.property("valueAsLong"))));
DetachedCriteria refCiCrit = DetachedCriteria.forClass(ConfigurationItem.class);
refCiCrit.add(Property.forName("longId").in(refCrit.setProjection(Projections.property("targetId"))));
return(getDisplayNameOrder(targetTemplate, refCiCrit, info));
}
private DetachedCriteria getComplexAttributeOrderCriteria2(String template, DetachedCriteria ciCrit, DetachedCriteria ci2Crit,
OrderInfo info) {
DetachedCriteria orderedAttr = getComplexAttributeOrderCriteria(template, ciCrit, info);
// Serach for this with page info...
return(orderedAttr);
}
private DetachedCriteria getBackComplexAttributeOrder(List<Long> attrOwnerId, DetachedCriteria ci2Crit,
OrderInfo info) {
DetachedCriteria targetCrit = DetachedCriteria.forClass(ConfigurationItem.class);
targetCrit.add(Property.forName("longId").in(attrOwnerId));
DetachedCriteria refCrit = DetachedCriteria.forClass(ConfigurationItem.class);
refCrit.add(Property.forName("targetId").in(targetCrit.setProjection(Projections.property("longId"))));
DetachedCriteria attrCrit = DetachedCriteria.forClass(BasicAttribute.class);
attrCrit.add(Property.forName("valueAsLong").in(refCrit.setProjection(Projections.property("longId"))));
attrCrit.add(Property.forName("ownerId").in(ci2Crit.setProjection(Projections.property("longId"))));
attrCrit.add(Expression.eq("alias", info.getAttrAlias()));
attrCrit.addOrder(Order.desc("longId"));
return(attrCrit);
}
private String toXML(GraphQuery query, int tab) {
StringBuffer b = new StringBuffer();
b.append(getTab(tab));
b.append("<" + query.getClass().getSimpleName() + ">");
b.append("\n");
b.append(getTab(tab+1));
b.append("<selectors>");
b.append("\n");
for (ItemSelector sel : query.fetchSelectors()) {
b.append(toXML(sel, tab+2));
}
b.append(getTab(tab+1));
b.append("</selectors>");
b.append("\n");
b.append(getTab(tab));
b.append("</" + query.getClass().getSimpleName());
b.append("\n");
return(b.toString());
}
private String toXML(ItemSelector selector, int tab) {
StringBuffer b = new StringBuffer();
b.append(getTab(tab));
b.append("<" + selector.getClass().getSimpleName());
b.append(" id=\"" + selector.getId() + "\"");
b.append(" primary=\"" + selector.isPrimary() + "\"");
b.append(">");
b.append("\n");
b.append(getTab(tab+1));
b.append("<templateAlias>" + selector.getTemplateAlias() + "</templateAlias>");
b.append("\n");
if (selector instanceof ItemTransactionSelector) {
b.append(getTab(tab+1));
b.append("<txid>" + ((ItemTransactionSelector)selector).getTxId() + "</txid>");
b.append("\n");
}
if (selector instanceof ItemAliasSelector) {
b.append(getTab(tab+1));
b.append("<alias>" + ((ItemAliasSelector)selector).getAlias() + "</alias>");
b.append("\n");
}
if (selector instanceof ItemRelationSelector) {
ItemRelationSelector relSel = (ItemRelationSelector)selector;
b.append(getTab(tab+1));
b.append("<source>" + ((ItemRelationSelector)selector).getSource() + "</source>");
b.append("\n");
b.append(getTab(tab+1));
b.append("<target>" + ((ItemRelationSelector)selector).getTarget() + "</target>");
b.append("\n");
if (relSel.getSourceRange() != null) {
b.append(getTab(tab+1));
b.append("<sourceRange>");
b.append("\n");
for (Long id : relSel.getSourceRange()) {
b.append(getTab(tab+1));
b.append("<id>" + id + "</id>");
b.append("\n");
}
b.append(getTab(tab+1));
b.append("</sourceRange>");
b.append("\n");
}
if (relSel.getTargetRange() != null) {
b.append(getTab(tab+1));
b.append("<targetRange>");
b.append("\n");
for (Long id : relSel.getTargetRange()) {
b.append(getTab(tab+1));
b.append("<id>" + id + "</id>");
b.append("\n");
}
b.append(getTab(tab+1));
b.append("</targetRange>");
b.append("\n");
}
}
b.append(getTab(tab+1));
b.append("<constraint>");
b.append("\n");
b.append(toXML(selector.fetchConstraint(), tab+2));
b.append(getTab(tab+1));
b.append("</constraint>");
b.append("\n");
if (selector.getPageInfo() != null) {
b.append(getTab(tab+1));
b.append("<pageInfo>");
b.append("\n");
Integer max = selector.getPageInfo().getMaxResult();
if (max != null) {
b.append(getTab(tab+2));
b.append("<maxResult>" + max + "</maxResult>");
b.append("\n");
}
Integer first = selector.getPageInfo().getFirstResult();
if (first != null) {
b.append(getTab(tab+2));
b.append("<firstResult>" + first + "</firstResult>");
b.append("\n");
}
b.append(getTab(tab+1));
b.append("</pageInfo>");
b.append("\n");
}
b.append(getTab(tab));
b.append("</" + selector.getClass().getSimpleName() + ">");
b.append("\n");
return(b.toString());
}
private String toXML(ItemConstraint constraint, int tab) {
StringBuffer b = new StringBuffer();
if (constraint == null) {
return(b.toString());
}
b.append(getTab(tab));
b.append("<" + constraint.getClass().getSimpleName() + ">");
b.append("\n");
if (constraint instanceof ItemGroupConstraint) {
b.append(getTab(tab+1));
b.append("<constraints>");
b.append("\n");
for (ItemConstraint con : ((ItemGroupConstraint)constraint).fetchConstraints()) {
b.append(toXML(con, tab+2));
}
b.append(getTab(tab+1));
b.append("</constraints>");
b.append("\n");
}
if (constraint instanceof ItemSecurityConstraint) {
ItemSecurityConstraint con = (ItemSecurityConstraint)constraint;
if (con.getGid() != null) {
b.append(getTab(tab+1));
b.append("<gid>" + con.getGid() + "</gid>");
b.append("\n");
}
if (con.getGroupName() != null) {
b.append(getTab(tab+1));
b.append("<groupName>" + con.getGroupName() + "</groupName>");
b.append("\n");
}
}
if (constraint instanceof AttributeValueConstraint) {
AttributeValueConstraint con = (AttributeValueConstraint)constraint;
b.append(getTab(tab+1));
b.append("<operation>" + con.getOperation() + "</operation>");
b.append("\n");
b.append(getTab(tab+1));
b.append("<alias>" + con.getAlias() + "</alias>");
b.append("\n");
b.append(getTab(tab+1));
b.append("<value>" + con.getValue() + "</value>");
b.append("\n");
}
if (constraint instanceof RelationConstraint) {
RelationConstraint con = (RelationConstraint)constraint;
b.append(getTab(tab+1));
b.append("<direction>" + con.getDirection() + "</direction>");
b.append("\n");
b.append(getTab(tab+1));
b.append("<selector>" + con.getSelector() + "</selector>");
b.append("\n");
}
b.append(getTab(tab));
b.append("</" + constraint.getClass().getSimpleName() + ">");
b.append("\n");
return(b.toString());
}
private String getTab(int index) {
StringBuffer b = new StringBuffer();
for (int i = 0; i < index; i++) {
b.append("\t");
}
return(b.toString());
}
private ItemSelector buildGraph(GraphQuery q, ItemSelector selector) {
ItemSelector nSelector = selector.clone();
ItemAndGroupConstraint group = new ItemAndGroupConstraint();
if (nSelector.fetchConstraint() != null) {
group.add(nSelector.fetchConstraint());
}
for (ItemSelector sel : q.fetchSelectors()) {
if (sel.reference()) {
ItemRelationSelector rel = (ItemRelationSelector)sel;
if (rel.getSource().equals(selector.getId())) {
group.add(new RelationConstraint(RelationConstraint.SOURCE, rel.getId()));
}
if (rel.getTarget().equals(selector.getId())) {
group.add(new RelationConstraint(RelationConstraint.TARGET, rel.getId()));
}
}
}
nSelector.applyConstraint(group);
return(nSelector);
}
private ItemSelector buildGraph2(GraphQuery newQ, GraphQuery orgQ, ItemSelector selector) {
ItemSelector nSelector = selector.clone();
ItemAndGroupConstraint group = new ItemAndGroupConstraint();
if (nSelector.fetchConstraint() != null) {
group.add(nSelector.fetchConstraint());
}
newQ.addSelector(nSelector);
for (ItemRelationSelector rel : orgQ.fetchRelationSelectors()) {
if (!rel.isMandatory()) {
continue;
}
if (rel.getSource().equals(selector.getId())) {
if (selector.excludeRelation(rel.getId())) {
continue;
}
newQ.addSelector(rel);
ItemSelector targetSel = orgQ.findSelector(rel.getTarget());
if (targetSel == null) {
throw new IllegalArgumentException("RelationSelector[" + rel.getId() + "] target id[" + rel.getTarget() + "] not found.");
}
if (newQ.findSelector(targetSel.getId()) == null) {
buildGraph2(newQ, orgQ, targetSel);
group.add(new RelationConstraint(RelationConstraint.SOURCE, rel.getId()));
}
}
if (rel.getTarget().equals(selector.getId())) {
if (selector.excludeRelation(rel.getId())) {
continue;
}
newQ.addSelector(rel);
ItemSelector sourceSel = orgQ.findSelector(rel.getSource());
if (sourceSel == null) {
throw new IllegalArgumentException("RelationSelector[" + rel.getId() + "] source id[" + rel.getTarget() + "] not found.");
}
if (newQ.findSelector(sourceSel.getId()) == null) {
buildGraph2(newQ, orgQ, sourceSel);
group.add(new RelationConstraint(RelationConstraint.TARGET, rel.getId()));
}
}
}
if (!group.fetchConstraints().isEmpty()) {
nSelector.applyConstraint(group);
}
return(nSelector);
}
protected QueryExpression getExpression(GraphQuery query, ItemSelector selector) {
// OffspringItemSelector
// RelationItemSelector
// Convert the selector to an expression.
QueryExpression queryExpr = new QueryExpression();
// Find Template...
ICi template = selector.fetchTemplate();
if (selector.hasTemplate()) {
if (template == null) {
ItemExpression item = new ItemExpression();
item.setAlias(selector.getTemplateAlias());
List<ICi> cis = msvc.queryCrtiteria(item.getCriteria(), new PageInfo());
if (cis.size() != 1) {
throw new IllegalArgumentException("ItemSelector's template '" + selector.getTemplateAlias() + "' not found!");
}
template = cis.get(0);
selector.bindTemplate(template);
}
}
DetachedCriteria resultCrit = null;
if (selector instanceof ItemOffspringSelector) {
OffspringExpression expr = new OffspringExpression();
// Lookup for alias.
if (template != null) {
expr.setTemplatePath(template.getTemplatePath());
expr.setTemplateID(template.getId().asLong());
}
expr.setMatchTemplate(((ItemOffspringSelector)selector).getMatchTemplate());
expr.setLimitToChild(((ItemOffspringSelector)selector).isLimitToChild());
resultCrit = expr.getCriteria();
} else if (selector instanceof ItemAliasSelector) {
// Validate...
if (((ItemAliasSelector)selector).getAlias() == null && ((ItemAliasSelector)selector).getAliases() == null) {
queryExpr.empty = true;
return(queryExpr);
}
if (((ItemAliasSelector)selector).getAlias() == null) {
if (((ItemAliasSelector)selector).getAliases().size() == 0) {
queryExpr.empty = true;
return(queryExpr);
}
}
ItemExpression aliasExpr = new ItemExpression();
aliasExpr.setAlias(((ItemAliasSelector)selector).getAlias());
aliasExpr.setAliases(((ItemAliasSelector)selector).getAliases());
resultCrit = aliasExpr.getCriteria();
} else if (selector instanceof ItemRFCSelector) {
RFCExpression rfcExpr = new RFCExpression();
rfcExpr.setType(selector.getTemplateAlias());
rfcExpr.setTxId(((ItemRFCSelector)selector).getTxId());
resultCrit = rfcExpr.getCriteria();
} else if (selector instanceof ItemTransactionSelector) {
TransactionExpression transactionExpr = new TransactionExpression();
transactionExpr.setTxid(((ItemTransactionSelector)selector).getTxId());
resultCrit = transactionExpr.getCriteria();
} else if (selector instanceof ItemRelationSelector) {
RelationExpression expr = new RelationExpression();
ItemRelationSelector rel = (ItemRelationSelector)selector;
if (rel.getSourceRange() != null) {
if (rel.getSourceRange().size() == 0) {
log.info("RelationSelector[" + rel.getId() + "] SourceRange Empty!");
queryExpr.empty = true;
return(queryExpr);
}
expr.setSourceIds(rel.getSourceRange());
} else {
ItemSelector sourceSel = query.findSelector(rel.getSource());
if (sourceSel == null) {
throw new IllegalArgumentException("RelationSelector[" + rel.getId() + "] source id[" + rel.getSource() + "] not found.");
}
QueryExpression sExpr = getExpression(query, sourceSel);
if (sExpr.empty) {
queryExpr.empty = sExpr.empty;
return(queryExpr);
}
expr.setSource(sExpr.criteria);
}
if (rel.getTargetRange() != null) {
if (rel.getTargetRange().size() == 0) {
log.info("RelationSelector[" + rel.getId() + "] TargetRange Empty!");
queryExpr.empty = true;
return(queryExpr);
}
expr.setTargetIds(rel.getTargetRange());
} else {
ItemSelector targetSel = query.findSelector(rel.getTarget());
if (targetSel == null) {
throw new IllegalArgumentException("RelationSelector[" + rel.getId() + "] target id[" + rel.getTarget() + "] not found.");
}
QueryExpression tExpr = getExpression(query, targetSel);
if (tExpr.empty) {
queryExpr.empty = tExpr.empty;
return(queryExpr);
}
expr.setTarget(tExpr.criteria);
}
resultCrit = expr.getCriteria();
} else {
throw new IllegalArgumentException("ItemSelector type [" + selector.getClass().getName() + "] is not supported!");
}
ItemConstraint constraint = selector.fetchConstraint();
if (constraint != null) {
Criterion crit = getConstraint2(query, constraint);
if (crit == null) {
queryExpr.empty = true;
} else {
resultCrit.add(crit);
}
}
queryExpr.criteria = resultCrit;
return(queryExpr);
}
private Criterion getConstraint2(GraphQuery query, ItemConstraint cons) {
if (cons instanceof ItemGroupConstraint) {
ItemGroupConstraint group = (ItemGroupConstraint)cons;
Junction j = null;
if (group.conjunction()) {
j = Restrictions.conjunction();
} else {
j = Restrictions.disjunction();
}
for (Iterator iter = group.fetchConstraints().iterator(); iter.hasNext();) {
ItemConstraint con = (ItemConstraint)iter.next();
Criterion criterion = getConstraint2(query, con);
if (group.conjunction()) {
if (criterion == null) {
return(null);
}
}
if (criterion != null) {
j.add(criterion);
}
}
return(j);
}
if (cons instanceof ItemNotConstraint) {
ItemConstraint notCons = ((ItemNotConstraint)cons).fetchConstraint();
if (notCons == null) {
throw new IllegalArgumentException("ItemNotGroupConstraint must containt a constraint");
}
Criterion notCrit = getConstraint2(query, notCons);
return(Expression.not(notCrit));
}
if (cons instanceof RelationConstraint) {
RelationConstraint rel = (RelationConstraint)cons;
DetachedCriteria crit = null;
String direction = null;
ItemSelector selector = query.findSelector(rel.getSelector());
if (!(selector instanceof ItemRelationSelector)) {
throw new IllegalArgumentException("RelationExpression selector " + rel.getSelector() + " is not a ItemRelationSelection!");
}
RelationExpression relExpr = new RelationExpression();
if (selector instanceof RFCItemRelationSelector) {
relExpr = new RFCRelationExpression();
} else if (selector instanceof TransactionRelationSelector) {
relExpr = new TransactionRelationExpression();
}
ItemRelationSelector relSelector = (ItemRelationSelector)selector;
Criterion relation = null;
if (rel.isTarget()) {
if (relSelector.getSourceRange() != null) {
if (relSelector.getSourceRange().size() == 0) {
log.info("RelationConstraint RelationSelector[" + relSelector.getId() + "] SourceRange Empty!");
return(null);
}
relExpr.setSourceIds(relSelector.getSourceRange());
} else {
String srcId = ((ItemRelationSelector)selector).getSource();
ItemSelector sel = (ItemSelector) query.findSelector(srcId);
QueryExpression sExpr = getExpression(query, sel);
if (sExpr.empty) {
return(null);
}
DetachedCriteria source = sExpr.criteria;
relExpr.setSource(source);
}
relation = relExpr.getSourceCriterion();
/*
crit = relExpr.getSourceCriteria();
relation = Property.forName("longId").in(crit.setProjection(Projections.property("targetId")));
*/
} else {
if (relSelector.getTargetRange() != null) {
if (relSelector.getTargetRange().size() == 0) {
log.info("RelationConstraint RelationSelector[" + relSelector.getId() + "] TargetRange Empty!");
return(null);
}
relExpr.setTargetIds(relSelector.getTargetRange());
//relation = Property.forName("longId").in(relSelector.getTargetRange());
} else {
String trgId = ((ItemRelationSelector)selector).getTarget();
ItemSelector sel = query.findSelector(trgId);
QueryExpression tExpr = getExpression(query, sel);
if (tExpr.empty) {
return(null);
}
DetachedCriteria target = tExpr.criteria;
relExpr.setTarget(target);
}
relation = relExpr.getTargetCriterion();
/*
crit = relExpr.getTargetCriteria();
relation = Property.forName("longId").in(crit.setProjection(Projections.property("sourceId")));
*/
}
log.debug(relation.toString());
return(relation);
}
if (cons instanceof AttributeValueConstraint) {
AttributeValueConstraint aValue = (AttributeValueConstraint)cons;
AttributeValueExpression aExpr = new AttributeValueExpression();
aExpr.setAlias(aValue.getAlias());
aExpr.setOperation(aValue.getOperation());
aExpr.setType(aValue.getValueType());
aExpr.setStringValue(aValue.getValue());
if (aExpr.isInternal()) {
return(aExpr.getInternalCriterion());
}
DetachedCriteria attr = aExpr.getCriteria();
return(Property.forName("longId").in(attr.setProjection(Projections.property("ownerId"))));
}
if (cons instanceof ItemSecurityConstraint) {
ItemSecurityConstraint sCon = (ItemSecurityConstraint)cons;
if (sCon.getGid() != null) {
return(Property.forName("gid").eq(sCon.getGid()));
}
ItemExpression expr = new ItemExpression();
expr.setAlias(sCon.getGroupName());
DetachedCriteria gid = expr.getCriteria();
return(Property.forName("gid").in(gid.setProjection(Projections.property("longId"))));
}
if (cons instanceof ItemIdConstraint) {
ItemIdConstraint idContrain = (ItemIdConstraint)cons;
if (idContrain.getId() != null) {
return(Restrictions.idEq(idContrain.getId()));
}
if (idContrain.getAlias() != null) {
return(Property.forName("alias").eq(idContrain.getAlias()));
}
}
if (cons instanceof RFCTargetConstraint) {
return(Property.forName("targetId").eq(((RFCTargetConstraint)cons).getLongId()));
}
if (cons instanceof AttributeSourceRelationConstraint) {
AttributeSourceRelationConstraint relACons = (AttributeSourceRelationConstraint)cons;
AttributeValueExpression expr = new AttributeValueExpression();
expr.setAlias(relACons.getAlias());
DetachedCriteria crit = expr.getCriteria();
return(Property.forName("sourceId").in(crit.setProjection(Projections.property("valueAsLong"))));
}
log.error("Constraint{" + cons.getClass().getSimpleName() + "] not implemented!");
return(null);
}
private RFCBean convert(ICcb ccbSvc, IRFC rfc) {
IModelService mSvc = (IModelService) this.session.getService(IModelService.class);
// Return this list.
RFCBean rfcBean = new RFCBean();
rfcBean.setId(rfc.getId());
rfcBean.setSummary(RFCSummaryDecorator.decorateSummary(mSvc, rfc));
rfcBean.setTransactionId(rfc.getTxId());
rfcBean.setTs(rfc.getTs());
rfcBean.setTargetId(rfc.getTargetId());
rfcBean.setTargetCIId(rfc.getTargetCIId());
if (ccbSvc != null) {
// Retrieve the Transaction to get the issuer.
ICmdbTransaction tx = ccbSvc.findTxForRfc(rfc);
rfcBean.setIssuer(tx.getIssuer());
}
return(rfcBean);
}
/*
private Criterion convertConstraint(GraphQuery query, DetachedCriteria parent, ItemConstraint cons) {
if (cons instanceof ItemGroupConstraint) {
ItemGroupConstraint group = (ItemGroupConstraint)cons;
Junction j = null;
if (group.isConjunction()) {
j = Restrictions.conjunction();
} else {
j = Restrictions.disjunction();
}
for (Iterator iter = group.getConstraints().iterator(); iter.hasNext();) {
ItemConstraint con = (ItemConstraint)iter.next();
j.add(convertConstraint(query, parent, con));
}
return(j);
}
/*
if (cons instanceof RelationConstraint) {
RelationConstraint rel = (RelationConstraint)cons;
DetachedCriteria crit = null;
String direction = null;
RelationExpression relExpr = new RelationExpression();
ItemSelector selector = query.findSelector(rel.getSelector());
if (!(selector instanceof ItemRelationSelector)) {
throw new IllegalArgumentException("RelationExpression need a ItemRelationSelection!");
}
if (rel.isTarget()) {
direction = "targetId";
String srcId = ((ItemRelationSelector)selector).getSource();
ItemSelector sel = query.findSelector(srcId);
DetachedCriteria source = getExpression(query, sel);
relExpr.setSource(source);
crit = relExpr.getSourceCriteria();
} else {
direction = "sourceId";
String trgId = ((ItemRelationSelector)selector).getTarget();
ItemSelector sel = query.findSelector(trgId);
DetachedCriteria target = getExpression(query, sel);
relExpr.setTarget(target);
crit = relExpr.getTargetCriteria();
}
parent.add(Property.forName("longId").in(crit.setProjection(Projections.property(direction))));
}
if (cons instanceof AttributeValueConstraint) {
AttributeValueConstraint aValue = (AttributeValueConstraint)cons;
AttributeValueExpression aExpr = new AttributeValueExpression();
aExpr.setAlias(aValue.getAlias());
aExpr.setOperation(aValue.getOperation());
//aExpr.setType(aValue.get);
aExpr.setStringValue(aValue.getValue());
DetachedCriteria attr = aExpr.getCriteria();
//DetachedCriteria ownerCI = DetachedCriteria.forClass(ConfigurationItem.class);
parent.add(Property.forName("longId").in(attr.setProjection(Projections.property("ownerId"))));
}
return(null);
}
*/
}