DoubleUserDefinedContinuousSource.java

/*
 * Created on 2007/07/16
 * Copyright (C) 2007 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.tool.control.system.source;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;

import org.mklab.nfc.matrix.DoubleMatrix;
import org.mklab.nfc.ode.SolverStopException;
import org.mklab.tool.control.system.ParameterUtil;
import org.mklab.tool.control.system.UserDefinedSystem;
import org.mklab.tool.control.system.parameter.NoSuchParameterException;
import org.mklab.tool.control.system.parameter.ParameterException;


/**
 * ユーザ定義連続信号発生システムを表わすクラスです。
 * 
 * @author koga
 * @version $Revision: 1.12 $, 2007/07/16
 */
public class DoubleUserDefinedContinuousSource extends DoubleContinuousSource implements UserDefinedSystem, Importer {

  /** システムの出力方程式を定義したクラス */
  private Class<?> systemKlass;

  /** システムの初期化処理を定義したメソッド */
  private Method initializeFunction;

  /** システムの更新処理を定義したメソッド */
  private Method updateFunction;

  /** システムの出力方程式を定義したメソッド */
  private Method outputFunction;

  /** システムのクローズ処理を定義したメソッドです。 */
  private Method closeFunction;

  /** システムのオープン処理を定義したメソッドです。 */
  private Method openFunction;

  /** メソッドの定義してあるオブジェクト。nullの場合は静的メソッドを呼び出します。 */
  private Object obj;

  /** システムがアクティブであるか調べます。 */
  private boolean active;

  /**
   * 新しく生成された<code>UserDefinedContinuousSource</code>オブジェクトを初期化します。
   */
  public DoubleUserDefinedContinuousSource() {
    this(null);
  }

