/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 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.
*
*
* Copyright 2005-2008 Pentaho Corporation. All rights reserved.
*
* @created Jun 15, 2005
* @author Marc Batchelor
*
*/
package org.pentaho.platform.engine.services.runtime;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.repository.IRuntimeElement;
import org.pentaho.platform.api.repository.RepositoryException;
import org.pentaho.platform.engine.core.system.PentahoBase;
import org.pentaho.platform.engine.services.messages.Messages;
import org.pentaho.platform.util.xml.XmlHelper;
public class SimpleRuntimeElement extends PentahoBase implements IRuntimeElement {
private static final long serialVersionUID = 5024690844237335928L;
private static final Log logger = LogFactory.getLog(SimpleRuntimeElement.class);
private String instanceId;
private String parentId;
private String solutionId;
private String parentType;
private int revision;
private Map typesMap = new HashMap(); // The total list of properties and
// their types
private Map paramMapSS = new HashMap(); // ShortString Map ( VARCHAR(254) )
private Map paramMapLS = new HashMap(); // LongString Map ( CLOB )
private Map paramMapBD = new HashMap(); // BigDecimal Map
private Map paramMapDT = new HashMap(); // Date Map
private Map paramMapLong = new HashMap(); // Long Map
private Map paramMapCPLX = new HashMap(); // Complex Map (Serialized as a
// Blob)
private static final int MAXSSLENGH = 254;
private static final ThreadLocal allowableReadAttributeNames = new ThreadLocal();
private boolean loaded;
private boolean readOnly;
// TODO: Implement check on every set and get to make sure that the
// attribute is allowed to be read/written
/**
* Constructor for Hibernate
*/
protected SimpleRuntimeElement() {
}
/**
* Constructor
*
* @param instId
* The Instance Id
*/
public SimpleRuntimeElement(final String instId) {
instanceId = instId;
}
/**
* Constructor
*
* @param instId
* The Instance Id
* @param parId
* The Parent Id
* @param parType
* The Parent Type
*/
public SimpleRuntimeElement(final String instId, final String parId, final String parType) {
instanceId = instId;
parentId = parId;
parentType = parType;
}
/**
* Constructor
*
* @param instId
* The Instance Id
* @param parId
* The Parent Id
* @param parType
* The Parent Type
* @param solnId
* The Solution Id
*/
public SimpleRuntimeElement(final String instId, final String parId, final String parType, final String solnId) {
instanceId = instId;
parentId = parId;
parentType = parType;
solutionId = solnId;
}
public List getMessages() {
return null;
}
protected void setPentahoSession(final IPentahoSession sess) {
genLogIdFromSession(sess);
}
/**
* @return Returns the parentId.
*/
public String getParentId() {
return parentId;
}
/**
* @param parentId
* The parentId to set.
*/
public void setParentId(final String parentId) {
this.updateOk();
this.parentId = parentId;
}
/**
* @return Returns the parentType.
*/
public String getParentType() {
return parentType;
}
/**
* @param parentType
* The parentType to set.
*/
public void setParentType(final String parentType) {
this.updateOk();
this.parentType = parentType;
}
/**
* @return Returns the instanceId.
*/
public String getInstanceId() {
return instanceId;
}
/**
* @param instId
* The instanceId to set.
*/
public void setInstanceId(final String instId) {
this.updateOk();
this.instanceId = instId;
}
/**
* @return Returns the solutionId.
*/
public String getSolutionId() {
return solutionId;
}
/**
* @param solutionId
* The solutionId to set.
*/
public void setSolutionId(final String solutionId) {
this.updateOk();
this.solutionId = solutionId;
}
/**
* Auto-handled revision mechanism.
*
* @return The current revision
*/
public int getRevision() {
return revision;
}
/**
* Sets the revision of the class
*
* @param rev
* New revision to set.
*/
protected void setRevision(final int rev) {
revision = rev;
}
/**
* Uses the instanceId to distinguish equality. The instanceId will never be
* null, won't change, and is the primary key. Therefore, it's the perfect
* candidate for equals() and hashcode.
*/
@Override
public boolean equals(final Object other) {
if (this == other) {
return true;
}
if (!(other instanceof IRuntimeElement)) {
return false;
}
final IRuntimeElement otherRE = (IRuntimeElement) other;
return this.getInstanceId().equals(otherRE.getInstanceId());
}
@Override
public int hashCode() {
return this.getInstanceId().hashCode();
}
protected Map getParamMapSS() {
return paramMapSS;
}
protected Map getParamMapLS() {
return paramMapLS;
}
protected Map getParamMapDT() {
return paramMapDT;
}
protected Map getParamMapBD() {
return paramMapBD;
}
protected Map getParamMapLong() {
return paramMapLong;
}
protected Map getParamMapCPLX() {
return paramMapCPLX;
}
protected void setParamMapSS(final Map ss) {
paramMapSS = ss;
}
protected void setParamMapLS(final Map ls) {
paramMapLS = ls;
}
protected void setParamMapDT(final Map dt) {
paramMapDT = dt;
}
protected void setParamMapBD(final Map bd) {
paramMapBD = bd;
}
protected void setParamMapLong(final Map lng) {
paramMapLong = lng;
}
protected void setParamMapCPLX(final Map cplx) {
paramMapCPLX = cplx;
}
/**
* Gets a property from the paramMap as a string with no default value.
*
* @param key
* The key into the map.
* @return The property.
*/
public String getStringProperty(final String key) {
return getStringProperty(key, null);
}
/**
* Gets a property from the paramMap as a string, using a default value if
* it doesn't exist in the map.
*
* @param key
* The key into the map.
* @param defaultValue
* Default value returned if the key isn't already in the map.
* @return The property.
*/
public String getStringProperty(final String key, final String defaultValue) {
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "getString", key)); //$NON-NLS-1$ //$NON-NLS-2$
Object prop = getParamMapSS().get(key);
if (prop == null) {
prop = getParamMapLS().get(key);
}
return (prop != null) ? prop.toString() : defaultValue;
}
protected void checkType(final String key, final String type, final boolean setIt) {
Map localTypesMap = getTypesMap();
String curType = (String) localTypesMap.get(key);
if (curType != null) {
if (!curType.equals(type)) {
throw new RepositoryException(Messages.getInstance().getErrorString("RTREPO.ERROR_0001_INVALIDTYPE", curType, type)); //$NON-NLS-1$
}
}
if (setIt) {
localTypesMap.put(key, type);
}
}
/**
* Sets a property into the paramMap. Special implementation note - Null
* values aren't supported in the Map. So, if a null value is passed in,
* this implementation will remove the entry from the map.
*
* @param key
* The key into the map.
* @param value
* The value to set.
*/
public void setStringProperty(final String key, final String value) {
this.updateOk();
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "setString", key)); //$NON-NLS-1$ //$NON-NLS-2$
Map theMapSS = getParamMapSS();
Map theMapLS = getParamMapLS();
if (value != null) {
checkType(key, value.getClass().getName(), true);
if (value.length() > SimpleRuntimeElement.MAXSSLENGH) {
theMapSS.remove(key); // Make sure it's not in the short map
// first.
theMapLS.put(key, new StringBuffer(value));
} else {
theMapLS.remove(key);
theMapSS.put(key, value);
}
} else {
theMapSS.remove(key);
theMapLS.remove(key);
}
}
/**
* Gets a BigDecimal property from the paramMap.
*
* @param key
* Key in the paramMap.
* @return BigDecimal property
*/
public BigDecimal getBigDecimalProperty(final String key) {
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "getBigDecimal", key)); //$NON-NLS-1$ //$NON-NLS-2$
return getBigDecimalProperty(key, null);
}
/**
* Gets a property from the paramMap as a BigDecimal, using a default value
* if it doesn't exist in the map.
*
* @param key
* Key in the paramMap.
* @param defaultValue
* Detault value if the property doesn't exist in the paramMap.
* @return Returns the property from the paramMap.
*/
public BigDecimal getBigDecimalProperty(final String key, final BigDecimal defaultValue) {
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "getBigDecimal", key)); //$NON-NLS-1$ //$NON-NLS-2$
Object prop = getParamMapBD().get(key);
return (prop != null) ? new BigDecimal((String) prop) : defaultValue;
}
/**
* Sets the BigDecimal property in the paramMap. Special implementation note -
* Null values aren't supported in the Map. So, if a null value is passed
* in, this implementation will remove the entry from the map.
*
* @param key
* Key in the paramMap.
* @param value
* The property value to set.
*/
public void setBigDecimalProperty(final String key, final BigDecimal value) {
this.updateOk();
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "setBigDecimal", key)); //$NON-NLS-1$ //$NON-NLS-2$
checkType(key, value.getClass().getName(), true);
Map theMap = getParamMapBD();
if (value != null) {
theMap.put(key, value.toString());
} else {
theMap.remove(key);
}
}
/**
* Gets a property from the paramMap as a Date, with no default value.
*
* @param key
* Key in the paramMap
* @return The property in the map.
*/
public Date getDateProperty(final String key) {
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "getDate", key)); //$NON-NLS-1$ //$NON-NLS-2$
return getDateProperty(key, null);
}
/**
* Gets a property from the paramMap as a Date using a default value if it
* doesn't exist in the map
*
* @param key
* Key in the paramMap
* @param defaultValue
* The default value if the property doesn't exist in the
* paramMap.
* @return The property in the map.
*/
public Date getDateProperty(final String key, final Date defaultValue) {
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "getDate", key)); //$NON-NLS-1$ //$NON-NLS-2$
Object prop = getParamMapDT().get(key);
return (prop != null) ? (Date) prop : defaultValue;
}
/**
* Sets a date property in the paramMap. If null comes in, it removes the
* value from the map. Special implementation note - Null values aren't
* supported in the Map. So, if a null value is passed in, this
* implementation will remove the entry from the map.
*
* @param key
* Key in the paramMap
* @param value
* The property value to set.
*/
public void setDateProperty(final String key, final Date value) {
this.updateOk();
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "setDate", key)); //$NON-NLS-1$ //$NON-NLS-2$
checkType(key, value.getClass().getName(), true);
Map theMap = getParamMapDT();
if (value != null) {
theMap.put(key, value);
} else {
theMap.remove(key);
}
}
/**
* Gets a property from the paramMap as a Long using a default value if it
* doesn't exist in the map
*
* @param key
* Key in the paramMap
* @param defaultValue
* The default value if the property doesn't exist in the
* paramMap.
* @return The property in the map.
*/
public Long getLongProperty(final String key, final Long defaultValue) {
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "getLong", key)); //$NON-NLS-1$ //$NON-NLS-2$
Object prop = getParamMapLong().get(key);
return (prop != null) ? (Long) prop : defaultValue;
}
/**
* Gets a property from the paramMap as a long using a default value if it
* doesn't exist in the map
*
* @param key
* Key in the paramMap
* @param defaultValue
* The default value if the property doesn't exist in the
* paramMap.
* @return The property in the map.
*/
public long getLongProperty(final String key, final long defaultValue) {
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "getLong", key)); //$NON-NLS-1$ //$NON-NLS-2$
Object prop = getParamMapLong().get(key);
return (prop != null) ? ((Long) prop).longValue() : defaultValue;
}
/**
* Sets a long property in the paramMap. If null comes in, it removes the
* value from the map. Special implementation note - Null values aren't
* supported in the Map. So, if a null value is passed in, this
* implementation will remove the entry from the map.
*
* @param key
* Key in the paramMap
* @param value
* The property value to set.
*/
public void setLongProperty(final String key, final Long value) {
this.updateOk();
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "setLong", key)); //$NON-NLS-1$ //$NON-NLS-2$
checkType(key, value.getClass().getName(), true);
Map theMap = getParamMapLong();
if (value != null) {
theMap.put(key, value);
} else {
theMap.remove(key);
}
}
/**
* Sets a long property in the paramMap.
*
* @param key
* Key in the paramMap
* @param value
* The property value to set.
*/
public void setLongProperty(final String key, final long value) {
this.updateOk();
setLongProperty(key, new Long(value));
}
/**
* Gets a list property from the paramMap.
*
* @param key
* Key in the map
* @return The list property in the paramMap.
*/
public List getListProperty(final String key) {
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "getList", key)); //$NON-NLS-1$ //$NON-NLS-2$
Object prop = getParamMapCPLX().get(key);
return (List) prop;
}
/**
* Gets a map property from the paramMap.
*
* @param key
* The key in the map
* @return The map value in the paramMap.
*/
public Map getMapProperty(final String key) {
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "getMap", key)); //$NON-NLS-1$ //$NON-NLS-2$
Object prop = getParamMapCPLX().get(key);
return (Map) prop;
}
/**
* Sets a list property in the paramMap. Special implementation note - Null
* values aren't supported in the Map. So, if a null value is passed in,
* this implementation will remove the entry from the map.
*
* @param key
* The key in the map.
* @param value
* The list property to set.
*/
public void setListProperty(final String key, final List value) {
this.updateOk();
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "setList", key)); //$NON-NLS-1$ //$NON-NLS-2$
checkType(key, value.getClass().getName(), true);
Map theMap = getParamMapCPLX();
if (value != null) {
theMap.put(key, value);
} else {
theMap.remove(key);
}
}
/**
* Sets a map property in the paramMap. Special implementation note - Null
* values aren't supported in the Map. So, if a null value is passed in,
* this implementation will remove the entry from the map.
*
* @param key
* The key in the map.
* @param value
* The map property to set.
*/
public void setMapProperty(final String key, final Map value) {
this.updateOk();
trace(Messages.getInstance().getString("RTREPO.DEBUG_PROPERTY_GETSET", "setMap", key)); //$NON-NLS-1$ //$NON-NLS-2$
checkType(key, value.getClass().getName(), true);
Map theMap = getParamMapCPLX();
if (value != null) {
theMap.put(key, value);
} else {
theMap.remove(key);
}
}
/**
* Returns an XML representation of the RuntimeElement. Mainly for
* Debug/Test Cases to make sure that what goes in is what comes out during
* tests.
*
* @return Returns an XML representation of the RuntimeElement
*/
public String toXML() {
StringBuffer rtn = new StringBuffer();
rtn.append("<runtime-element>\r"); //$NON-NLS-1$
rtn.append(getXMLString(getInstanceId(), "instance-id", " ")); //$NON-NLS-1$ //$NON-NLS-2$
rtn.append(getXMLString(Integer.toString(getRevision()), "revision", " ")); //$NON-NLS-1$ //$NON-NLS-2$
rtn.append(getXMLString(getParentId(), "parent-id", " ")); //$NON-NLS-1$ //$NON-NLS-2$
rtn.append(getXMLString(getParentType(), "parent-type", " ")); //$NON-NLS-1$ //$NON-NLS-2$
rtn.append(getXMLString(getSolutionId(), "solution-id", " ")); //$NON-NLS-1$ //$NON-NLS-2$
rtn.append(getMapXML(this.getParamMapSS(), "small-string-map")); //$NON-NLS-1$
rtn.append(getMapXML(this.getParamMapLS(), "large-string-map")); //$NON-NLS-1$
rtn.append(getMapXML(this.getParamMapDT(), "date-map")); //$NON-NLS-1$
rtn.append(getMapXML(this.getParamMapBD(), "big-decimal-map")); //$NON-NLS-1$
rtn.append(getMapXML(this.getParamMapLong(), "long-map")); //$NON-NLS-1$
rtn.append(getMapXML(this.getParamMapCPLX(), "complex-map")); //$NON-NLS-1$
rtn.append("</runtime-element>\r"); //$NON-NLS-1$
return rtn.toString();
}
private String getXMLString(final String str, final String tag, final String indent) {
return indent + "<" + tag + "><![CDATA[" + str + "]]></" + tag + ">\r"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
private String getMapXML(final Map theMap, final String tag) {
StringBuffer sb = new StringBuffer();
sb.append(" <").append(tag).append(">\r"); //$NON-NLS-1$ //$NON-NLS-2$
sb.append(XmlHelper.mapToXML(theMap, " ")); //$NON-NLS-1$
sb.append(" </").append(tag).append(">\r"); //$NON-NLS-1$ //$NON-NLS-2$
return sb.toString();
}
/* ILogger Needs */
@Override
public Log getLogger() {
return SimpleRuntimeElement.logger;
}
public void setAllowableAttributeNames(final Collection allowedReadNames) {
SimpleRuntimeElement.allowableReadAttributeNames.set(allowedReadNames);
}
/**
* @return Returns the typesMap.
*/
protected Map getTypesMap() {
return typesMap;
}
/**
* @param typesMap
* The typesMap to set.
*/
protected void setTypesMap(final Map typesMap) {
this.typesMap = typesMap;
}
public Set getParameterNames() {
return getTypesMap().keySet();
}
public String getParameterType(final String parameterName) {
return (String) getTypesMap().get(parameterName);
}
public void setLoaded(final boolean value) {
this.loaded = value;
}
public boolean getLoaded() {
return this.loaded;
}
private void updateOk() {
if (!loaded) {
return;
}
if (readOnly) {
throw new IllegalStateException(Messages.getInstance().getErrorString("RTELEMENT.ERROR_0001_INVALIDUPDATE")); //$NON-NLS-1$
}
}
public boolean getReadOnly() {
return readOnly;
}
public void setReadOnly(final boolean value) {
this.readOnly = value;
}
public void forceSave() {
}
}