oms3.FieldAccess Maven / Gradle / Ivy
package oms3;
import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;
import oms3.Notification.DataflowEvent;
//import oms3.gen.Access;
/** Field Access.
*
* @author od
* @version $Id$
*/
class FieldAccess implements Access {
Notification ens;
Field field;
Object comp;
FieldContent data;
private static final Logger log = Logger.getLogger("oms3.sim");
// Access access;
FieldAccess(Object target, Field field, Notification ens) {
this.field = field;
this.comp = target;
this.ens = ens;
field.setAccessible(true); // just in case
// access = Utils.compiled(comp, field);
}
// called on 'out' access.
@Override
public FieldContent getData() {
if (data == null) {
data = new FieldContent();
}
return data;
}
// called in 'in' access
@Override
public void setData(FieldContent data) {
// allow setting in field once only.
// cannot have multiple sources for one @In !
if (this.data != null) {
throw new ComponentException("Attempt to set @In field twice: " + comp + "." + field.getName());
}
this.data = data;
}
/**
* Checks if this object is in a valid state.
* @return
*/
@Override
public boolean isValid() {
return data != null && field.isAccessible();
}
/**
* a field is receiving a new value (in)
*
* @throws java.lang.Exception
*/
@Override
public void in() throws Exception {
if (data == null) {
// throw new ComponentException("Not connected: " + toString());
if (log.isLoggable(Level.WARNING)) {
log.warning("@In not connected : " + toString() + ", using default value.");
}
return;
}
Object val = data.getValue();
// fire only if there is a listener
if (ens.shouldFire()) {
DataflowEvent e = new DataflowEvent(ens.getController(), this, val);
// DataflowEvent e = new DataflowEvent(ens.getController(), this, access.toObject());
ens.fireIn(e);
// the value might be altered
val = e.getValue();
}
// type conversion
if (val != null && field.getType() != val.getClass() && !field.getType().isAssignableFrom(val.getClass())) {
// // default type conversion fails, we need to convert.
// // this will use the Conversions SPI.
val = Conversions.convert(val, field.getType());
}
// access.pass((Access) val);
setFieldValue(val);
}
/**
* a field is sending a new value (out)
*
* @return the object value in out
* @throws java.lang.Exception
*/
@Override
public void out() throws Exception {
Object val = getFieldValue();
// Object val = access;
if (ens.shouldFire()) {
DataflowEvent e = new DataflowEvent(ens.getController(), this, val);
// DataflowEvent e = new DataflowEvent(ens.getController(), this, access.toObject());
ens.fireOut(e);
// the value might be altered
val = e.getValue();
}
// if data==null this unconsumed @Out, its OK but we do not want to set it.
if (data != null) {
data.setValue(val);
}
}
/** Get the command belonging to this Object
*
* @return the command object
*/
@Override
public Object getComponent() {
return comp;
}
/**
* Get the Field
* @return the field object.
*/
@Override
public Field getField() {
return field;
}
/**
* Get directly the value of the component field.
*
* @return the field value object
* @throws Exception if there is illegal access ot type
*/
@Override
final public Object getFieldValue() throws Exception {
return field.get(comp);
}
/**
* Set directly the value of a component field.
*
* @param o the new value to set
* @throws Exception if there is illegal access ot type
*/
@Override
final public void setFieldValue(Object o) throws Exception {
field.set(comp, o);
}
@Override
public String toString() {
return comp + "%" + field.getName() + " - " + (data == null ? null : data.getValue());
}
// public static void main(String[] args) {
// System.out.println(Number.class.isAssignableFrom(Double.class));
// System.out.println(int.class.isAssignableFrom(double.class));
// }
}