ParameterContainer.java
/*
* Created on 2007/01/23
* Copyright (C) 2007 Koga Laboratory. All rights reserved.
*
*/
package org.mklab.tool.control.system.parameter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.tool.control.system.SystemOperator;
/**
* パラメータの値とアノテーションをまとめて管理するクラスです。
*
* @author Koga Laboratory
* @version $Revision: 1.12 $, 2007/01/23
* @param <RS> type of real scalar
* @param <RM> type of real matrix
* @param <CS> type of complex scalar
* @param <CM> type of complex matrix
*/
public class ParameterContainer<RS extends RealNumericalScalar<RS,RM,CS,CM>, RM extends RealNumericalMatrix<RS,RM,CS,CM>, CS extends ComplexNumericalScalar<RS,RM,CS,CM>, CM extends ComplexNumericalMatrix<RS,RM,CS,CM>> implements Comparable<ParameterContainer<RS,RM,CS,CM>> {
/** パラメータをもつシステム */
private SystemOperator<RS,RM,CS,CM> system;
/** パラメータの値を保持するフィールド */
private Field value;
/** パラメータのアノテーション */
private Parameter anotation;
/** 名前 */
private String name;
/** パラメータの定義式 */
private String expression;
/**
* 新しく生成された<code>ParameterContainer</code>オブジェクトを初期化します。
*
* @param system パラメータをもつシステム
* @param value パラメータの値を保持するフィールド
* @param anotation パラメータのアノテーション
* @param name 名前
*/
public ParameterContainer(SystemOperator<RS,RM,CS,CM> system, final Field value, final Parameter anotation, final String name) {
this.system = system;
this.value = value;
this.anotation = anotation;
this.name = name;
}
/**
* パラメータのアノテーションを返します。
*
* @return パラメータのアノテーション
*/
public Parameter getAnotation() {
return this.anotation;
}
/**
* パラメータの値を返します。
*
* @return パラメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public Object getValue() throws ParameterAccessException {
try {
this.value.setAccessible(true);
final Class<?> type = this.value.getType();
if (type.isArray() && this.name.contains("[")) { //$NON-NLS-1$
return Array.get(this.value.get(this.system), getIndexOfArray(this.name));
}
return this.value.get(this.system);
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータに値を設定します。
*
* @param value 設定する値
*
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public void setValue(Object value) throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray() && value.getClass().isArray() == false) {
Array.set(this.value.get(this.system), getIndexOfArray(this.name), value);
} else {
this.value.set(this.system, value);
}
updateWithParameter();
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの定義式を設定します。
*
* @param expression パラメータの定義式
*/
public void setExpression(final String expression) {
this.expression = expression;
}
/**
* パラメータの値を返します。
*
* @return パラメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public boolean getBoolean() throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
return Array.getBoolean(this.value.get(this.system), getIndexOfArray(this.name));
}
return this.value.getBoolean(this.system);
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を設定します。
*
* @param value パラメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public void setBoolean(final boolean value) throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
Array.setBoolean(this.value.get(this.system), getIndexOfArray(this.name), value);
} else {
this.value.setBoolean(this.system, value);
}
updateWithParameter();
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を返します。
*
* @return パラメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public byte getByte() throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
return Array.getByte(this.value.get(this.system), getIndexOfArray(this.name));
}
return this.value.getByte(this.system);
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を設定します。
*
* @param value パレメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public void setByte(final byte value) throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
Array.setByte(this.value.get(this.system), getIndexOfArray(this.name), value);
} else {
this.value.setByte(this.system, value);
}
updateWithParameter();
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を返します。
*
* @return パラメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public char getChar() throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
return Array.getChar(this.value.get(this.system), getIndexOfArray(this.name));
}
return this.value.getChar(this.system);
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を設定します。
*
* @param value パレメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public void setChar(final char value) throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
Array.setChar(this.value.get(this.system), getIndexOfArray(this.name), value);
} else {
this.value.setChar(this.system, value);
}
updateWithParameter();
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を返します。
*
* @return パラメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public double getDouble() throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
return Array.getDouble(this.value.get(this.system), getIndexOfArray(this.name));
}
return this.value.getDouble(this.system);
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を設定します。
*
* @param value パレメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public void setDouble(final double value) throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
Array.setDouble(this.value.get(this.system), getIndexOfArray(this.name), value);
} else {
this.value.setDouble(this.system, value);
}
updateWithParameter();
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を返します。
*
* @return パラメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public float getFloat() throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
return Array.getFloat(this.value.get(this.system), getIndexOfArray(this.name));
}
return this.value.getFloat(this.system);
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を設定します。
*
* @param value パレメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public void setFloat(final float value) throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
Array.setFloat(this.value.get(this.system), getIndexOfArray(this.name), value);
} else {
this.value.setFloat(this.system, value);
}
updateWithParameter();
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を返します。
*
* @return パラメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public int getInt() throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
return Array.getInt(this.value.get(this.system), getIndexOfArray(this.name));
}
return this.value.getInt(this.system);
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を設定します。
*
* @param value パレメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public void setInt(final int value) throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
Array.setInt(this.value.get(this.system), getIndexOfArray(this.name), value);
} else {
this.value.setInt(this.system, value);
}
updateWithParameter();
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を返します。
*
* @return パラメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public long getLong() throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
return Array.getLong(this.value.get(this.system), getIndexOfArray(this.name));
}
return this.value.getLong(this.system);
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を設定します。
*
* @param value パレメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public void setLong(final long value) throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
Array.setLong(this.value.get(this.system), getIndexOfArray(this.name), value);
} else {
this.value.setLong(this.system, value);
}
updateWithParameter();
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を返します。
*
* @return パラメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public short getShort() throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
return Array.getShort(this.value.get(this.system), getIndexOfArray(this.name));
}
return this.value.getShort(this.system);
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* パラメータの値を設定します。
*
* @param value パレメータの値
* @throws ParameterAccessException パラメータにアクセスする権利が無い場合
*/
public void setShort(final short value) throws ParameterAccessException {
try {
this.value.setAccessible(true);
if (this.value.getType().isArray()) {
Array.setShort(this.value.get(this.system), getIndexOfArray(this.name), value);
} else {
this.value.setShort(this.system, value);
}
updateWithParameter();
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
}
}
/**
* <code>opponent</code>と比較した結果を返します。
*
* <p> <code>opponent</code>より順序が前のとき正、 <code>opponent</code>より順序が後のとき負、 等しいとき0を返します。
*
* @param opponent 比較対象
* @return <code>opponent</code>と比較した結果
*/
public int compareTo(final ParameterContainer<RS,RM,CS,CM> opponent) {
final String thisName = getName();
final String opponentName = opponent.getName();
int ans = thisName.compareToIgnoreCase(opponentName);
if (ans == 0) {
ans = thisName.compareTo(opponentName);
}
return ans;
}
/**
* パラメータの名前を返します。
*
* @return パラメータの名前
*/
public String getName() {
return this.name;
}
/**
* パラメータの定義式を返します。
*
* @return パラメータの定義式
*/
public String getExpression() {
return this.expression;
}
/**
* パラメータの型を識別するための Class オブジェクトを返します。
*
* @return パラメータの型を識別するための Class オブジェクトを返します。
*/
public Class<?> getType() {
return this.value.getType();
}
/**
* パラメータを宣言するクラスまたはインタフェースを表す Class オブジェクトを返します。
*
* @return パラメータを宣言するクラスまたはインタフェースを表す Class オブジェクト
*/
public Class<?> getParameterClass() {
return this.value.getDeclaringClass();
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if (o.getClass() != getClass()) {
return false;
}
final ParameterContainer<RS,RM,CS,CM> castedObj = (ParameterContainer<RS,RM,CS,CM>)o;
return ((this.system == null ? castedObj.system == null : this.system.equals(castedObj.system)) && (this.value == null ? castedObj.value == null : this.value.equals(castedObj.value))
&& (this.anotation == null ? castedObj.anotation == null : this.anotation.equals(castedObj.anotation)) && (this.name == null ? castedObj.name == null : this.name.equals(castedObj.name)) && (this.expression == null
? castedObj.expression == null : this.expression.equals(castedObj.expression)));
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int hashCode = 1;
// hashCode = 31 * hashCode + (this.system == null ? 0 :
// this.system.hashCode());// これを入れるとループ
hashCode = 31 * hashCode + (this.value == null ? 0 : this.value.hashCode());
hashCode = 31 * hashCode + (this.anotation == null ? 0 : this.anotation.hashCode());
hashCode = 31 * hashCode + (this.name == null ? 0 : this.name.hashCode());
hashCode = 31 * hashCode + (this.expression == null ? 0 : this.expression.hashCode());
return hashCode;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
Object object = ""; //$NON-NLS-1$
try {
this.value.setAccessible(true);
object = this.value.get(this.system);
} catch (@SuppressWarnings("unused") IllegalArgumentException e) {
// nothing
} catch (@SuppressWarnings("unused") IllegalAccessException e) {
// nothing
}
String unitString = ""; //$NON-NLS-1$
if (getUnit()[0] != SIunit.undefined) {
unitString = " [" + SIunit.toString(getUnit()) + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
String descriptionString = ""; //$NON-NLS-1$
if (getDescription().length() != 0) {
descriptionString = " (" + getDescription() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
}
return getName() + " = " + object + unitString + descriptionString; //$NON-NLS-1$
}
/**
* 説明を返します。
*
* @return 説明
*/
public String getDescription() {
if (this.anotation.description().equals("") == false) { //$NON-NLS-1$
return this.anotation.description();
}
if (this.anotation.quantity() != QuantityType.UNDEFINED) {
return this.anotation.quantity().getName();
}
return ""; //$NON-NLS-1$
}
/**
* 単位を返します。
*
* @return 単位
*/
public SIunit[] getUnit() {
if (this.anotation.unit()[0] != SIunit.undefined) {
return this.anotation.unit();
}
if (this.anotation.quantity() != QuantityType.UNDEFINED) {
return this.anotation.quantity().getUnitAsArray();
}
return new SIunit[] {SIunit.undefined};
}
/**
* パラメータ変更に伴う更新を行います。
*
* @throws ParameterAccessException パラメータ変更に伴う更新ができない場合
*/
private void updateWithParameter() throws ParameterAccessException {
if (this.anotation.update() == false) {
return;
}
if ((this.system instanceof ParameterUpdator) == false) {
return;
}
final boolean success = ((ParameterUpdator)this.system).updateWith(getName());
if (success) {
return;
}
updateWithSuperParameter(this.system.getClass());
}
/**
* パラメータ変更に伴う更新をスーパークラスに対して行います。
*
* @param klass 対象となるクラス
* @throws ParameterAccessException パラメータ変更に伴う更新ができない場合
*/
private void updateWithSuperParameter(final Class<? extends SystemOperator> klass) throws ParameterAccessException {
if (SystemOperator.class.isAssignableFrom(klass) == false || SystemOperator.class == klass) {
return;
}
final Class<? extends SystemOperator> superKlass = klass.getSuperclass().asSubclass(SystemOperator.class);
if (ParameterUpdator.class.isAssignableFrom(superKlass) == false) {
return;
}
try {
final Method method = superKlass.getMethod("updateWith", String.class); //$NON-NLS-1$
final Boolean success = (Boolean)method.invoke(this.system, getName());
if (success.booleanValue()) {
return;
}
updateWithSuperParameter(superKlass);
} catch (SecurityException e) {
throw new ParameterAccessException(e);
} catch (NoSuchMethodException e) {
throw new ParameterAccessException(e);
} catch (IllegalArgumentException e) {
throw new ParameterAccessException(e);
} catch (IllegalAccessException e) {
throw new ParameterAccessException(e);
} catch (InvocationTargetException e) {
throw new ParameterAccessException(e.getTargetException());
}
}
/**
* 配列パラメータの指数を返します。
*
* @param elementName 配列パラメータの名前
* @return 配列パラメータの指数
*/
public static int getIndexOfArray(final String elementName) {
final int start = elementName.indexOf("["); //$NON-NLS-1$
final int end1 = elementName.indexOf("/"); //$NON-NLS-1$
final int end2 = elementName.indexOf("]"); //$NON-NLS-1$
if (end1 < 0) {
return Integer.parseInt(elementName.substring(start + 1, end2)) - 1;
}
final int index = Integer.parseInt(elementName.substring(start + 1, end1)) - 1;
return index;
}
/**
* 配列パラメータの成分の個数を返します。
*
* @param elementName 配列パラメータの名前
* @return 配列パラメータの成分の個数
*/
public static int getArrayLength(final String elementName) {
final int start = elementName.indexOf("["); //$NON-NLS-1$
final int end1 = elementName.indexOf("/"); //$NON-NLS-1$
final int end2 = elementName.indexOf("]"); //$NON-NLS-1$
if (start < 0) {
throw new IllegalArgumentException(Messages.getString("ParameterContainer.18")); //$NON-NLS-1$
}
if (end1 < 0) {
return Integer.parseInt(elementName.substring(start + 1, end2));
}
return Integer.parseInt(elementName.substring(end1 + 1, end2));
}
/**
* パラメータの説明が国際化されているか判定します。
*
* @return パラメータの説明が国際化されていればtrue、そうでなければfalse
*/
public boolean isInternationalized() {
return this.anotation.internationalization();
}
/**
* 国際化されたパラメータの説明を返します。
*
* @param key キー
* @return 国際化されたパラメータの説明
* @throws ParameterException パラメータの説明が国際化されていない場合
*/
public String getInternationalizedString(final String key) throws ParameterException {
if (this.system instanceof StringExternalizable) {
return ((StringExternalizable)this.system).getString(key);
}
throw new ParameterException(Messages.getString("ParameterContainer.19")); //$NON-NLS-1$
}
}