package hdgl.db.query.stm;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.hadoop.io.Writable;
import hdgl.db.exception.HdglException;
import hdgl.db.query.condition.AbstractCondition;
public class StateMachine implements Writable {
public static enum TransitionType{
In, Out, Backtrack, Success;
public static TransitionType read(DataInput in) throws IOException{
byte i = in.readByte();
switch (i) {
case 1:
return In;
case 2:
return Out;
case 3:
return Backtrack;
case 4:
return Success;
default:
throw new HdglException("Unsupported Transition Type: "+i);
}
}
public static void write(TransitionType tt, DataOutput out) throws IOException {
switch (tt) {
case In:
out.writeByte(1);
break;
case Out:
out.writeByte(2);
break;
case Backtrack:
out.writeByte(3);
break;
case Success:
out.writeByte(4);
break;
default:
throw new HdglException("Unsupported Transition Type: " + tt);
}
}
}
public static class Transition implements Writable{
private TransitionType type;
private AbstractCondition test;
private int toState;
public Transition() {
}
public Transition(TransitionType type, AbstractCondition test,
int toState) {
super();
this.type = type;
this.test = test;
this.toState = toState;
}
public TransitionType getType() {
return type;
}
public void setType(TransitionType type) {
this.type = type;
}
public AbstractCondition getTest() {
return test;
}
public void setTest(AbstractCondition test) {
this.test = test;
}
public int getToState() {
return toState;
}
public void setToState(int toState) {
this.toState = toState;
}
@Override
public void readFields(DataInput in) throws IOException {
type = TransitionType.read(in);
test = AbstractCondition.readAbstractCondition(in);
toState = in.readInt();
}
@Override
public void write(DataOutput out) throws IOException {
TransitionType.write(type, out);
test.write(out);
out.writeInt(toState);
}
}
public static class Condition implements Writable{
private AbstractCondition test;
private ArrayList<Transition> transitions = new ArrayList<StateMachine.Transition>();
public int getSize(){
return transitions.size();
}
public AbstractCondition getTest() {
return test;
}
public void setTest(AbstractCondition test) {
this.test = test;
}
public Transition getTransition(int transId) {
return transitions.get(transId);
}
public Iterable<Transition> getTransitions(){
return transitions;
}
public int addTransition(Transition transition) {
this.transitions.add(transition);
return transitions.size()-1;
}
public Condition() {
}
public Condition(AbstractCondition test) {
super();
this.test = test;
}
@Override
public void readFields(DataInput in) throws IOException {
test = AbstractCondition.readAbstractCondition(in);
int len=in.readInt();
transitions.clear();
for(int i=0;i<len;i++){
Transition t = new Transition();
t.readFields(in);
transitions.add(t);
}
}
@Override
public void write(DataOutput out) throws IOException {
test.write(out);
out.writeInt(transitions.size());
for(Transition t:transitions){
t.write(out);
}
}
}
public static class State implements Writable{
ArrayList<Condition> conditions = new ArrayList<Condition>();
public int getSize(){
return conditions.size();
}
public Condition getCondition(int condId){
return conditions.get(condId);
}
public Iterable<Condition> getConditions(){
return conditions;
}
public int addCondition(Condition cond) {
this.conditions.add(cond);
return conditions.size()-1;
}
@Override
public void readFields(DataInput in) throws IOException {
int len=in.readInt();
conditions.clear();
for(int i=0;i<len;i++){
Condition condition = new Condition();
condition.readFields(in);
conditions.add(condition);
}
}
@Override
public void write(DataOutput out) throws IOException {
out.writeInt(conditions.size());
for(Condition c:conditions){
c.write(out);
}
}
}
public int getStartState(){
return 1;
}
int maxState = 1;
Map<Integer, State> states = new HashMap<Integer, StateMachine.State>();
public int addState(){
int stateId = maxState;
maxState++;
states.put(stateId, new State());
return stateId;
}
public State getState(int stateId){
return states.get(stateId);
}
public Iterable<State> getStates(){
return states.values();
}
public void print(PrintStream out){
out.println("states\tconditions\ttransitions");
for (Map.Entry<Integer, State> states : this.states.entrySet()) {
out.print(states.getKey()+"\t");
int condsize=states.getValue().getSize();
for(int i=0;i<condsize;i++){
Condition cond = states.getValue().getCondition(i);
if(i>0){
out.print("\t");
}
out.print(cond.getTest()+"\t\t");
for(int j=0;j<cond.getSize();j++){
Transition transition = cond.getTransition(j);
if(j>0){
out.print("\t\t\t");
}
out.println(transition.type + "[" + transition.test + "] -> "+transition.toState);
}
}
}
}
@Override
public void readFields(DataInput in) throws IOException {
states.clear();
int len = in.readInt();
for(int i=0;i<len;i++){
int id = in.readInt();
State state=new State();
state.readFields(in);
states.put(id, state);
}
maxState = len + 1;
}
@Override
public void write(DataOutput out) throws IOException {
Set<Map.Entry<Integer, State>> states = this.states.entrySet();
out.writeInt(states.size());
for(Map.Entry<Integer, State> state:states){
out.writeInt(state.getKey());
state.getValue().write(out);
}
}
@Override
public String toString() {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream w = new PrintStream(out);
print(w);
return new String(out.toByteArray());
}
}