/*
* 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.policy;
import java.util.HashMap;
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.IAttributePolicy;
import org.onecmdb.core.ICi;
import org.onecmdb.core.IObjectScope;
import org.onecmdb.core.IRFC;
import org.onecmdb.core.IRfcResult;
import org.onecmdb.core.internal.ccb.rfc.RFCModifyAttributeValue;
import org.onecmdb.core.internal.ccb.workers.RfcResult;
import org.onecmdb.core.internal.model.BasicAttribute;
import org.onecmdb.core.internal.model.ConfigurationItem;
import org.onecmdb.core.utils.ClassInjector;
public class AttributePolicy extends ConfigurationItem implements IAttributePolicy {
protected String attributeAliasPattern = ".*";
protected boolean propagateValueChangeToTemplates = false;
protected boolean valueUniqueInInstance = false;
protected boolean valueUniqueOnAllInstances = false;
protected boolean allowValueChange = true;
protected boolean propagateValueChangeToInstances = false;
protected boolean propagateInitialValueChange = true;
protected String valuePattern = null;
protected boolean allowTypeChange = true;
protected boolean allowReferenceTypeChange = true;
private Log log = LogFactory.getLog(this.getClass());
interface IAttributeRfcPolicyValidator {
public IRfcResult validate(IObjectScope scope, IRFC rfc, IAttribute a);
}
private HashMap<Class, IAttributeRfcPolicyValidator> validatorMap = new HashMap<Class, IAttributeRfcPolicyValidator>();
public AttributePolicy(ICi ci) {
super.copy((ConfigurationItem)ci);
ClassInjector inject = new ClassInjector();
inject.injectAttributes(this, ci);
setupValidatorMap();
}
private void setupValidatorMap() {
validatorMap.put(RFCModifyAttributeValue.class, getModifyValueValidator());
}
public IRfcResult runValidation(IObjectScope scope, IRFC rfc, IAttribute a) {
IRfcResult result = new RfcResult();
String aliasPattern = getAttributeAliasPattern();
if (aliasPattern == null) {
log .warn("No 'attributeAliasPattern' defined in attribute policy '" + this.getAlias() + "'");
return(result);
}
if (a.getAlias() == null) {
return(result);
}
if (!a.getAlias().matches(aliasPattern)) {
return(result);
}
// Its for us...
IAttributeRfcPolicyValidator validator = validatorMap.get(rfc.getClass());
if (validator != null) {
result = validator.validate(scope, rfc, a);
}
return(result);
}
private IAttributeRfcPolicyValidator getAddAttributeValidator() {
return (new IAttributeRfcPolicyValidator() {
public IRfcResult validate(IObjectScope scope, IRFC iRfc, IAttribute a) {
RfcResult result = new RfcResult();
return(result);
}
});
}
private IAttributeRfcPolicyValidator getModifyTypeValidator() {
return (new IAttributeRfcPolicyValidator() {
public IRfcResult validate(IObjectScope scope, IRFC iRfc, IAttribute a) {
RfcResult result = new RfcResult();
if (!isAllowTypeChange()) {
result
.setRejectCause("Type changes not are allowed according to policy");
return (result);
}
return(result);
}
});
}
private IAttributeRfcPolicyValidator getModifyReferenceTypeValidator() {
return (new IAttributeRfcPolicyValidator() {
public IRfcResult validate(IObjectScope scope, IRFC iRfc, IAttribute a) {
RfcResult result = new RfcResult();
if (!isAllowReferenceTypeChange()) {
result
.setRejectCause("Type changes not are allowed according to policy");
return (result);
}
return(result);
}
});
}
private IAttributeRfcPolicyValidator getModifyValueValidator() {
return (new IAttributeRfcPolicyValidator() {
public IRfcResult validate(IObjectScope scope, IRFC iRfc, IAttribute a) {
RfcResult result = new RfcResult();
if (!(iRfc instanceof RFCModifyAttributeValue)) {
log.error("Internal error: RFCModifyAttributeValue policy validator called with wrong RFC '" + iRfc.getClass().getName() + "'");
return(result);
}
RFCModifyAttributeValue rfc = (RFCModifyAttributeValue)iRfc;
if (!isAllowValueChange()) {
// Validate that it's not on root policy
ICi ci = scope.getAttributeOwner(a);
// Sanity check, allways be able to modify myself.
if (!ci.getId().equals(getId())) {
result.setRejectCause("Value changes not are allowed according to policy");
return (result);
}
}
if (isValueUniqueOnAllInstances()) {
if (a.getDerivedFrom() != null) {
Set<ICi> attributes = a.getDerivedFrom().getOffsprings();
for (ICi ci : attributes) {
// Should always be.
if (ci instanceof IAttribute) {
IAttribute ia = (IAttribute) ci;
if (((BasicAttribute) ia).getValueAsString().equals(
(rfc).getNewValue())) {
result.setRejectCause("Value must be unique on all instances!");
return (result);
}
}
}
}
}
if (isValueUniqueInInstance()) {
ICi ci = a.getOwner();
for (IAttribute ciA : ci.getAttributesWithAlias(a.getAlias())) {
if (ciA.equals(a)) {
continue;
}
if (((BasicAttribute)ciA).getValueAsString().equals(
((RFCModifyAttributeValue)rfc).getNewValue())) {
result.setRejectCause("Value must be unique on instance!");
return (result);
}
}
}
// Check pattern.
String pattern = getValuePattern();
if (pattern != null && rfc.getNewValue() != null) {
ICi ci = scope.getAttributeOwner(a);
// Sanity check, allways be able to modify myself.
if (!ci.getId().equals(getId())) {
if (!pattern.equals("")) {
if (!rfc.getNewValue().matches(pattern)) {
result.setRejectCause("Value '" + rfc.getNewValue() + "' don't match pattern '" + pattern + "' according to policy");
return(result);
}
}
}
}
// Modify all offsprings of this IAttribute
if (isPropagateValueChangeToInstances()) {
propagateValue(scope, rfc, a, false);
}
if (isPropagateValueChangeToTemplates()) {
propagateValue(scope, rfc, a, true);
}
if (isPropagateInitialValueChange()) {
propagateInitalValue(scope, rfc, a);
}
return(result);
}
});
}
/**
* Propagate value changes to template or instance offsprings.
* Always propagte attribute is null.
* @param scope
* @param rfc
* @param attr
*/
protected void propagateValue(IObjectScope scope, RFCModifyAttributeValue rfc, IAttribute attr, boolean templates) {
if (attr.isBlueprint()) {
Set<ICi> offsprings = scope.getOffspringForCi(attr);
for (ICi offspring : offsprings) {
BasicAttribute ba = (BasicAttribute)offspring;
if (offspring.isBlueprint() == templates || ba.getValueAsString() == null) {
RFCModifyAttributeValue setValueRfc = new RFCModifyAttributeValue();
setValueRfc.setTarget(offspring);
setValueRfc.setNewValueAsAlias(rfc.getNewValueAsAlias());
setValueRfc.setNewValue(rfc.getNewValue());
rfc.add(setValueRfc);
}
}
}
}
protected void propagateInitalValue(IObjectScope scope, RFCModifyAttributeValue rfc, IAttribute attr) {
if (attr.isBlueprint()) {
Set<ICi> offsprings = scope.getOffspringForCi(attr);
for (ICi offspring : offsprings) {
BasicAttribute ba = (BasicAttribute)offspring;
if (ba.getValueAsString() == null) {
RFCModifyAttributeValue setValueRfc = new RFCModifyAttributeValue();
setValueRfc.setTarget(offspring);
setValueRfc.setNewValueAsAlias(rfc.getNewValueAsAlias());
setValueRfc.setNewValue(rfc.getNewValue());
rfc.add(setValueRfc);
}
}
}
}
/**
* Getter/Setters.
*/
public boolean isAllowValueChange() {
return allowValueChange;
}
public void setAllowValueChange(boolean allowValueChange) {
this.allowValueChange = allowValueChange;
}
public String getAttributeAliasPattern() {
return attributeAliasPattern;
}
public void setAttributeAliasPattern(String attributeAliasPattern) {
this.attributeAliasPattern = attributeAliasPattern;
}
public boolean isPropagateValueChangeToInstances() {
return propagateValueChangeToInstances;
}
public void setPropagateValueChangeToInstances(
boolean propagateValueChangeToInstances) {
this.propagateValueChangeToInstances = propagateValueChangeToInstances;
}
public boolean isPropagateValueChangeToTemplates() {
return propagateValueChangeToTemplates;
}
public void setPropagateValueChangeToTemplates(
boolean propagateValueChangeToTemplates) {
this.propagateValueChangeToTemplates = propagateValueChangeToTemplates;
}
public boolean isValueUniqueInInstance() {
return valueUniqueInInstance;
}
public void setValueUniqueInInstance(boolean valueUniqueInInstance) {
this.valueUniqueInInstance = valueUniqueInInstance;
}
public boolean isValueUniqueOnAllInstances() {
return valueUniqueOnAllInstances;
}
public void setValueUniqueOnAllInstances(boolean valueUniqueOnAllInstances) {
this.valueUniqueOnAllInstances = valueUniqueOnAllInstances;
}
public boolean isAllowReferenceTypeChange() {
return allowReferenceTypeChange;
}
public void setAllowReferenceTypeChange(boolean allowReferenceTypeChange) {
this.allowReferenceTypeChange = allowReferenceTypeChange;
}
public boolean isAllowTypeChange() {
return allowTypeChange;
}
public void setAllowTypeChange(boolean allowTypeChange) {
this.allowTypeChange = allowTypeChange;
}
public String getValuePattern() {
return valuePattern;
}
public void setValuePattern(String valuePattern) {
this.valuePattern = valuePattern;
}
public boolean isPropagateInitialValueChange() {
return propagateInitialValueChange;
}
public void setPropagateInitialValueChange(boolean propagateInitialValueChange) {
this.propagateInitialValueChange = propagateInitialValueChange;
}
}