  /**
   * 新しく生成された<code>UserDefinedContinuousSource</code>オブジェクトを初期化します。
   * 
   * @param obj メソッドの定義してあるオブジェクト。nullの場合は静的メソッドを呼び出します。
   */
  public DoubleUserDefinedContinuousSource(Object obj) {
    super(1);
    this.obj = obj;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public DoubleMatrix outputEquation(double t) throws SolverStopException {
    try {
      return (DoubleMatrix)this.outputFunction.invoke(this.obj, Double.valueOf(t));
    } catch (IllegalArgumentException e) {
      throw new SolverStopException(e);
    } catch (IllegalAccessException e) {
      throw new SolverStopException(e);
    } catch (InvocationTargetException e) {
      throw new SolverStopException(e.getTargetException());
    }
  }

  /**
   * @see org.mklab.tool.control.system.UserDefinedSystem#setSystemClass(java.lang.Class)
   */
  public void setSystemClass(final Class<?> klass) {
    this.systemKlass = klass;
  }

  /**
   * @see org.mklab.tool.control.system.UserDefinedSystem#getSystemClass()
   */
  public Class<?> getSystemClass() {
    return this.systemKlass;
  }

  /**
   * システムの出力方程式を定義したメソッドを設定します。
   * 
   * @param method システムの出力方程式を定義したメソッド
   * @throws SecurityException メソッドにアクセスする権利が無い場合
   */
  public void setOutputFunction(Method method) throws SecurityException {
    this.outputFunction = method;
    this.outputFunction.setAccessible(true);
  }

  /**
   * @see org.mklab.tool.control.system.UserDefinedSystem#setInitializeFunction(java.lang.reflect.Method)
   */
  public void setInitializeFunction(final Method method) throws SecurityException {
    this.initializeFunction = method;
    this.initializeFunction.setAccessible(true);
  }

  /**
   * @see org.mklab.tool.control.system.UserDefinedSystem#setUpdateFunction(java.lang.reflect.Method)
   */
  public void setUpdateFunction(final Method method) throws SecurityException {
    this.updateFunction = method;
    this.updateFunction.setAccessible(true);
  }

  /**
   * システムのクローズ処理を記述したメソッドを設定します。
   * 
   * @param closeFunction システムのクローズ処理を記述したメソッド
   */
  public void setCloseFunction(Method closeFunction) {
    this.closeFunction = closeFunction;
    this.closeFunction.setAccessible(true);
  }

  /**
   * システムのオープン処理を記述したメソッドを設定します。
   * 
   * @param openFunction システムのクローズ処理を記述したメソッド
   */
  public void setOpenFunction(Method openFunction) {
    this.openFunction = openFunction;
    this.openFunction.setAccessible(true);
  }

  /**
   * @see org.mklab.tool.control.system.UserDefinedSystem#getParameterValue(java.lang.String)
   */
  public Object getParameterValue(String name) throws NoSuchParameterException {
    return ParameterUtil.getValue(this.systemKlass, name);
  }

  /**
   * @see org.mklab.tool.control.system.UserDefinedSystem#getParameterNames()
   */
  public Set<String> getParameterNames() throws NoSuchParameterException {
    return ParameterUtil.getParameterNames(this.systemKlass);
  }

  /**
   * @see org.mklab.tool.control.system.UserDefinedSystem#setParameterValue(java.lang.String, java.lang.Object)
   */
  public void setParameterValue(String name, Object value) throws NoSuchParameterException {
    ParameterUtil.setValue(this.systemKlass, name, value);
  }

  /**
   * @see org.mklab.tool.control.system.UserDefinedSystem#containParameter(java.lang.String)
   */
  public boolean containParameter(String name) {
    return ParameterUtil.contains(this.systemKlass, name);
  }

  /**
   * @see org.mklab.tool.control.system.UserDefinedSystem#update()
   */
  public void update() throws ParameterException {
    try {
      this.updateFunction.invoke(this.obj);
    } catch (IllegalArgumentException e) {
      throw new ParameterException(e);
    } catch (IllegalAccessException e) {
      throw new ParameterException(e);
    } catch (InvocationTargetException e) {
      throw new ParameterException(e.getTargetException());
    } catch (Exception e) {
      throw new ParameterException(e);
    }
  }

  /**
   * @see org.mklab.tool.control.system.discrete.BaseDiscreteStaticSystem#initialize()
   */
  @Override
  public void initialize() {
    super.initialize();
    try {
      if (this.initializeFunction != null) {
        this.initializeFunction.invoke(this.obj);
      }
    } catch (IllegalArgumentException e) {
      throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      throw new RuntimeException(e.getTargetException());
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * @see org.mklab.tool.control.system.source.Importer#open()
   * @throws IOException 入出力例外がクローズ中に発生した場合
   * @throws RuntimeException その他の例外の場合
   */
  @Override
  public void open() throws IOException {
    this.active = true;
    try {
      if (this.openFunction != null) {
        this.openFunction.invoke(this.obj);
      }
    } catch (IllegalArgumentException e) {
      throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      if (e.getTargetException() instanceof IOException) {
        throw (IOException)e.getTargetException();
      }
      throw new RuntimeException(e.getTargetException());
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * @see org.mklab.tool.control.system.source.Importer#close()
   * @throws IOException 入出力例外がクローズ中に発生した場合
   * @throws RuntimeException その他の例外の場合
   */
  @Override
  public void close() throws IOException {
    this.active = false;
    try {
      if (this.closeFunction != null) {
        this.closeFunction.invoke(this.obj);
      }
    } catch (IllegalArgumentException e) {
      throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      if (e.getTargetException() instanceof IOException) {
        throw (IOException)e.getTargetException();
      }
      throw new RuntimeException(e.getTargetException());
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * @see org.mklab.tool.control.system.source.Importer#importData()
   */
  @Override
  public void importData() {
    // do nothing
  }

  /**
   * @see org.mklab.tool.control.system.source.Importer#isActive()
   */
  @Override
  public boolean isActive() {
    return this.active;
  }

}