/*
* 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.internal.ccb;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.onecmdb.core.IAttribute;
import org.onecmdb.core.IAuthorizationService;
import org.onecmdb.core.ICi;
import org.onecmdb.core.IObjectScope;
import org.onecmdb.core.IRFC;
import org.onecmdb.core.ISession;
import org.onecmdb.core.internal.model.BasicAttribute;
import org.onecmdb.core.internal.model.ConfigurationItem;
import org.onecmdb.core.internal.model.ItemId;
import org.onecmdb.core.internal.model.Path;
import org.onecmdb.core.internal.storage.IDaoReader;
public class CcbObjectScope implements IObjectScope {
private ISession session;
private IDaoReader reader;
HashMap<ItemId, ICi> newMap = new HashMap<ItemId, ICi>();
HashMap<ItemId, ICi> modifyMap = new HashMap<ItemId, ICi>();
HashMap<ItemId, ICi> destroyMap = new HashMap<ItemId, ICi>();
HashMap<ItemId, ICi> rfcMap = new HashMap<ItemId, ICi>();
HashMap<String, ICi> aliasMap = new HashMap<String, ICi>();
private HashMap<ICi, Set<IAttribute>> attributeMap = new HashMap<ICi, Set<IAttribute>>();
private HashMap<IAttribute, ICi> attributeToOwnerMap = new HashMap<IAttribute, ICi>();
private HashMap<ICi, Set<ICi>> offspringMap = new HashMap<ICi, Set<ICi>>();
// Simple cache...
HashMap<String, ICi> aliasCache = new HashMap<String, ICi>();
HashMap<ItemId, ICi> idCache = new HashMap<ItemId, ICi>();
private int ciModified = 0;
private int ciAdded = 0;
private int ciDeleted = 0;
private IAuthorizationService auth;
public CcbObjectScope(ISession session, IDaoReader reader) {
this.reader = reader;
this.session = session;
this.auth = (IAuthorizationService) session.getService(IAuthorizationService.class);
}
public ISession getSession() {
return(this.session);
}
public Collection<ICi> getNewICis() {
return (newMap.values());
}
public Collection<ICi> getModifiedICis() {
return (modifyMap.values());
}
public Collection<ICi> getDestroyedICis() {
return (destroyMap.values());
}
public ICi getICiFromAlias(String alias) {
ICi ci = aliasMap.get(alias);
if (ci != null) {
return (ci);
}
ci = aliasCache.get(alias);
if (ci != null) {
return(ci);
}
// Serach the dao.
ci = reader.findCiByAlias(new Path<String>(alias));
// Put in cache...
if (ci != null) {
aliasCache.put(alias, ci);
}
return(ci);
}
public ICi getICiById(ItemId id) {
// System.out.println("FIND CI [" + id + "]");
// Check internal maps.
ICi ci = newMap.get(id);
if (ci != null) {
return (ci);
}
ci = modifyMap.get(id);
if (ci != null) {
return (ci);
}
ci = idCache.get(id);
if (ci != null) {
return(ci);
}
ci = reader.findById(id);
if (ci != null) {
idCache.put(id, ci);
}
return(ci);
}
/*
* public void mapRfcToCi(IRFC rfc, ICi ci) { //System.out.println("MAP
* RFC[" + rfc.getItemId() +"]-->ICI" + ci.getId()); rfcMap.put(rfc.getId(),
* ci); }
*
*
* public ICi getCIFromRfc(ItemId source) { ICi ci = rfcMap.get(source);
* return(ci); }
*/
public void addNewICi(ICi ci) {
// Verify Permission...
if (auth != null) {
auth.validateCreatePermission(session, ci);
}
// System.out.println("NEW CI[" + ci.getId() +"]");
// TODO: Should we thorw an Error here, or an Exception!
// Consult Spring...
if (modifyMap.containsKey(ci.getId())) {
throw new IllegalAccessError("Can't add new item[" + ci.getId()
+ "] when it exists in modify map");
}
((ConfigurationItem) ci).setDaoReader(this.reader);
newMap.put(ci.getId(), ci);
idCache.put(ci.getId(), ci);
if (ci.getAlias() != null) {
if (!(ci instanceof IAttribute)) {
aliasMap.put(ci.getAlias(), ci);
}
}
// Update ts.
Date create = new Date();
((ConfigurationItem)ci).setCreateTime(create);
((ConfigurationItem)ci).setLastModified(create);
if (ci instanceof IAttribute) {
ICi owner = getAttributeOwner((IAttribute)ci);
if (owner != null) {
addModifiedICi(owner);
}
}
}
public void addModifiedICi(ICi ci) {
// Verify Permission...
if (auth != null) {
auth.validateWritePermission(session, ci);
}
if (destroyMap.containsKey(ci.getId())) {
return;
}
// System.out.println("MODIFY CI[" + ci.getId() +"]");
if (ci.getAlias() != null) {
if (!(ci instanceof IAttribute)) {
aliasMap.put(ci.getAlias(), ci);
}
}
// TODO: Is this ok, or should we throw something here.
if (newMap.containsKey(ci.getId())) {
// Already known.
return;
}
idCache.put(ci.getId(), ci);
modifyMap.put(ci.getId(), ci);
// Update ts.
((ConfigurationItem)ci).setLastModified(new Date());
if (ci instanceof IAttribute) {
ICi owner = getAttributeOwner((IAttribute)ci);
if (owner != null) {
addModifiedICi(owner);
}
}
}
public void addDestroyedICi(ICi ci) {
// Verify Permission...
if (auth != null) {
auth.validateDeletePermission(session, ci);
}
// Remove from all maps...
aliasMap.remove(ci.getAlias());
modifyMap.remove(ci.getId());
newMap.remove(ci.getId());
destroyMap.put(ci.getId(), ci);
// Update ts.
if (ci instanceof IAttribute) {
// To speed things up.
Long id = ((BasicAttribute)ci).getOwnerId();
if (id != null) {
if (!destroyMap.containsKey(new ItemId(id))) {
long start = System.currentTimeMillis();
ICi owner = getAttributeOwner((IAttribute)ci);
if (owner != null) {
addModifiedICi(owner);
}
}
}
}
}
public Set<ICi> getOffspringForCi(ICi ci) {
Set<ICi> set = offspringMap.get(ci);
if (set == null) {
set = new HashSet<ICi>();
}
// Refresh from db.
set.addAll(ci.getOffsprings());
return (set);
}
public void addOffspringToCi(ICi parent, ICi offspring) {
Set<ICi> set = offspringMap.get(parent);
if (set == null) {
set = new HashSet<ICi>();
offspringMap.put(parent, set);
}
set.add(offspring);
}
public Set<IAttribute> getAttributesForCi(ICi ci) {
if (ci == null) {
return(Collections.EMPTY_SET);
}
Set<IAttribute> set = attributeMap.get(ci);
if (set == null) {
set = new HashSet<IAttribute>();
}
// Refresh from db only if the ci is not a new one.
if (!newMap.containsKey(ci.getId())) {
set.addAll(ci.getAttributes());
}
// Store these in the idMap.
for (IAttribute a: set) {
idCache.put(a.getId(), a);
}
return (set);
}
public void addAttributeToCi(ICi item, IAttribute ba) {
Set<IAttribute> set = attributeMap.get(item);
if (set == null) {
set = new HashSet<IAttribute>();
attributeMap.put(item, set);
}
set.add(ba);
// add in reverse map.
attributeToOwnerMap.put(ba, item);
}
public IAttribute getAttributeFromRFC(IRFC rfc) {
Long itemId = rfc.getTargetId();
if (itemId != null) {
// Target point's to the Ci
IAttribute attribute = reader.findAttributeById(new ItemId(itemId));
if (attribute != null) {
return (attribute);
}
}
return((IAttribute)getCIFromRFC(rfc));
}
public ICi getCIFromRFC(IRFC rfc) {
Long itemId = rfc.getTargetId();
if (itemId != null) {
// Target point's to the Ci
ICi ci = getICiById(new ItemId(itemId));
return (ci);
}
String alias = rfc.getTargetAlias();
if (alias != null) {
ICi ci = getICiFromAlias(alias);
return (ci);
}
// Need to serach upward.
IRFC parent = rfc.getParent();
if (parent == null) {
return (null);
}
return (getCIFromRFC(parent));
}
public IDaoReader getDaoReader() {
return (this.reader);
}
public ICi getAttributeOwner(IAttribute attribute) {
ICi ci = attributeToOwnerMap.get(attribute);
if (ci != null) {
return(ci);
}
if (attribute instanceof BasicAttribute) {
Long id = ((BasicAttribute)attribute).getOwnerId();
if (id != null) {
ci = newMap.get(new ItemId(id));
if (ci != null) {
return(ci);
}
ci = modifyMap.get(new ItemId(id));
if (ci != null) {
return(ci);
}
}
}
return(attribute.getOwner());
}
public boolean isDestroyed(ICi ci) {
return(destroyMap.containsKey(ci.getId()));
}
/**
* Statistics....
*/
private int getUniqueCIs(Collection<ICi> cis) {
HashSet<Long> marked = new HashSet<Long>();
for (ICi ci : cis) {
if (ci instanceof BasicAttribute) {
marked.add(((BasicAttribute)ci).getOwnerId());
} else {
marked.add(ci.getId().asLong());
}
}
return(marked.size());
}
public int getCiModified() {
return(getUniqueCIs(getModifiedICis()));
}
public int getCiAdded() {
return(getUniqueCIs(getNewICis()));
}
public int getCiDeleted() {
return(getUniqueCIs(getDestroyedICis()));
}
public List<IAttribute> getAttributeForReference(ICi referrer) {
List<IAttribute> attributes = reader.getAttributesReferringTo(referrer);
return(attributes);
}
/**
* Get all reference ci that has target as ci.
*/
public List<ICi> getReferrer(ICi ci) {
List<IAttribute> attributes = reader.getTargetReference(ci);
List<ICi> references = new ArrayList<ICi>();
for (IAttribute attribute : attributes) {
references.add(attribute.getOwner());
}
return(references);
}
}