package ru.csu.stan.java.cfg.automaton.base; import java.math.BigInteger; import ru.csu.stan.java.cfg.automaton.ControlFlowContext; import ru.csu.stan.java.cfg.jaxb.BaseCfgElement; import ru.csu.stan.java.cfg.jaxb.Flow; import ru.csu.stan.java.cfg.jaxb.Method; import ru.csu.stan.java.cfg.jaxb.Project; import ru.csu.stan.java.classgen.automaton.IContext; import ru.csu.stan.java.classgen.handlers.NodeAttributes; import ru.csu.stan.java.classgen.util.CompilationUnit; /** * Реализация базово-условного блока, который делает разветвление в графе потока управления. * Это могут быть условия, циклы итп. * * @author mz * * @param <T> конкретный тип блока */ public abstract class ControlFlowForkContextBase<T extends BaseCfgElement> extends ContextBase { private FlowCursor cursor; private T flowForkBlock; private CompilationUnit compilationUnit; private Method method; protected ControlFlowForkContextBase(ContextBase previousState, FlowCursor cursor, CompilationUnit compilationUnit, Method method) { super(previousState); this.cursor = cursor; this.compilationUnit = compilationUnit; this.method = method; } @Override public IContext<Project> getPreviousState(String eventName) { for (String tag: getTagNames()) if (tag.equals(eventName)) return getUpperState(); return this; } @Override public void processTag(String name, NodeAttributes attrs) { if (isEventFitToContext(name)){ makeFlowsToCurrent(); flowForkBlock = createFlowForkBlock(); flowForkBlock.setFromlineno(BigInteger.valueOf(attrs.getIntAttribute(NodeAttributes.LINE_ATTRIBUTE))); flowForkBlock.setColOffset(BigInteger.valueOf(attrs.getIntAttribute(NodeAttributes.COL_ATTRIBUTE))); flowForkBlock.setId(cursor.getCurrentIdBigInteger()); cursor.incrementCurrentId(); method.getTryExceptOrTryFinallyOrWith().add(flowForkBlock); } } protected abstract T createFlowForkBlock(); protected boolean isEventFitToContext(String eventName){ for (String tag: getTagNames()) if (tag.equals(eventName)) return true; return false; } protected abstract String[] getTagNames(); protected void makeFlowsToCurrent(){ makeFlowsFromCursorToId(cursor, cursor.getCurrentIdBigInteger()); } protected void makeFlowsFromCursorToId(FlowCursor flowCursor, BigInteger toId) { for (Integer parent: flowCursor.getParentIds()){ if (parent.intValue() > 0){ Flow flow = getObjectFactory().createFlow(); flow.setFromId(BigInteger.valueOf(parent.longValue())); flow.setToId(toId); method.getTryExceptOrTryFinallyOrWith().add(flow); } } } protected T getFlowForkBlock(){ return flowForkBlock; } protected FlowCursor getCursor(){ return cursor; } protected Method getMethod(){ return method; } protected CompilationUnit getCompilationUnit(){ return compilationUnit; } protected void addCursorDataToCurrent(FlowCursor additionCursor){ if (additionCursor != null){ for (Integer i: additionCursor.getParentIds()) cursor.addParentId(i.intValue()); cursor.setCurrentId(additionCursor.getCurrentId()); } } protected IContext<Project> createStandardControlFlowContext(final FlowCursor innerCursor){ cursor.clearParentIds(); innerCursor.setCurrentId(cursor.getCurrentId()); innerCursor.clearParentIds(); innerCursor.addParentId(flowForkBlock.getId().intValue()); return new ControlFlowContext(this, method, innerCursor, compilationUnit); } }