[openrtm-commit:02196] r900 - in trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC: . jfsm jfsm/machine

openrtm @ openrtm.org openrtm @ openrtm.org
2017年 1月 9日 (月) 23:29:09 JST


Author: win-ei
Date: 2017-01-09 23:29:08 +0900 (Mon, 09 Jan 2017)
New Revision: 900

Added:
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/DataType.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/DeepHistory.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/Event.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/History.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/Machine.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/State.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/StateDef.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/EventBase.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/MachineBase.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/RootStateInfo.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateAlias.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateBase.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateInfo.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/SubStateInfo.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/TopState.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/package-info.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/package-info.java
Log:
[FSM4RTC]Added a library for FSM. The library is implemented based on a design of Machine Objects.

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/DataType.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/DataType.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/DataType.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,18 @@
+package jp.go.aist.rtm.RTC.jfsm;
+//package jfsm;
+
+import java.lang.annotation.*;
+
+/**
+ * ユーザー定義状態の保持するデータのクラスを宣言するためのアノテーション。
+ *
+ * {@code @DataType(MyData.class)} のように使う。
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+ at Inherited
+public @interface DataType {
+
+    Class value();
+    boolean persistent() default false;
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/DeepHistory.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/DeepHistory.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/DeepHistory.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,12 @@
+package jp.go.aist.rtm.RTC.jfsm;
+//package jfsm;
+
+import java.lang.annotation.*;
+
+/**
+ * 深い履歴を指定するアノテーション。ユーザー定義状態クラスに付加する。
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface DeepHistory {
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/Event.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/Event.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/Event.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,39 @@
+package jp.go.aist.rtm.RTC.jfsm;
+//package jfsm;
+
+import jp.go.aist.rtm.RTC.jfsm.machine.EventBase;
+import jp.go.aist.rtm.RTC.jfsm.machine.StateInfo;
+
+/**
+ * <p>イベントオブジェクト。イベントをオブジェクトとして扱ったり、ハンドラ名(メソッド名)から
+ * イベントを発火するときに使用する。</p>
+ *
+ * <p>C++版と異なりジェネリクスは用いていない。{@link Event#dispatch(StateInfo)}を隠蔽するため、
+ * EventBaseと分離している。</p>
+ */
+public class Event extends EventBase {
+
+    /**
+     * イベントオブジェクトを構築する。handlerNameとkwargsから、リフレクションで適切な
+     * ハンドラメソッドを呼び出せる。
+     *
+     * @param handlerName ハンドラのメソッド名。
+     * @param kwargs ハンドラに渡すパラメータ。
+     */
+    public Event(String handlerName, Object... kwargs) {
+        this(handlerName, null, kwargs);
+    }
+
+    /**
+     * イベントオブジェクトを構築する。handlerNameとkwargsから、リフレクションで適切な
+     * ハンドラメソッドを呼び出せる。
+     *
+     * @param handlerName ハンドラのメソッド名。
+     * @param args ハンドラのパラメータ型。
+     * @param kwargs ハンドラに渡すパラメータ。
+     */
+    public Event(String handlerName, Class<?>[] args, Object... kwargs) {
+        super(handlerName, args, kwargs);
+    }
+
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/History.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/History.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/History.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,12 @@
+package jp.go.aist.rtm.RTC.jfsm;
+//package jfsm;
+
+import java.lang.annotation.*;
+
+/**
+ * 履歴を指定するアノテーション。ユーザー定義状態クラスに付加する。
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface History {
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/Machine.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/Machine.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/Machine.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,139 @@
+package jp.go.aist.rtm.RTC.jfsm;
+
+import jp.go.aist.rtm.RTC.jfsm.machine.*;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+import jp.go.aist.rtm.RTC.log.Logbuf;
+
+/**
+ * 状態遷移マシンの実装クラス。アプリケーションに対するAPIを提供する。
+ * アプリケーションはMachineのインスタンスを生成し、実際の状態遷移を実行する。
+ * アプリケーションはMachineのインスタンスに対し、イベントの発生、
+ * 現在の状態の取得、データの取得などができる。
+ *
+ * @param <T> ユーザー定義の最上位状態クラス。
+ * @param <EP> イベントプロトコルとなるインターフェース。
+ */
+public class Machine<T extends StateDef, EP> extends MachineBase {
+
+    //private static final Logger LOGGER = LoggerFactory.getLogger(Machine.class);
+
+    private final Class<EP> eventProtocolInterface;
+
+    /**
+     * 状態遷移マシンを初期化する。
+     *
+     * @param topState ユーザー定義の最上位状態クラス。
+     * @param eventProtocolInterface ベントプロトコルとなるインターフェース。
+     * @param data 最上位状態クラスが初期状態で持つデータ。ない場合はnullを指定する。
+     */
+    public Machine(Class<T> topState, Class<EP> eventProtocolInterface, Object data) {
+        super(topState);
+
+        // some remainings of experimental code
+        // require 'org.reflections:reflections:0.9.10'
+        // Reflections reflections = new Reflections("");
+        // Set<? extends Class<? extends StateBase>> subTypes = reflections.getSubTypesOf(topState);
+        // for(Class s: subTypes) {
+        // System.out.println(s.getName());
+        // }
+        this.eventProtocolInterface = eventProtocolInterface;
+//        # statechart.h: 909
+//        #  Machine(typename TOP::Data * data = 0) {  // NOLINT
+//        #    // Compile time check: TOP must directly derive from TopState<TOP>
+//        #    TopState<TOP> * p = 0;
+//        #    typename TOP::SUPER * p2 = 0;
+//        #    p2 = p;
+//        #    allocate(the_state_count_);
+//        #    start(TOP::get_info(*this), data);
+        start(getInfo(topState), data);
+//        #  }
+
+        rtcout = new Logbuf("Machine");
+    }
+
+    /**
+     * 最初の状態を指定して状態遷移マシンを初期化する。
+     *
+     * @param topState ユーザー定義の最上位状態クラス。
+     * @param eventProtocolInterface ベントプロトコルとなるインターフェース。
+     * @param state 開始時の状態。
+     * @param data 最上位状態クラスが初期状態で持つデータ。ない場合はnullを指定する。
+     */
+    public Machine(Class<T> topState, Class<EP> eventProtocolInterface, State state, Object data) {
+        super(topState);
+        this.eventProtocolInterface = eventProtocolInterface;
+        start(state.getInfo(this), data);
+    }
+
+    private void start(StateInfo info, Object data) {
+//        #   HRTM_DEBUG(LOGGER, "Starting Machine");
+        rtcout.println(Logbuf.DEBUG, "Starting Machine");
+        //LOGGER.debug("Starting Machine");
+//        #
+//        #   // Start with Root state
+//        #   current_state_ = &StateBase::get_info(*this);
+        currentState = getInfo(StateDef.class);
+//        #   // Then go to state
+//        #   set_state(info, false, data);
+        setState(info, false, data);
+    }
+
+    /**
+     * 現在の状態を調べる。
+     *
+     * @param stateClass ここで指定した状態かどうかを調べる。
+     * @return true - 現在stateClassかそのサブ状態。 false - それ以外。
+     */
+    public boolean isCurrent(Class<? extends T> stateClass) {
+        return currentState.isChild(getInfo(stateClass));
+    }
+
+    /**
+     * 現在の状態を調べる。
+     *
+     * @param stateClass ここで指定した状態かどうかを調べる。
+     * @return true - 現在stateClassの状態(サブ状態は含まない)。 false - それ以外
+     */
+    public boolean isCurrentDirect(Class<? extends T> stateClass) {
+        return currentState == getInfo(stateClass);
+    }
+
+    /**
+     * イベントを発生させるためのエンドポイントを取得する。
+     * イベントハンドラをメソッド呼び出しの形で以下のように記述できる。
+     *
+     * {@code machine.current().eventHandler(param)}
+     *
+     * エンドポイントは java.lang.reflect.Proxy のインスタンスとなっている。
+     *
+     * @return イベントハンドラの呼び出しエンドポイント。
+     */
+    public EP current() {
+        InvocationHandler handler = new MyHandler((EP) currentState.getInstance());
+        EP proxy = (EP) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{eventProtocolInterface}, handler);
+        return proxy;
+    }
+
+    class MyHandler implements InvocationHandler {
+
+        private final EP target;
+
+        MyHandler(EP target) {
+            assert target != null;
+            this.target = target;
+        }
+
+        @Override
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            Object ret = method.invoke(target, args);
+            performPending();
+            return ret;
+        }
+    }
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/State.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/State.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/State.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,57 @@
+package jp.go.aist.rtm.RTC.jfsm;
+//package jfsm;
+
+import jp.go.aist.rtm.RTC.jfsm.machine.MachineBase;
+import jp.go.aist.rtm.RTC.jfsm.machine.StateAlias;
+import jp.go.aist.rtm.RTC.jfsm.machine.StateBase;
+import jp.go.aist.rtm.RTC.jfsm.machine.StateInfo;
+
+/**
+ * 状態遷移を実行するときに遷移先を示すオブジェクト。
+ * 以下のように、ユーザー定義状態のクラスを渡してオブジェクトを作り、{@link StateBase#setState(State)}に渡す。
+ *
+ * <pre>
+ *     public void MyEventHandler() {
+ *         setState(new State(MyDefinedState.class));
+ *     }
+ * </pre>
+ *
+ * C++版ではStateAliasを継承し、Stateクラスはテンプレートクラスになっているが、
+ * Java版ではStateAliasを継承した普通のクラスになっている。
+ *
+ */
+public class State extends StateAlias {
+    private Class<? extends StateBase> stateClass;
+
+    /**
+     * 遷移先と初期データを指定してオブジェクトを作る。
+     *
+     * @param stateDef 遷移先の状態のクラス
+     * @param data 遷移先状態の初期データ
+     */
+    public State(Class<? extends StateBase> stateDef, Object data) {
+        super(data);
+        this.stateClass = stateDef;
+    }
+
+    /**
+     * 遷移先を指定してオブジェクトを作る。
+     *
+     * @param stateDef 遷移先の状態のクラス
+     */
+    public State(Class<? extends StateBase> stateDef) {
+        this(stateDef, null);
+    }
+
+    /**
+     * Machine内部で使用するメソッド。アプリケーションから呼び出してはならない。
+     *
+     * 状態に対応するStateInfoを取得する。
+     *
+     * @param machine Machineオブジェクト。
+     * @return 自身の状態に対応するSateInfoオブジェクト。
+     */
+    public StateInfo getInfo(MachineBase machine) {
+        return getInfo(machine, stateClass);
+    }
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/StateDef.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/StateDef.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/StateDef.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,91 @@
+package jp.go.aist.rtm.RTC.jfsm;
+
+import jp.go.aist.rtm.RTC.jfsm.DeepHistory;
+import jp.go.aist.rtm.RTC.jfsm.History;
+import jp.go.aist.rtm.RTC.jfsm.machine.StateInfo;
+import jp.go.aist.rtm.RTC.jfsm.machine.TopState;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.annotation.Annotation;
+
+/**
+ * ユーザー定義状態のスーパークラス。最上位状態は、かならずこのクラスを直接継承しなくてはならない。
+ */
+public class StateDef extends TopState {
+
+    private final boolean history;
+    private final boolean deepHistory;
+
+    public StateDef() {
+        history = isHistory();
+        deepHistory = isDeepHistory();
+    }
+
+    /**
+     * Machine内部で使用するメソッド。アプリケーションから呼び出してはならない。
+     */
+// statechar.h:77
+//          void set_history_super(\
+//               hrtm::sc::StateInfo & self, hrtm::sc::StateInfo & deep) \
+    @Override
+    public void setHistorySuper(StateInfo self, StateInfo deep) {
+//           { self.set_history_super(deep); } \
+        self.setHistorySuper(deep);
+    }
+
+    /**
+     * Machine内部で使用するメソッド。アプリケーションから呼び出してはならない。
+     */
+    @Override
+    protected void saveHistory(StateInfo self, StateInfo shallow, StateInfo deep) {
+        if (history) {
+// statechar.h:71
+//            void save_history(hrtm::sc::StateInfo & self, hrtm::sc::StateInfo & shallow, \
+//            hrtm::sc::StateInfo & deep) { \
+//                self.set_history(&shallow); \
+//                SUPER::set_history_super(self, deep); } \
+            self.setHistory(shallow);
+            invokeSetHistorySuper(self, deep);
+            return;
+        }
+        if (deepHistory) {
+// statechar.h:57
+//           void save_history(hrtm::sc::StateInfo & self, \
+//             hrtm::sc::StateInfo & /* shallow */, hrtm::sc::StateInfo & deep) { \
+//           self.set_history(&deep); \
+//           SUPER::set_history_super(self, deep); } \
+            self.setHistory(deep);
+        }
+        invokeSetHistorySuper(self, deep);
+    }
+
+    private void invokeSetHistorySuper(final StateInfo self, final StateInfo deep) {
+        try {
+            this.getClass().getSuperclass().getMethod("setHistorySuper", new Class<?>[]{StateInfo.class, StateInfo.class}).invoke(this, self, deep);
+        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private boolean isHistory() {
+        //return getClass().getDeclaredAnnotation(History.class) != null;
+        Annotation[] annotations = getClass().getDeclaredAnnotations();
+        for(int ic=0;ic<annotations.length;++ic) {
+            if(annotations[ic].annotationType() == History.class) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isDeepHistory() {
+        //return getClass().getDeclaredAnnotation(DeepHistory.class) != null;
+        Annotation[] annotations = getClass().getDeclaredAnnotations();
+        for(int ic=0;ic<annotations.length;++ic) {
+            if(annotations[ic].annotationType() == DeepHistory.class) {
+                return true;
+            }
+        }
+        return false;
+    }
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/EventBase.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/EventBase.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/EventBase.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,27 @@
+package jp.go.aist.rtm.RTC.jfsm.machine;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class EventBase {
+    protected final String handlerName;
+    protected final Class<?>[] args;
+    protected final Object[] kwargs;
+
+    public EventBase(String handlerName, Class<?>[] args, Object... kwargs) {
+        this.handlerName = handlerName;
+        this.args = args;
+        this.kwargs = kwargs;
+    }
+
+    void dispatch(StateInfo info) {
+       try {
+           info.getInstance().getClass().getMethod(handlerName, args).invoke(info.getInstance(), kwargs);
+       } catch (InvocationTargetException | SecurityException e) {
+           throw new RuntimeException("exception in onExit", e);
+       } catch (IllegalAccessException e) {
+           throw new RuntimeException("failed to invoke onExit() - perhaps non public?", e);
+       } catch (NoSuchMethodException e) {
+           throw new RuntimeException(e);
+       }
+   }
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/MachineBase.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/MachineBase.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/MachineBase.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,298 @@
+package jp.go.aist.rtm.RTC.jfsm.machine;
+
+import static java.lang.String.format;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import jp.go.aist.rtm.RTC.jfsm.Event;
+import jp.go.aist.rtm.RTC.jfsm.State;
+import jp.go.aist.rtm.RTC.jfsm.StateDef;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+import jp.go.aist.rtm.RTC.log.Logbuf;
+
+public class MachineBase {
+
+    //private static final Logger LOGGER = LoggerFactory.getLogger(MachineBase.class);
+
+    protected StateInfo currentState;
+    private final Map<Class, StateInfo> states = new HashMap<>();
+    private StateInfo pendingState;
+    private final Map<String, EventBase> deferredEvents = new HashMap<>();
+    private final Deque<String> deferredNames = new ArrayDeque<>();
+
+    protected final Class<? extends StateBase> topState;
+    private boolean pendingHistory;
+
+    private Event pendingEvent;
+
+    private Object pendingData;
+
+    protected MachineBase(Class<? extends StateBase> topState) {
+        this.topState = topState;
+        rtcout = new Logbuf("MachineBase");
+
+    }
+
+    /**
+     * 対応するStateInfoを取得する。
+     *
+     * @param stateClass この状態についての情報を取得する。
+     * @return 対応するStateInfo。
+     */
+    protected final StateInfo getInfo(Class stateClass) {
+        StateInfo info = states.get(stateClass);
+        if (info == null) {
+            info = stateClass.equals(StateDef.class)
+                    ? new RootStateInfo(this, null) : new SubStateInfo(stateClass, this, getInfo(stateClass.getSuperclass()));
+            setInfo(stateClass, info);
+        }
+        return info;
+    }
+
+    public void setInfo(Class stateClass, StateInfo info) {
+        states.put(stateClass, info);
+    }
+
+//    #  void MachineBase::set_state(StateInfo & info, bool history, void * data) {
+    public void setState(StateInfo info, boolean history, Object data) {
+//    #      set_pending_state(info, history, data);
+//    #      perform_pending();
+        setPendingState(info, history, data);
+        performPending();
+    }
+
+//        # statechart.h: 695
+//        #  void set_pending_state(StateInfo & info, bool history, void * data) {
+    protected void setPendingState(StateInfo info, boolean history, Object data) {
+//        #      assert((!pending_state_ || pending_state_ == &info) &&
+//        #      "There is already a state transition pending!");
+        assert (pendingState == null || pendingState == info) : "There is already a state transition pending!";
+//        #      pending_state_ = &info;
+//        #      pending_data_ = data;
+//        #      pending_history_ = history;
+        pendingState = info;
+        pendingData = data;
+        pendingHistory = history;
+    }
+
+    protected void performPending() {
+//        #    assert(current_state_);
+        assert currentState != null;
+//        #    if (pending_state_) {
+        if (pendingState != null) {
+//        #      // Loop here because init actions might change state again.
+//        #      while (pending_state_) {
+            while (pendingState != null) {
+//        #        HRTM_DEBUG(LOGGER, current_state_->name() << ": transition to: " <<
+//        #            pending_state_->name());
+                rtcout.println(Logbuf.DEBUG, currentState.getName()
+                                             + ": transition to: " 
+                                             + pendingState.getName());
+                //LOGGER.debug(format("%s: transition to: %s", currentState.getName(), pendingState.getName()));
+//        #        // Perform exit actions (which exactly depends on new state).
+//        #        current_state_->on_exit(*pending_state_);
+                currentState.onExit(pendingState);
+//        #        // Store history information for previous state now.
+//        #        // Previous state will be used for deep history.
+//        #        current_state_->set_history_super(*current_state_);
+                currentState.setHistorySuper(currentState);
+//        #        StateInfo * previous = current_state_;
+                StateInfo previous = currentState;
+//        #        current_state_ = pending_state_;
+                currentState = pendingState;
+//        #        if (pending_data_) {
+//        #          current_state_->set_data(pending_data_);
+//        #        }
+                if (pendingData != null) {
+                    currentState.setData(pendingData);
+                }
+//        #        // Perform entry actions (which exactly depends on previous state).
+//        #        current_state_->on_entry(*previous);
+                currentState.onEntry(previous);
+//        #        // State transition complete.
+//        #        // Clear 'pending' information just now so that set_state would assert
+//        #        // in exits and entries, but not in init.
+//        #        pending_state_ = 0;
+                pendingState = null;
+//        #        pending_data_ = 0;
+                pendingData = null;
+//        #        bool history = pending_history_;
+                boolean history = pendingHistory;
+//        #        pending_history_ = false;
+                pendingHistory = false;
+//        #        // "init" may change state again.
+//        #        current_state_->on_init(history);
+                currentState.onInit(history);
+//        #        assert("Init may only transition to proper substates" &&
+//        #            (!pending_state_ ||
+//        #             (pending_state_->is_child(*current_state_) &&
+//        #             (current_state_ != pending_state_))));
+                if (pendingState != null && pendingState.isChild(currentState)) {
+                    assert currentState != pendingState : "Init may only transition to proper substates";
+                }
+//        #        // Perform pending event
+//        #        perform_pending_event();
+                peformPendingEvent();
+//        #        // Perform deferred events
+//        #        perform_deferred_events();
+                performDeferredEvents();
+//        #      }  // while (pending_state_)
+            }
+//        #    } else {  // if (pending_state_)
+        } else {
+//        #      // Perform pending event
+//        #      perform_pending_event();
+            peformPendingEvent();
+//        #    }
+//        #  }
+
+        }
+
+    }
+
+    public void addDeferredEvent(Event event, String name) {
+//        try:
+//            queue = self._deferred_events.get(name, None)
+//            if queue:
+//                logger.debug("{0} is already deferred.".format(name))
+//                return
+//            self._deferred_events[name] = event
+//            self._deferred_names.append(name)
+//        except Exception as e:
+//            logger.debug("Can't add defferd event by {0}".format(e))
+        if (this.deferredNames.contains(name)) {
+            rtcout.println(Logbuf.DEBUG, "{} is already deferred. " + name);
+            //LOGGER.debug("{} is already deferred.", name);
+            return;
+        }
+        this.deferredEvents.put(name, event);
+        this.deferredNames.offerLast(name);
+    }
+
+    void performDeferredEvents() {
+//        if not self._deferred_events:
+//            return
+        if (this.deferredEvents.isEmpty()) {
+            return;
+        }
+//        for name in self._deferred_names:
+//            if self._current_state:
+//                self._deferred_events[name].dispatch(self._current_state)
+        final Iterator<String> it = this.deferredNames.iterator();
+        while (it.hasNext()) {
+            final String name = it.next();
+            if (this.currentState != null) {
+                this.deferredEvents.get(name).dispatch(this.currentState);
+            }
+        }
+//        self._deferred_events.clear()
+//        del self._deferred_names[:]  # effectively self._deferred_names.clean() (not in Python2.7)
+        this.deferredEvents.clear();
+        this.deferredNames.clear();
+    }
+
+    public Object data() {
+        return currentState.getInstance().data(topState);
+    }
+
+    void setPendingEvent(Event event) {
+        assert this.pendingEvent == null;
+        this.pendingEvent = event;
+    }
+
+    private void peformPendingEvent() {
+        if (this.pendingEvent != null) {
+            final EventBase event = this.pendingEvent;
+            this.pendingEvent = null;
+            event.dispatch(currentState);
+        }
+    }
+
+//        # statechart.cc: 151
+//        #  void MachineBase::shutdown() {
+    public void shutdown() {
+//        #    assert(!pending_state_);
+        assert pendingState == null;
+
+//        #    HRTM_DEBUG(LOGGER, "Shutting down Machine");
+//        #    // Performs exit actions by going to Root (=State) state.
+//        #    set_state(StateBase::get_info(*this), false, 0);
+//        #    current_state_ = 0;
+        rtcout.println(Logbuf.DEBUG, "Shutting down Machine");
+        //LOGGER.debug("Shutting down Machine");
+        this.setState(getInfo(StateDef.class), false, null);
+        this.currentState = null;
+    }
+
+    /**
+     * イベントを発生させる。
+     *
+     * @param event 発生させるイベントオブジェクト。
+     */
+    public void dispatch(Event event) {
+        // C++版ではMachineのメソッドだが、EventBase#dispatch(StateInfo)を隠蔽するためにここで実装している。
+        final EventBase base = event;
+        assert base != null;
+        base.dispatch(currentState);
+        this.performPending();
+    }
+
+    /**
+     * <p>保存された履歴を削除する。</p>
+     * <p>C++の実装ではLinkクラスのstaticメソッドだが、Javaの制限により、Machineクラスのメソッドとしている。</p>
+     *
+     * @param stateClass 履歴を削除したいユーザー定義状態クラス
+     */
+    public void clearHistory(Class<? extends StateBase> stateClass) {
+        getInfo(stateClass).setHistory(null);
+    }
+
+    /**
+     * <p>保存された深い履歴を削除する。</p>
+     * <p>C++の実装ではLinkクラスのstaticメソッドだが、Javaの制限により、Machineクラスのメソッドとしている。</p>
+     *
+     * @param stateClass 履歴を削除したいユーザー定義状態クラス
+     */
+    public void clearHistoryDeep(Class<? extends StateBase> stateClass) {
+        StateInfo state = getInfo(stateClass);
+        for (StateInfo s : states.values()) {
+            if (s != null && s.isChild(state)) {
+                s.setHistory(null);
+            }
+        }
+    }
+
+    /**
+     * Machineに対して直接状態遷移を指示する。イベントハンドラ外から使用する。
+     * アプリケーションで本来想定していない遷移も可能のため、主にテスト目的。
+     *
+     * @param state 遷移先の状態
+     * @param history 履歴を使うかどうか
+     */
+    public void setState(State state, boolean history) {
+        setState(state, history, null);
+    }
+
+    /**
+     * Machineに対して直接状態遷移を指示する。イベントハンドラ外から使用する。
+     * アプリケーションで本来想定していない遷移も可能のため、主にテスト目的。
+     *
+     * @param state 遷移先の状態
+     * @param history 履歴を使うかどうか
+     * @param data 遷移先の状態に設定するデータ
+     */
+    public void setState(State state, boolean history, Object data) {
+        setPendingState(state.getInfo(this), history, data);
+        performPending();
+    }
+    /**
+     * {@.ja Logging用フォーマットオブジェクト}
+     * {@.en Format object for Logging}
+     */
+    protected Logbuf rtcout;
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/RootStateInfo.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/RootStateInfo.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/RootStateInfo.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,24 @@
+package jp.go.aist.rtm.RTC.jfsm.machine;
+
+class RootStateInfo extends StateInfo {
+
+    public <T, D> RootStateInfo(MachineBase machine, StateInfo parent) {
+        super(machine, parent);
+        setInstance(new StateBase());
+        this.setStateInfo();
+    }
+
+    private void setStateInfo() {
+        getInstance().setStateInfo(this);
+    }
+
+    @Override
+    protected void createData() {
+        // do nothing
+    }
+
+    @Override
+    public String getName() {
+        return "Root";
+    }
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateAlias.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateAlias.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateAlias.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,27 @@
+package jp.go.aist.rtm.RTC.jfsm.machine;
+
+public class StateAlias {
+
+    protected Object data;
+
+    public StateAlias(Object data) {
+        this.data = data;
+    }
+
+    public Object takeData() {
+        Object data = this.data;
+        this.data = null;
+        return data;
+    }
+
+    /**
+     * StateInfoを取得する。MachineBase#getInfo(Class)をprotectedにするため、ここで実装している。
+     *
+     * @param machine Machineオブジェクト。
+     * @param stateClass この状態の情報を取得する。
+     * @return StateInfoオブジェクト。
+     */
+    protected StateInfo getInfo(MachineBase machine, Class<? extends StateBase> stateClass) {
+        return machine.getInfo(stateClass);
+    }
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateBase.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateBase.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateBase.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,108 @@
+package jp.go.aist.rtm.RTC.jfsm.machine;
+
+import jp.go.aist.rtm.RTC.jfsm.Event;
+import jp.go.aist.rtm.RTC.jfsm.State;
+
+/**
+ * ユーザー定義状態のスーパークラス。
+ */
+public class StateBase {
+
+    protected StateInfo stateInfo;
+
+    protected StateBase() {
+    }
+
+    void setStateInfo(StateInfo stateInfo) {
+        // StateBaseのコンストラクタではStateInfoを渡せない
+        // (ユーザー定義状態クラスのコンストラクタを書けないため)。
+        // そのためMachineBaseでインスタンス生成するタイミングで設定するようにする
+        assert this.stateInfo == null;
+        this.stateInfo = stateInfo;
+    }
+
+    /**
+     * <p>状態遷移する。イベントハンドラ内で使用する。</p>
+     * <p>実際の遷移にするタイミングは、このメソッドを呼び出したイベントハンドラが終了した直後となる。
+     * このメソッドでは、(ハンドラ後に)遷移する先を登録する。</p>
+     *
+     * @param state 遷移先の状態。
+     *
+     */
+    protected void setState(State state) {
+        final StateInfo info = state.getInfo(this.stateInfo.machine);
+        this.stateInfo.machine.setPendingState(info, true, state.takeData());
+    }
+
+    /**
+     * <p>履歴を無視して状態遷移する。イベントハンドラ内で使用する。</p>
+     * <p>実際の遷移にするタイミングは、このメソッドを呼び出したイベントハンドラが終了した直後となる。
+     * このメソッドでは、(ハンドラ後に)遷移する先を登録する。</p>
+     *
+     * @param state 遷移先の状態。
+     */
+    protected void setStateDirect(State state) {
+        final StateInfo info = state.getInfo(this.stateInfo.machine);
+        this.stateInfo.machine.setPendingState(info, false, state.takeData());
+    }
+
+    protected <T> T data() {
+        return (T) stateInfo.getData();
+    }
+
+    protected <T> T data(Class<?> state) {
+        return (T) stateInfo.machine.getInfo(state).getData();
+    }
+
+    public void onInit() {
+    }
+
+    public void onEntry() {
+    }
+
+    public void onExit() {
+    }
+
+    /**
+     * @param event イベントオブジェクト。
+     * @param name イベント名。イベント事にユニークな名前をつける。
+     */
+    public void defer(Event event, String name) {
+//        # default value for parameter name is placed in StateDef.defer()
+//        assert event
+//        self._state_info.machine.add_deferred_event(event, name)
+        assert event != null;
+        this.stateInfo.machine.addDeferredEvent(event, name);
+    }
+
+    public void defer(Event event) {
+        this.defer(event, "event");
+    }
+
+    String getStateName() {
+        return getClass().getSimpleName();
+    }
+
+    /**
+     * Machine内部で使用するメソッド。アプリケーションから呼び出してはならない。
+     *
+     * saveHistory()とsetHistorySuper()の組み合わせで、履歴の戦略の切り替えを実現する。
+     */
+    // リフレクション(getMethod)で取得するため、可視性をpublicとしている。
+    public void setHistorySuper(StateInfo self, StateInfo deep) {
+        // no implementation for StateBase
+    }
+
+    /**
+     * Machine内部で使用するメソッド。アプリケーションから呼び出してはならない。
+     *
+     * saveHistory()とsetHistorySuper()の組み合わせで、履歴の戦略の切り替えを実現する。
+     */
+    protected void saveHistory(StateInfo self, StateInfo shallow, StateInfo deep) {
+        // no implementation for StateBase
+    }
+
+    void deleteData(StateInfo stateInfo) {
+        stateInfo.deleteData();
+    }
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateInfo.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateInfo.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/StateInfo.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,200 @@
+package jp.go.aist.rtm.RTC.jfsm.machine;
+
+import static java.lang.String.format;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.annotation.Annotation;
+
+import jp.go.aist.rtm.RTC.jfsm.DataType;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+
+import jp.go.aist.rtm.RTC.log.Logbuf;
+
+/**
+ * 状態に関する実行時情報を保持するオブジェクト。
+ */
+public class StateInfo {
+
+    //private static final Logger LOGGER = LoggerFactory.getLogger(StateInfo.class);
+
+    private final StateInfo parent;
+    private StateInfo history;
+    private StateBase instance;
+    public MachineBase machine;
+    protected Object data;
+
+    public StateInfo(MachineBase machine, StateInfo parent) {
+        this.machine = machine;
+        this.parent = parent;
+        rtcout = new Logbuf("StateInfo");
+    }
+
+    public void onExit(StateInfo next) {
+        if (parent == null) {
+            return;
+        }
+        if (this == next || !next.isChild(this)) {
+            rtcout.println(Logbuf.DEBUG, getName() + ": exit");
+            //LOGGER.debug(format("%s: exit", getName()));
+
+            // onExit()を実装していない状態では、親のものを呼んではならない
+            // C++版では継承関係にLinkを介在させていたが、Javaでは同じことができないので
+            // リフレクションで検査している
+            invokeMethod(instance, "onExit");
+            instance.deleteData(this);
+            parent.onExit(next);
+        }
+    }
+
+    public boolean isChild(StateInfo state) {
+        return this == state || (parent != null && parent.isChild(state));
+    }
+
+    public void onEntry(StateInfo previous) {
+        onEntry(previous, true);
+    }
+
+//        # statechart.cc: 49
+//        #  void StateInfo::on_entry(StateInfo & previous, bool first) {
+    public void onEntry(StateInfo previous, boolean first) {
+//        #    // Only Root has no parent
+//        #    if (!parent_) {
+//        #      return;
+//        #    }
+        if (parent == null) {
+            return;
+        }
+//        #    // first entry or previous state is not substate -> perform entry
+//        #    if (first || !previous.is_child(*this)) {
+        if (first || !previous.isChild(this)) {
+//        #      parent_->on_entry(previous, false);
+            parent.onEntry(previous, false);
+//        #      // Could be set from outside or persistent (or EmptyData)
+//        #      if (!data_) {
+//        #        create_data();
+//        #      }
+            if (data == null) {
+                createData();
+            }
+//        #      HRTM_DEBUG(LOGGER, name() <<  ": entry");
+//        #      instance_->on_entry();
+            rtcout.println(Logbuf.DEBUG, getName() + ": entry");
+            //LOGGER.debug(format("%s: entry", getName()));
+            instance.onEntry();
+//        #    }
+        }
+    }
+
+    protected void createData() {
+        throw new RuntimeException("create_data() must be overridden");
+    }
+
+//        # statechart.cc: 80
+//        #  void StateInfo::on_init(bool history) {
+    public void onInit(boolean history) {
+//        #    if (history && history_) {
+//        #      HRTM_DEBUG(LOGGER, name() << ": history transition to: " <<
+//        #         history_->name());
+//        #      machine_.set_pending_state(*history_, true, 0);
+        if (history && this.history != null) {
+            rtcout.println(Logbuf.DEBUG, getName()
+                                         + ": history transition to: "
+                                         + this.history.getName());
+            //LOGGER.debug(format("%s: history transition to: %s", getName(), this.history.getName()));
+            machine.setPendingState(this.history, true, 0);
+        } else {
+//        #    } else {
+//        #      HRTM_DEBUG(LOGGER, name() << ": init");
+//        #      instance_->on_init();
+//        #    }
+            // onInit()を実装していない状態では、親のものを呼んではならない
+            // C++版では継承関係にLinkを介在させて実現していたが、Javaでは同じことができないので
+            // リフレクションで検査している
+            rtcout.println(Logbuf.DEBUG, getName() + ": init");
+            //LOGGER.debug(format("%s: init", getName()));
+            invokeMethod(instance, "onInit");
+        }
+//        #    history_ = 0;
+        this.history = null;
+    }
+
+    private static void invokeMethod(final StateBase instance, final String methodName) {
+        try {
+            instance.getClass().getDeclaredMethod(methodName).invoke(instance);
+        } catch (NoSuchMethodException e) {
+            // method is not declared; just skip
+        } catch (InvocationTargetException e) {
+            throw new RuntimeException("exception in onInit", e);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException("failed to invoke onInit() - perhaps non public?", e);
+        }
+    }
+
+    final void setInstance(StateBase stateInstance) {
+        assert instance == null;
+        instance = stateInstance;
+    }
+
+    public final StateBase getInstance() {
+        return instance;
+    }
+
+    protected Object getData() {
+        return data;
+    }
+
+    public String getName() {
+        return null;
+    }
+
+// statechart.h: 398
+//          void save_history(StateInfo & shallow, StateInfo & deep) {
+    public void saveHistory(StateInfo shallow, StateInfo deep) {
+//            // Check state's history strategy.
+//            instance_->save_history(*this, shallow, deep);
+        instance.saveHistory(this, shallow, deep);
+    }
+
+// statechart.h: 402
+//          // Update superstate's history information:
+//          void set_history_super(StateInfo & deep) {
+    public void setHistorySuper(StateInfo deep) {
+//            if (parent_) {
+//              // Let it choose between deep or shallow history.
+//              parent_->save_history(*this, deep);
+//            }
+        if (parent != null) {
+            parent.saveHistory(this, deep);
+        }
+    }
+
+    public void setHistory(StateInfo history) {
+        this.history = history;
+    }
+
+    void setData(Object data) {
+        assert data != null;
+        this.data = data;
+    }
+
+    void deleteData() {
+        //DataType dataType = instance.getClass().getDeclaredAnnotation(DataType.class);
+        Annotation[] annotations = instance.getClass().getDeclaredAnnotations();
+        DataType dataType = null;
+        for(int ic=0;ic<annotations.length;++ic) {
+            if(annotations[ic].annotationType() == DataType.class) {
+                dataType = (DataType)annotations[ic];
+            }
+        }
+        if(dataType != null && dataType.persistent()) {
+            return;
+        }
+        this.data = null;
+    }
+
+    /**
+     * {@.ja Logging用フォーマットオブジェクト}
+     * {@.en Format object for Logging}
+     */
+    protected Logbuf rtcout;
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/SubStateInfo.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/SubStateInfo.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/SubStateInfo.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,43 @@
+package jp.go.aist.rtm.RTC.jfsm.machine;
+
+import jp.go.aist.rtm.RTC.jfsm.DataType;
+
+class SubStateInfo extends StateInfo {
+
+    private final Class<? extends StateBase> stateClass;
+
+    public SubStateInfo(Class<? extends StateBase> stateClass, MachineBase machine, StateInfo parent) {
+        super(machine, parent);
+        this.stateClass = stateClass;
+        setInstance(newInstance(stateClass));
+        this.setStateInfo();
+    }
+
+    private void setStateInfo() {
+        getInstance().setStateInfo(this);
+    }
+
+    @Override
+    protected void createData() {
+        final DataType dataType = stateClass.getAnnotation(DataType.class);
+        if (dataType == null) {
+            return;
+        }
+        data = newInstance(dataType.value());
+    }
+
+    @Override
+    public String getName() {
+        return getInstance().getStateName();
+    }
+
+    private static <T> T newInstance(Class<T> type) {
+        try {
+            return type.newInstance();
+        } catch (InstantiationException e) {
+            throw new RuntimeException("failed to instantiate a user defined data - perhaps no default constructor?", e);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException("failed to instantiate a user defined data - maybe not public?", e);
+        }
+    }
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/TopState.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/TopState.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/TopState.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,13 @@
+package jp.go.aist.rtm.RTC.jfsm.machine;
+
+import jp.go.aist.rtm.RTC.jfsm.Event;
+
+public class TopState extends StateBase {
+
+    public TopState() {
+    }
+
+    protected void dispatch(Event event) {
+        stateInfo.machine.setPendingEvent(event);
+    }
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/package-info.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/package-info.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/machine/package-info.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,4 @@
+/**
+ * 状態マシンの内部実装のためのクラス。アプリケーションからは使用しない。
+ */
+package jp.go.aist.rtm.RTC.jfsm.machine;

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/package-info.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/package-info.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/jfsm/package-info.java	2017-01-09 14:29:08 UTC (rev 900)
@@ -0,0 +1,5 @@
+/**
+ * 有限状態マシン(FSM)のAPIパッケージ。アプリケーションは、このパッケージに存在する
+ * クラスを用いて実装する。
+ */
+package jp.go.aist.rtm.RTC.jfsm;



More information about the openrtm-commit mailing list