package hdgl.db.query.convert; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import hdgl.db.query.condition.AbstractCondition; import hdgl.db.query.condition.NoRestriction; import hdgl.db.query.expression.Edge; import hdgl.db.query.expression.Entity; import hdgl.db.query.expression.Expression; import hdgl.db.query.expression.Query; import hdgl.db.query.expression.Vertex; import hdgl.db.query.stm.SimpleStateMachine; import hdgl.db.query.stm.SimpleStateMachineWithData; import hdgl.db.query.visitor.FirstPosVisitor; import hdgl.db.query.visitor.FollowPosVisitor; import hdgl.db.query.visitor.IdentifyEntitiesVisitor; import hdgl.db.query.visitor.LastPosVisitor; import hdgl.db.query.visitor.NullableVisitor; public class QueryToStateMachine { static class SimpleState{ Set<Integer> pos; Map<Entity, SimpleState> translates = new HashMap<Entity, QueryToStateMachine.SimpleState>(); boolean isVertex; boolean isSuccess; public boolean isSuccess() { return isSuccess; } public boolean isVertex() { return isVertex; } public SimpleState(Set<Integer> pos, boolean isVertex, boolean isSuccess){ this.pos = pos; this.isVertex = isVertex; this.isSuccess = isSuccess; } @Override public int hashCode() { return pos.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; SimpleState other = (SimpleState) obj; if (pos == null) { if (other.pos != null) return false; } else if (!pos.equals(other.pos)) return false; return true; } public Set<Integer> getPos() { return pos; } public Map<Entity, SimpleState> getTranslates() { return translates; } @Override public String toString() { return pos.toString(); } } public static SimpleStateMachine convert(Expression query){ IdentifyEntitiesVisitor visitor = new IdentifyEntitiesVisitor(); query.accept(visitor); Map<Entity, Integer> idsMap = visitor.getEntityMap(); Map<Integer, Entity> idsRevMap = visitor.getIdMap(); Map<Integer, AbstractCondition[]> condMap = new HashMap<Integer, AbstractCondition[]>(); for (Map.Entry<Integer, Entity> i : idsRevMap.entrySet()) { condMap.put(i.getKey(), i.getValue().getAbstractConditions()); } // for(Map.Entry<Integer, Entity> i:visitor.getIdMap().entrySet()){ // assert i.getKey().equals(idsMap.get(i.getValue())); // System.out.println(i.getKey()+": "+i.getValue()); // } NullableVisitor visitor2 = new NullableVisitor(idsMap); query.accept(visitor2); // for(Map.Entry<Expression, Boolean> i:visitor2.getNullableMap().entrySet()){ // System.out.println(i.getKey()+": "+i.getValue()); // } Map<Expression, Boolean> nullable = visitor2.getNullableMap(); FirstPosVisitor v3 = new FirstPosVisitor(idsMap, nullable); LastPosVisitor v4 = new LastPosVisitor(idsMap, nullable); query.accept(v3); query.accept(v4); Map<Expression, Set<Integer>> firstpos = v3.getFirstPos(); Map<Expression, Set<Integer>> lastpos = v4.getLastPos(); // for(Entry<Expression, Set<Integer>> i: firstpos.entrySet()){ // System.out.println(i.getKey()+": "+i.getValue()+" - "+lastpos.get(i.getKey())); // } FollowPosVisitor v5 = new FollowPosVisitor(idsMap, idsRevMap, nullable, firstpos, lastpos); query.accept(v5); Map<Entity, Set<Integer>> followpos = v5.getFollowPos(); // for(Entry<Entity, Set<Integer>> i: followpos.entrySet()){ // System.out.println(idsMap.get(i.getKey())+": "+i.getValue()); // } Set<AbstractCondition> vcs = new HashSet<AbstractCondition>(); Set<AbstractCondition> ecs = new HashSet<AbstractCondition>(); for(Entity e:idsMap.keySet()){ if(e instanceof Vertex){ for (AbstractCondition ac : e.getAbstractConditions()) { vcs.add(ac); } }else if(e instanceof Edge){ for (AbstractCondition ac : e.getAbstractConditions()) { ecs.add(ac); } } } if(!vcs.contains(NoRestriction.I)){ vcs.add(NoRestriction.I); } if(!ecs.contains(NoRestriction.I)){ ecs.add(NoRestriction.I); } AbstractCondition[] valphabet = SortConditions.sortConditions(vcs.toArray(new AbstractCondition[0])); AbstractCondition[] ealphabet = SortConditions.sortConditions(ecs.toArray(new AbstractCondition[0])); // for (int i = 0; i < valphabet.length; i++) { // System.out.println("v["+i+"]\t"+valphabet[i]); // } // for (int i = 0; i < valphabet.length; i++) { // System.out.println("e["+i+"]\t"+ealphabet[i]); // } Set<SimpleState> openStates = new HashSet<SimpleState>(); Set<SimpleState> closedStates = new HashSet<SimpleState>(); Integer successPos = idsMap.get(((Query)query).getEOF()); Set<Integer> start = firstpos.get(query); SimpleState startState = new SimpleState(start, true, false); openStates.add(startState); SimpleStateMachineWithData<SimpleState> stm = new SimpleStateMachineWithData<SimpleState>(ealphabet, valphabet); stm.addState(startState, startState.isSuccess()); while(!openStates.isEmpty()){ SimpleState one = openStates.iterator().next(); openStates.remove(one); closedStates.add(one); AbstractCondition[] alphabet = one.isVertex()?valphabet:ealphabet; for(int i=0; i<alphabet.length; i++){ Set<Integer> next = new HashSet<Integer>(); AbstractCondition input = alphabet[i]; boolean isSuccess = false; //for(Entry<Integer, AbstractCondition[]> ec:condMap.entrySet()){ for(Integer inpos:one.pos){ AbstractCondition[] conds=condMap.get(inpos); boolean satisfy=true; for(AbstractCondition ac:conds){ if(!input.require(ac)){ satisfy = false; break; } } if(satisfy){ Set<Integer> follows = followpos.get(idsRevMap.get(inpos)); if(follows.contains(successPos)){ for (Integer integer : follows) { if(!integer.equals(successPos)){ next.add(integer); } } isSuccess = true; }else{ next.addAll(follows); } } } if(next.size()>0||isSuccess){ SimpleState nextState = new SimpleState(next, !one.isVertex(), isSuccess); int n; if((n=stm.findState(nextState))<0){ openStates.add(nextState); n=stm.addState(nextState, nextState.isSuccess()); } stm.addTransition(stm.findState(one), n, i, one.isVertex()); } } } SimpleStateMachine rstm = stm.removeData(); rstm.minimize(); return rstm; } }