/*
* Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.dal;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.csstudio.dal.simple.MetaData;
import org.csstudio.dal.simple.Severity;
import com.cosylab.util.BitCondition;
/**
* This is info class, which provides some meta information about a characteristic.
* This class also provides access to set of characteristics, which
* DAL API forces to be supported on all DAL plugs.
*
* <p>Info clasu is unmodifiable, data can be provided only trough constructor.
*
* @author ikriznar
*
*/
public class CharacteristicInfo {
/*
* Static declaration of default DAL supported characteristics.
*/
/**
* Name of characteristic declaring position of this property
* within group of properties. This could be physical layout position of
* device in experimental installation or just indication of logical order
* in list of similar properties. By definition position must be of
* <code>double</code> type.<p>E.g. position my be used in profile
* chart to position this value point on horizontal axis.</p>
*/
public static final CharacteristicInfo C_POSITION = new CharacteristicInfo("position",Double.class, new Class[]{SimpleProperty.class},"Position of this property within group of properties, this could be physical layout position of device in experimental installation or just indication of logical order.");
/**
* Name of characteristic declaring long description string for
* this property.
*/
public static final CharacteristicInfo C_DESCRIPTION = new CharacteristicInfo("description",String.class, new Class[]{SimpleProperty.class},"Description of the property.");
/**
* Name of characteristic declaring short descriptive name of this
* property. May be shortend version of the unique name. This name is
* intended to be used in GUI widgets as title. Display name should be
* short, familiar to end users, but still unique inside context is
* appears.
*/
public static final CharacteristicInfo C_DISPLAY_NAME = new CharacteristicInfo("displayName",String.class, new Class[]{SimpleProperty.class},"A short descriptive name of this property, intended to be used in GUI widgets as title.");
/**
* Short descriptive name of the "type" of the property. The
* properties with same propertyType can be grouped together in GUI
* widgets: same types go to same row in table, go to same series in
* profile chart, etc. Same property types must be of same access type or
* property class.<p>Example: Device of type "PowerSupply" has
* property "current". Property type for such property would be "current"
* or even "PowerSupply/current", whatever distinguish better this
* property inside context or set of properties it is used.</p>
*/
public static final CharacteristicInfo C_PROPERTY_TYPE = new CharacteristicInfo("propertyType",String.class, new Class[]{SimpleProperty.class},"Descriptive name for type of the property. Example: Device of type 'PowerSupply' has property 'current', property type would be 'current' or even 'PowerSupply/current'.");
/**
* Name of the resolution characteristic which gives in number of bits used for ADC conversion of analog value when sampled.
*/
public static final CharacteristicInfo C_RESOLUTION = new CharacteristicInfo("resolution",Integer.class, new Class[]{NumericProperty.class},"Number of bits used for ADC conversion of analog value when sampled.");
/**
* Name of the precision characteristic. Such characteristic represents the number of decimal places.
*/
public static final CharacteristicInfo C_PRECISION = new CharacteristicInfo("precision",Integer.class, new Class[]{NumericProperty.class},"Number of decimal places.");
/**
* Name of the minimum characteristic. Such characteristic represents the
* value that should be taken as a minimum allowed value of the dynamic
* value.
*/
public static final CharacteristicInfo C_MINIMUM = new CharacteristicInfo("minimum",Number.class, new Class[]{NumericProperty.class},"A minimum allowed value of the property.");
/**
* The name of the maximum characteristic. Such characteristic represents
* the value that should be taken as a maximum allowed of the dynamic
* value.
* If dynamic value type is array or sequence, then this value is scalar value and
* represents limit for all positions in array or seuence.
*/
public static final CharacteristicInfo C_MAXIMUM = new CharacteristicInfo("maximum",Number.class, new Class[]{NumericProperty.class},"A maximum allowed value of the property.");
/**
* Name of the graphMin characteristic. Such characteristic represents the
* value that should be taken as a display minimum if the dynamic value of
* the property is being charted.
* If dynamic value type is array or sequence, then this value is scalar value and
* represents limit for all positions in array or sequence.
*/
public static final CharacteristicInfo C_GRAPH_MIN = new CharacteristicInfo("graphMin",Number.class, new Class[]{NumericProperty.class},"A minimum display value of the property.");
/**
* The name of the graphMax characteristic. Such characteristic represents
* the value that should be taken as a display maximum if the dynamic
* value of the property is being charted.
* If dynamic value type is array or sequence, then this value is scalar value and
* represents limit for all positions in array or sequence.
*/
public static final CharacteristicInfo C_GRAPH_MAX = new CharacteristicInfo("graphMax",Number.class, new Class[]{NumericProperty.class},"A maximum display value of the property.");
/**
* The name of the format characteristic. Such characteristic represents
* the C printf-style format specifier that is used to render the dynamic
* value of the given property into a string.
*/
public static final CharacteristicInfo C_FORMAT = new CharacteristicInfo("format",String.class, new Class[]{NumericProperty.class},"A C printf-style format specifier that is used to convert a property value to a string.");
/**
* The name of the units characteristic. Such characteristic represents the
* units of the dynamic value.
*/
public static final CharacteristicInfo C_UNITS = new CharacteristicInfo("units",String.class, new Class[]{NumericProperty.class},"A physical units fo property value.");
/**
* The name of the scaleType characteristic. Such characteristic represents
* the scale type used to plot the property. It can have values "linear"
* or "logarithmic"; case is significant.
*/
public static final CharacteristicInfo C_SCALE_TYPE = new CharacteristicInfo("scaleType",String.class, new Class[]{NumericProperty.class},"Can specify 'linear' or 'logarithmic' scale.");
/**
* Optional characteristic.
*
* The name of the warning upper limit characteristic. Such characteristic
* represents the value that should be taken as a maximum value which
* is displayed without a warning. Any value higher that this maximum, should
* have a warning label attached to it.
* If dynamic value type is array or sequence, then this value is scalar value and
* represents limit for all positions in array or sequence.
*/
public static final CharacteristicInfo C_WARNING_MAX = new CharacteristicInfo("warningMax",Number.class, new Class[]{NumericProperty.class},"A maximum warning value of the property.");
/**
* Optional characteristic.
*
* The name of the warning lower limit characteristic. Such characteristic
* represents the value that should be taken as a minimum value which
* is displayed without a warning. Any value lower that this minimum, should
* have a warning label attached to it.
* If dynamic value type is array or sequence, then this value is scalar value and
* represents limit for all positions in array or sequence.
*/
public static final CharacteristicInfo C_WARNING_MIN = new CharacteristicInfo("warningMin",Number.class, new Class[]{NumericProperty.class},"A minimum warning value of the property.");
/**
* Optional characteristic.
*
* The name of the alarm upper limit characteristic. Such characteristic
* represents the value that should be taken as a maximum value which
* is displayed without an alarm. Any value higher that this maximum, should
* have a major alarm label attached to it.
* If dynamic value type is array or sequence, then this value is scalar value and
* represents limit for all positions in array or sequence.
*/
public static final CharacteristicInfo C_ALARM_MAX = new CharacteristicInfo("alarmMax",Number.class, new Class[]{NumericProperty.class},"A maximum alarm value of the property.");
/**
* Optional characteristic.
*
* The name of the alarm lower limit characteristic. Such characteristic
* represents the value that should be taken as a minimum value which
* is displayed without an alarm. Any value lower that this minimum, should
* have a major alarm label attached to it.
* If dynamic value type is array or sequence, then this value is scalar value and
* represents limit for all positions in array or sequence.
*/
public static final CharacteristicInfo C_ALARM_MIN = new CharacteristicInfo("alarmMin",Number.class, new Class[]{NumericProperty.class},"A minimum alarm value of the property.");
/**
* The name of the characteristic denoting sequence length. The returned value type is <code>Integer</code>.
*/
public static final CharacteristicInfo C_SEQUENCE_LENGTH = new CharacteristicInfo("sequenceLength", Integer.class, new Class[]{DoubleSeqSimpleProperty.class,LongSeqSimpleProperty.class,ObjectSeqSimpleProperty.class,StringSeqSimpleProperty.class},"The length of value array if property is a sequence kind.");
/**
* Characteristic name for array of enumerated objects in same order as enum indexes returned by the property. Characteristic type
* is <code>Object[]</code>.
*/
public final static CharacteristicInfo C_ENUM_VALUES = new CharacteristicInfo("enumValues", Object[].class, new Class[]{EnumSimpleProperty.class}, "An array of all enumerated values for property in same order as enum indexes returned by the property.");
/**
* Characteristic name for array of descriptions for enumerated objects in same order as enum indexes returned by the property.
* Characteristic type is <code>String[]</code>.
*/
public final static CharacteristicInfo C_ENUM_DESCRIPTIONS = new CharacteristicInfo("enumDescriptions", String[].class, new Class[]{EnumSimpleProperty.class}, "An array of short descriptions for all enumerated values for property in same order as enum indexes returned by the property.");
/**
* Name of the characteristic describing bits. Returned value type
* is <code>String[]</code>.
*/
public static final CharacteristicInfo C_BIT_DESCRIPTIONS = new CharacteristicInfo("bitDescriptions", String[].class, new Class[]{PatternSimpleProperty.class},"An array with descriptions for masked bits.");
/**
* Name of the characteristic defining active bit significance.
* Returned value type is <code>BitCondition[]</code>.
*/
public static final CharacteristicInfo C_CONDITION_WHEN_SET = new CharacteristicInfo("conditionWhenSet", BitCondition[].class, new Class[]{PatternSimpleProperty.class},"An array defining masked bit significance when active (bit value 1).");
/**
* Name of the characteristic defining inactive bit significance.
* Returned value type is <code>BitCondition[]</code>.
*/
public static final CharacteristicInfo C_CONDITION_WHEN_CLEARED = new CharacteristicInfo("conditionWhenCleared", BitCondition[].class, new Class[]{PatternSimpleProperty.class},"An array defining masked bit significance when inactive (bit value 0).");
/**
* Name of the characteristic defining bits relevance. Returned
* value type is <code>BitSet</code>.
*/
public static final CharacteristicInfo C_BIT_MASK = new CharacteristicInfo("bitMask", BitSet.class, new Class[]{PatternSimpleProperty.class},"A mask which tells which bits in value are relevant and has defined conditions and descriptions.");
/**
* Meta characteristic for last received EPICS style timestamp.
* Returned value type is <code>Timestamp</code>.
*/
public static final CharacteristicInfo C_TIMESTAMP = new CharacteristicInfo("timestampInfo", Timestamp.class, new Class[] { DynamicValueProperty.class }, "Meta characteristic for last received EPICS style timestamp.", null, true);
/**
* Meta characteristic for last received severity.
* Returned value type is <code>Severity</code>.
*/
public static final CharacteristicInfo C_SEVERITY = new CharacteristicInfo("severity", Severity.class, new Class[] { DynamicValueProperty.class }, "Meta characteristic for last received severity.", null, true);
/**
* Meta characteristic for last received EPICS style status.
* Returned value type is <code>String</code>.
*/
public static final CharacteristicInfo C_STATUS = new CharacteristicInfo("statusInfo", String.class, new Class[] { DynamicValueProperty.class }, "Meta characteristic for last received EPICS style status.", null, true);
/**
* MetaData characteristic similar to that used by simple DAL.
* Returned value type is <code>MetaData</code>.
*/
public static final CharacteristicInfo C_META_DATA = new CharacteristicInfo("metaData", MetaData.class, new Class[] { DynamicValueProperty.class }, "MetaData characteristic similar to that used by simple DAL.", null, true);
private static CharacteristicInfo[] defaultCharacterictics;
private static Map<String,List<CharacteristicInfo>> plugSpecific= new HashMap<String, List<CharacteristicInfo>>();
/**
* Returns an array with all default characteristics declared in this class.
*
* @param plug if plug name non-null also plug specific characteristic are included in returned array
*
* @return an array with all default characteristics
*/
public synchronized static final CharacteristicInfo[] getDefaultCharacteristics(final String plug) {
if (defaultCharacterictics==null) {
final List<CharacteristicInfo> l= new ArrayList<CharacteristicInfo>(32);
final Field[] f= CharacteristicInfo.class.getDeclaredFields();
for (final Field element : f) {
if (Modifier.isStatic(element.getModifiers()) && element.getType()==CharacteristicInfo.class) {
try {
final CharacteristicInfo ci= (CharacteristicInfo)element.get(null);
if (!ci.isMeta()) {
l.add(ci);
}
} catch (final IllegalArgumentException e) {
e.printStackTrace();
} catch (final IllegalAccessException e) {
e.printStackTrace();
}
}
}
defaultCharacterictics= l.toArray(new CharacteristicInfo[l.size()]);
}
final List<CharacteristicInfo> infos= plugSpecific.get(plug);
if (infos != null) {
final CharacteristicInfo[] ci= new CharacteristicInfo[defaultCharacterictics.length+infos.size()];
infos.toArray(ci);
System.arraycopy(defaultCharacterictics, 0, ci, infos.size(), defaultCharacterictics.length);
return ci;
}
return defaultCharacterictics;
}
private static final CharacteristicInfo[] getDeclaredCharacteristics() {
final List<CharacteristicInfo> l= new ArrayList<CharacteristicInfo>(32);
final Field[] f= CharacteristicInfo.class.getDeclaredFields();
for (final Field element : f) {
if (Modifier.isStatic(element.getModifiers()) && element.getType()==CharacteristicInfo.class) {
try {
final CharacteristicInfo ci= (CharacteristicInfo)element.get(null);
l.add(ci);
} catch (final IllegalArgumentException e) {
e.printStackTrace();
} catch (final IllegalAccessException e) {
e.printStackTrace();
}
}
}
return l.toArray(new CharacteristicInfo[l.size()]);
}
/**
*
* @param property the property type
* @param plug name if non-null also plug specific characteristic are included in returned array
* @return array of characteristics info supported by provided property type and plug
*/
public static final CharacteristicInfo[] getDefaultCharacteristics(final Class<?> property, final String plug) {
final CharacteristicInfo[] inf= getDefaultCharacteristics(plug);
final List<CharacteristicInfo> l= new ArrayList<CharacteristicInfo>(inf.length);
for (final CharacteristicInfo element : inf) {
final Class<? extends SimpleProperty<?>>[] c = element.getProperties();
for (final Class<? extends SimpleProperty<?>> element2 : c) {
if (element2.isAssignableFrom(property)) {
l.add(element);
break;
}
}
}
return l.toArray(new CharacteristicInfo[l.size()]);
}
/**
* Dynamically registers a characteristic info.
* @param info a new characteristic info to register
*/
public static final void registerCharacteristicInfo(final CharacteristicInfo info) {
List<CharacteristicInfo> infos= plugSpecific.get(info.getPlug());
if (infos == null) {
infos= new ArrayList<CharacteristicInfo>(8);
plugSpecific.put(info.getPlug(), infos);
}
infos.add(info);
}
public static void main(final String[] args) {
final CharacteristicInfo[] infos= getDeclaredCharacteristics();
for (final CharacteristicInfo info : infos) {
System.out.println(info);
}
}
private final String name;
private final String description;
private String plug;
private final Class<?> type;
private final Class<? extends SimpleProperty<?>>[] properties;
private boolean meta= false;
private int hash=0;
/**
* Constructor with parameters.
*
* @param name characteristic name as it it used in DAL properties
* @param type Java class of value as returned by DAL property.
* If more types are possible, first common superclass should be used.
* @param description a short description
* @param properties an array of DAL property interfaces, which support characteristic
*/
public CharacteristicInfo(final String name, final Class<?> type,
final Class<? extends SimpleProperty<?>>[] properties, final String description) {
this.description = description;
this.name = name;
this.properties = properties;
this.type = type;
}
/**
* Constructor with parameters.
*
* @param name characteristic name as it it used in DAL properties
* @param type Java class of value as returned by DAL property.
* If more types are possible, first common superclass should be used.
* @param description a short description
* @param properties an array of DAL property interfaces, which support characteristic
* @param plug name of plug if this characteristic is specific to certain plug.
* If null then characteristic applies to any plug.
* @param meta <code>true</code> if this is "meta" characteristic generated by DAL and not directly
* connected to a remote entity.
*/
public CharacteristicInfo(final String name, final Class<?> type,
final Class<? extends SimpleProperty<?>>[] properties, final String description, final String plug, final boolean meta) {
this.description = description;
this.name = name;
this.properties = properties;
this.type = type;
this.plug= plug;
this.meta= meta;
}
/**
* The name of the characteristic.
* @return the name
*/
public String getName() {
return name;
}
/**
* The Java type of returned characteristic value by DAL property.
* Charateristic value should be possible to cast to this type.
* @return the type
*/
public Class<?> getType() {
return type;
}
/**
* The array of properties in which this characteristic is supported.
* Instead of multiple property interfaces a common super interface should be used.
* For example: NumericProperrty instead of DoubleProperty and LongProperty.
* @return the properties
*/
public Class<? extends SimpleProperty<?>>[] getProperties() {
@SuppressWarnings("unchecked")
final Class<? extends SimpleProperty<?>>[] r = new Class[properties.length];
System.arraycopy(properties, 0, r, 0, r.length);
return r;
}
/**
* Short description of the characcteristic.
* @return short description
*/
public String getDescription() {
return description;
}
/**
* Returns plug name, if this characteristic is plug specific. If <code>null</code> then characteristic applies to all plugs.
* @return plug name or <code>null</code>
*/
public String getPlug() {
return plug;
}
@Override
public String toString() {
final StringBuilder sb= new StringBuilder(256);
sb.append(name);
sb.append(":{");
sb.append(type.getSimpleName());
if (properties!=null) {
for (final Class<? extends SimpleProperty<?>> propertie : properties) {
sb.append(',');
sb.append(propertie.getSimpleName());
}
}
sb.append("}");
return sb.toString();
}
@Override
public int hashCode() {
if (hash==0) {
hash= toString().hashCode();
}
return hash;
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof CharacteristicInfo) {
return hashCode()==obj.hashCode();
}
return false;
}
/**
* Returns <code>true</code> if this is "meta" characteristic generated by DAL and not directly
* connected to a remote entity. It might not be supported in all DAL implementations.
* @return <code>true</code> if this is "meta" characteristic, could be optional
*/
public boolean isMeta() {
return meta;
}
}