/*******************************************************************************
* This file is part of Goko.
*
* Goko 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 3 of the License, or
* (at your option) any later version.
*
* Goko 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 Goko. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package org.goko.core.controller.bean;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.goko.core.common.event.EventDispatcher;
import org.goko.core.common.exception.GkException;
import org.goko.core.common.exception.GkTechnicalException;
import org.goko.core.common.measure.quantity.Quantity;
import org.goko.core.controller.event.MachineValueUpdateEvent;
/**
* A store used to store and manage controller values
*
* @author PsyKo
*
*/
public class MachineValueStore extends EventDispatcher{
/** The actual values */
private Map<String, MachineValue<?>> valueStore;
/** The list of supported values */
private List<MachineValueDefinition> lstMachineValueDefinition;
public MachineValueStore() {
super();
this.valueStore = new HashMap<String, MachineValue<?>>();
lstMachineValueDefinition = new ArrayList<MachineValueDefinition>();
}
public <T> void storeValue(MachineValueDefinition definition, MachineValue<T> value) throws GkException{
if(!valueStore.containsKey(value.getIdDescriptor())){
// First registration
initializeValue(definition, value);
}else{
// Update
updateValue(value.getIdDescriptor(), value);
}
}
public <T> void storeValue(String id, String name, String description, T value) throws GkException{
storeValue(new MachineValueDefinition(id, name, description, value.getClass()), new MachineValue<T>(id, value));
}
public <Q extends Quantity<Q>> void storeValue(String id, String name, String description, Q quantity) throws GkException{
storeValue(new MachineValueDefinition(id, name, description, quantity.getClass()), new MachineQuantityValue<Q>(id, quantity));
}
/**
* Returns the desired value as an Integer
* @param id the id of the value
* @return an Integer
* @throws GkException GkException
*/
public MachineValue<Integer> getIntegerValue(String id) throws GkException{
return getValue(id, Integer.class);
}
/**
* Returns the desired value as a Boolean
* @param id the id of the value
* @return a Boolean
* @throws GkException GkException
*/
public MachineValue<Boolean> getBooleanValue(String id) throws GkException{
return getValue(id, Boolean.class);
}
/**
* Returns the desired value as a BigDecimal
* @param id the id of the value
* @return a BigDecimal
* @throws GkException GkException
*/
public MachineValue<BigDecimal> getBigDecimalValue(String id) throws GkException{
return getValue(id, BigDecimal.class);
}
/**
* Returns the stored value with the given type if possible.
* @param id the id of the requested value
* @param clazz the requested type
* @return MachineValue or <code>null</code> if no value is stored for that id
* @throws GkException thrown only if the requested type does not match the stored type
*/
public <T> MachineValue<T> findValue(String id, Class<T> clazz) throws GkException{
MachineValue<?> machineValue = valueStore.get(id);
if(machineValue != null){
if(machineValue.getValue() == null){
return (MachineValue<T>)machineValue;
}else if(machineValue.getValue().getClass() == clazz){
return (MachineValue<T>) valueStore.get(id).clone();
}else{
throw new GkTechnicalException("ControllerValueStore : unable to get value '"+id+"' for the requested type '"+clazz+"'. Registered as '"+machineValue.getValue().getClass()+"'");
}
}
return null;
}
/**
* Returns the stored value with the given type if possible
* @param id the id of the requested value
* @param clazz the requested type
* @return MachineValue
* @throws GkException thrown if the value does not exist, or if the requested type does not match the stored type
*/
public <T> MachineValue<T> getValue(String id, Class<T> clazz) throws GkException{
if(!valueStore.containsKey(id)){
throw new GkTechnicalException("ControllerValueStore : value with id '"+id+"' does not exist.'");
}
MachineValue<T> machineValue = findValue(id, clazz);
return machineValue;
}
/**
* Initialize a value in the storage map
* @param name the name of the * @param value the value itself */
protected <T> void initializeValue(MachineValueDefinition definition,MachineValue<T> value){
lstMachineValueDefinition.add(definition);
valueStore.put(value.getIdDescriptor(), value);
super.notifyListeners(new MachineValueUpdateEvent(value));
}
/**
* Initialize a value in the storage map
* @param id the id of the value
* @param value the value itself
*
* @throws GkTechnicalException
*/
public <T> void updateValue(String id, T value) throws GkException{
MachineValue<?> machineValue = valueStore.get(id);
if(machineValue == null){
throw new GkTechnicalException("ControllerValueStore : '"+id+"' not initialized.");
}else if(machineValue.getValue().getClass() == value.getClass()){
MachineValue<T> typedValue = (MachineValue<T>) valueStore.get(id);
T oldValue = typedValue.getValue();
typedValue.setValue(value);
// Notify only if the value changed
if(!value.equals(oldValue)){
super.notifyListeners(new MachineValueUpdateEvent(typedValue.clone()));
}
}else{
throw new GkTechnicalException("ControllerValueStore : unable to store '"+id+"''. Type mismatch. Got "+value.getClass()+"', expecting '"+machineValue.getClass()+"'");
}
}
public List<MachineValueDefinition> getMachineValueDefinition(){
return lstMachineValueDefinition;
}
public Class<?> getControllerValueType(String name) {
if(valueStore.containsKey(name) && valueStore.get(name) != null){
return valueStore.get(name).getValue().getClass();
}
return Object.class;
}
public MachineValueDefinition getMachineValueDefinition(String id) throws GkException {
MachineValueDefinition definition = findMachineValueDefinition(id);
if(definition == null){
throw new GkTechnicalException("ControllerValueStore : '"+id+"' does not exist.");
}
return definition;
}
public MachineValueDefinition findMachineValueDefinition(String id) throws GkException {
for(MachineValueDefinition definition : lstMachineValueDefinition){
if(StringUtils.equals(definition.getId(), id)){
return definition;
}
}
return null;
}
}