/**
*
*/
package alma.ACS.impl;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.NO_RESOURCES;
import alma.ACS.Alarmpattern;
import alma.ACS.CBDescIn;
import alma.ACS.CBDescOut;
import alma.ACS.CBpattern;
import alma.ACS.Callback;
import alma.ACS.Condition;
import alma.ACS.Monitor;
import alma.ACS.Monitorpattern;
import alma.ACS.MonitorpatternHelper;
import alma.ACS.MonitorpatternPOATie;
import alma.ACS.NoSuchCharacteristic;
import alma.ACS.Subscription;
import alma.ACS.TimeSeqHolder;
import alma.ACS.jbaci.CallbackDispatcher;
import alma.ACS.jbaci.CompletionUtil;
import alma.ACS.jbaci.DataAccess;
import alma.ACS.jbaci.PropertyInitializationFailed;
import alma.ACSErr.Completion;
import alma.ACSErr.CompletionHolder;
import alma.ACSErrTypeCommon.wrappers.AcsJCouldntPerformActionEx;
import alma.acs.exceptions.AcsJException;
/**
* Base enum class. Contains common methods that does not contain <code>enumClass</code> class in method' signatures.
* <code>enumClass</code> must has standard Java CORBA generated metods of called <code>fromInt(int)</code> and <code>value()</code>.
* @author msekoranja
*/
public class CommonROEnumPropertyImpl extends ROCommonPropertyImpl {
/**
* @param name
* @param parentComponent
* @throws PropertyInitializationFailed
*/
CommonROEnumPropertyImpl(Class enumClass, String name,
CharacteristicComponentImpl parentComponent)
throws PropertyInitializationFailed {
super(enumClass, name, parentComponent);
initialize();
}
/**
* @param name
* @param parentComponent
* @param dataAccess
* @throws PropertyInitializationFailed
*/
CommonROEnumPropertyImpl(Class enumClass, String name,
CharacteristicComponentImpl parentComponent, DataAccess dataAccess)
throws PropertyInitializationFailed {
super(enumClass, name, parentComponent, dataAccess);
initialize();
}
private Method from_int_method;
private Method value_method;
@SuppressWarnings("unchecked")
protected void initialize()
throws PropertyInitializationFailed
{
try {
from_int_method = propertyType.getMethod("from_int", new Class[] { int.class });
value_method = propertyType.getMethod("value", (Class[])null);
} catch (NoSuchMethodException nse) {
throw new PropertyInitializationFailed("given enum class does not implement required method(s)", nse);
}
}
protected int value(Object value)
{
try {
return ((Integer)value_method.invoke(value, (Object[])null)).intValue();
} catch (Throwable th) {
throw new RuntimeException("failed to get int value from enum instance", th);
}
}
protected Object from_int(int value)
{
try {
// needed since it cen be called from super-constructor
if (from_int_method == null)
initialize();
return from_int_method.invoke(null, new Object[] { value });
} catch (Throwable th) {
throw new RuntimeException("failed to get enum instance from int value", th);
}
}
/* (non-Javadoc)
*/
public Condition[] condition() {
try
{
int[] temp = characteristicModelImpl.getIntegerSeq("condition");
Condition[] ret = new Condition[temp.length];
for (int i=0; i<temp.length; i++)
ret[i] = Condition.from_int(temp[i]);
return ret;
} catch (NoSuchCharacteristic e) {
throw new NO_RESOURCES();
}
}
/* (non-Javadoc)
*/
public String[] statesDescription() {
try {
return characteristicModelImpl.getStringSeq("statesDescription");
} catch (NoSuchCharacteristic e) {
throw new NO_RESOURCES();
}
}
/* (non-Javadoc)
*/
public Subscription new_subscription_AlarmEnum(Alarmpattern cb,
CBDescIn desc) {
// TODO NO_IMPLEMENT
throw new NO_IMPLEMENT();
}
/* (non-Javadoc)
*/
public Monitorpattern create_monitor(CBpattern cb, CBDescIn desc) {
return (Monitorpattern) create_postponed_monitor(0, cb, desc);
}
/* (non-Javadoc)
*/
public Monitor create_postponed_monitor(long start_time, CBpattern cb, CBDescIn desc) {
// create monitor and its servant
MonitorpatternImpl monitorImpl = new MonitorpatternImpl(this, cb, desc, start_time);
MonitorpatternPOATie monitorTie = new MonitorpatternPOATie(monitorImpl);
// register and activate
return MonitorpatternHelper.narrow(this.registerMonitor(monitorImpl, monitorTie));
}
/* (non-Javadoc)
*/
public void get_async(CBpattern cb, CBDescIn desc) {
getAsync(cb, desc);
}
/* (non-Javadoc)
*/
@Override
public Object readPropertyTypeCharacteristic(String name)
throws NoSuchCharacteristic {
return from_int(characteristicModelImpl.getInteger(name));
}
/* (non-Javadoc)
* @see alma.ACS.jbaci.CallbackDispatcher#dispatchCallback(int, java.lang.Object, alma.ACS.Callback, alma.ACSErr.Completion, alma.ACS.CBDescOut)
*/
public boolean dispatchCallback(int type, Object value, Callback callback,
Completion completion, CBDescOut desc) {
// NOTE: CBpattern is being used for enums
try
{
if (type == CallbackDispatcher.DONE_TYPE)
((CBpattern)callback).done(value(value), completion, desc);
else if (type == CallbackDispatcher.WORKING_TYPE)
((CBpattern)callback).working(value(value), completion, desc);
else
return false;
return true;
}
catch (Throwable th)
{
return false;
}
}
/* (non-Javadoc)
*/
private Object getEnumArrayFromCharacteristicModel(String name) {
try
{
int[] temp = characteristicModelImpl.getIntegerSeq(name);
Object ret = Array.newInstance(propertyType, temp.length);
for (int i=0; i<temp.length; i++)
Array.set(ret, i, from_int(temp[i]));
return ret;
} catch (NoSuchCharacteristic e) {
throw new NO_RESOURCES();
}
}
/* (non-Javadoc)
*/
public Object alarm_on() {
return getEnumArrayFromCharacteristicModel("alarm_on");
}
/* (non-Javadoc)
*/
public Object alarm_off() {
return getEnumArrayFromCharacteristicModel("alarm_off");
}
/* (non-Javadoc)
*/
public Object allStates() {
int statesCount = 0;
for (; statesCount < Integer.MAX_VALUE; statesCount++)
{
try
{
from_int(statesCount);
} catch (RuntimeException noMore) {
break;
}
}
Object states = Array.newInstance(propertyType, statesCount);
for (int i=0; i<statesCount; i++)
Array.set(states, i, from_int(i));
return states;
}
/* (non-Javadoc)
*/
public Object default_value() {
try {
return from_int(characteristicModelImpl.getInteger("default_value"));
} catch (NoSuchCharacteristic e) {
return from_int(0);
}
}
/* (non-Javadoc)
*/
public Object get_sync(CompletionHolder c) {
try
{
return getSync(c);
}
catch (AcsJException acsex)
{
AcsJCouldntPerformActionEx cpa =
new AcsJCouldntPerformActionEx("Failed to retrieve value", acsex);
c.value = CompletionUtil.generateCompletion(cpa);
// return default value in case of error
return default_value();
}
}
/**
* Create default in-memory RO enum structure.
* @see #createEnumProperty(Class, Class, String, CharacteristicComponentImpl, DataAccess)
*/
public static Object createEnumProperty(
Class operationsIF,
Class propertyType, String name,
CharacteristicComponentImpl parentComponent)
throws PropertyInitializationFailed
{
return createEnumProperty(operationsIF, propertyType, name, parentComponent, null);
}
/**
* Create RO enum structure.
* Example:
* <code>
* BasicStatesOperations basicStatesEnumImpl =
* (BasicStatesOperations)CommonROEnumPropertyImpl.createEnumProperty(
* BasicStatesOperations.class,
* BasicStates.class,
* "state",
* parentComponent,
* dataAccess);
* </code>
* @param operationsIF CORBA <enum type>Operations class.
* @param propertyType CORBA enum class.
* @param name name of the property.
* @param parentComponent property component.
* @param dataAccess data access to be used.
* @return CORBA <enum type>Operations instance.
* @throws PropertyInitializationFailed
*/
public static Object createEnumProperty(
Class operationsIF,
Class propertyType, String name,
CharacteristicComponentImpl parentComponent,
DataAccess dataAccess)
throws PropertyInitializationFailed
{
CommonROEnumPropertyImpl propertyImpl;
if (dataAccess == null)
propertyImpl = new CommonROEnumPropertyImpl(propertyType, name, parentComponent);
else
propertyImpl = new CommonROEnumPropertyImpl(propertyType, name, parentComponent, dataAccess);
return Proxy.newProxyInstance(
propertyImpl.getClass().getClassLoader(),
new Class[] { operationsIF, Destroyable.class },
new ROEnumProxy(propertyImpl));
}
/**
* RO enum proxy class.
*/
public static class ROEnumProxy implements InvocationHandler {
private final CommonROEnumPropertyImpl delegate;
ROEnumProxy(CommonROEnumPropertyImpl delegate) {
this.delegate = delegate;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
final String methodName = method.getName();
if (methodName.equals("get_history"))
{
int n_last_values = ((Integer)args[0]).intValue();
Object seqHolder = args[1];
TimeSeqHolder ts = (TimeSeqHolder)args[2];
Object historyArray = delegate.getHistory(n_last_values, ts);
Field valueField = seqHolder.getClass().getField("value");
valueField.set(seqHolder, historyArray);
return Array.getLength(historyArray);
}
else
{
// delegate
try {
// TODO cache
final Method localMethod = delegate.getClass().getMethod(method.getName(), method.getParameterTypes());
return localMethod.invoke(delegate, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Throwable e) {
throw e;
}
}
}
}
}