FileDocCategorySizeDatePackage
TextGraphReader.javaAPI DocAndroid 5.1 API19543Thu Mar 12 22:22:30 GMT 2015android.filterfw.io

TextGraphReader

public class TextGraphReader extends android.filterfw.io.GraphReader
hide

Fields Summary
private ArrayList
mCommands
private android.filterfw.core.Filter
mCurrentFilter
private android.filterfw.core.FilterGraph
mCurrentGraph
private android.filterfw.core.KeyValueMap
mBoundReferences
private android.filterfw.core.KeyValueMap
mSettings
private android.filterfw.core.FilterFactory
mFactory
Constructors Summary
Methods Summary
private voidapplySettings()

        for (String setting : mSettings.keySet()) {
            Object value = mSettings.get(setting);
            if (setting.equals("autoBranch")) {
                expectSettingClass(setting, value, String.class);
                if (value.equals("synced")) {
                    mCurrentGraph.setAutoBranchMode(FilterGraph.AUTOBRANCH_SYNCED);
                } else if (value.equals("unsynced")) {
                    mCurrentGraph.setAutoBranchMode(FilterGraph.AUTOBRANCH_UNSYNCED);
                } else if (value.equals("off")) {
                    mCurrentGraph.setAutoBranchMode(FilterGraph.AUTOBRANCH_OFF);
                } else {
                    throw new GraphIOException("Unknown autobranch setting: " + value + "!");
                }
            } else if (setting.equals("discardUnconnectedOutputs")) {
                expectSettingClass(setting, value, Boolean.class);
                mCurrentGraph.setDiscardUnconnectedOutputs((Boolean)value);
            } else {
                throw new GraphIOException("Unknown @setting '" + setting + "'!");
            }
        }
    
private voidbindExternal(java.lang.String name)

        if (mReferences.containsKey(name)) {
            Object value = mReferences.get(name);
            mBoundReferences.put(name, value);
        } else {
            throw new GraphIOException("Unknown external variable '" + name + "'! "
                + "You must add a reference to this external in the host program using "
                + "addReference(...)!");
        }
    
private voidcheckReferences()
Unused for now: Often you may want to declare references that are NOT in a certain graph, e.g. when reading multiple graphs with the same reader. We could print a warning, but even that may be too much.

        for (String reference : mReferences.keySet()) {
            if (!mBoundReferences.containsKey(reference)) {
                throw new GraphIOException(
                    "Host program specifies reference to '" + reference + "', which is not "
                    + "declared @external in graph file!");
            }
        }
    
private voidexecuteCommands()

        for (Command command : mCommands) {
            command.execute(this);
        }
    
private voidexpectSettingClass(java.lang.String setting, java.lang.Object value, java.lang.Class expectedClass)

        if (value.getClass() != expectedClass) {
            throw new GraphIOException("Setting '" + setting + "' must have a value of type "
                + expectedClass.getSimpleName() + ", but found a value of type "
                + value.getClass().getSimpleName() + "!");
        }
    
private voidparseString(java.lang.String graphString)

        final Pattern commandPattern = Pattern.compile("@[a-zA-Z]+");
        final Pattern curlyClosePattern = Pattern.compile("\\}");
        final Pattern curlyOpenPattern = Pattern.compile("\\{");
        final Pattern ignorePattern = Pattern.compile("(\\s+|//[^\\n]*\\n)+");
        final Pattern packageNamePattern = Pattern.compile("[a-zA-Z\\.]+");
        final Pattern libraryNamePattern = Pattern.compile("[a-zA-Z\\./:]+");
        final Pattern portPattern = Pattern.compile("\\[[a-zA-Z0-9\\-_]+\\]");
        final Pattern rightArrowPattern = Pattern.compile("=>");
        final Pattern semicolonPattern = Pattern.compile(";");
        final Pattern wordPattern = Pattern.compile("[a-zA-Z0-9\\-_]+");

        final int STATE_COMMAND           = 0;
        final int STATE_IMPORT_PKG        = 1;
        final int STATE_ADD_LIBRARY       = 2;
        final int STATE_FILTER_CLASS      = 3;
        final int STATE_FILTER_NAME       = 4;
        final int STATE_CURLY_OPEN        = 5;
        final int STATE_PARAMETERS        = 6;
        final int STATE_CURLY_CLOSE       = 7;
        final int STATE_SOURCE_FILTERNAME = 8;
        final int STATE_SOURCE_PORT       = 9;
        final int STATE_RIGHT_ARROW       = 10;
        final int STATE_TARGET_FILTERNAME = 11;
        final int STATE_TARGET_PORT       = 12;
        final int STATE_ASSIGNMENT        = 13;
        final int STATE_EXTERNAL          = 14;
        final int STATE_SETTING           = 15;
        final int STATE_SEMICOLON         = 16;

        int state = STATE_COMMAND;
        PatternScanner scanner = new PatternScanner(graphString, ignorePattern);

        String curClassName = null;
        String curSourceFilterName = null;
        String curSourcePortName = null;
        String curTargetFilterName = null;
        String curTargetPortName = null;

        // State machine main loop
        while (!scanner.atEnd()) {
            switch (state) {
                case STATE_COMMAND: {
                    String curCommand = scanner.eat(commandPattern, "<command>");
                    if (curCommand.equals("@import")) {
                        state = STATE_IMPORT_PKG;
                    } else if (curCommand.equals("@library")) {
                        state = STATE_ADD_LIBRARY;
                    } else if (curCommand.equals("@filter")) {
                        state = STATE_FILTER_CLASS;
                    } else if (curCommand.equals("@connect")) {
                        state = STATE_SOURCE_FILTERNAME;
                    } else if (curCommand.equals("@set")) {
                        state = STATE_ASSIGNMENT;
                    } else if (curCommand.equals("@external")) {
                        state = STATE_EXTERNAL;
                    } else if (curCommand.equals("@setting")) {
                        state = STATE_SETTING;
                    } else {
                        throw new GraphIOException("Unknown command '" + curCommand + "'!");
                    }
                    break;
                }

                case STATE_IMPORT_PKG: {
                    String packageName = scanner.eat(packageNamePattern, "<package-name>");
                    mCommands.add(new ImportPackageCommand(packageName));
                    state = STATE_SEMICOLON;
                    break;
                }

                case STATE_ADD_LIBRARY: {
                    String libraryName = scanner.eat(libraryNamePattern, "<library-name>");
                    mCommands.add(new AddLibraryCommand(libraryName));
                    state = STATE_SEMICOLON;
                    break;
                }

                case STATE_FILTER_CLASS:
                    curClassName = scanner.eat(wordPattern, "<class-name>");
                    state = STATE_FILTER_NAME;
                    break;

                case STATE_FILTER_NAME: {
                    String curFilterName = scanner.eat(wordPattern, "<filter-name>");
                    mCommands.add(new AllocateFilterCommand(curClassName, curFilterName));
                    state = STATE_CURLY_OPEN;
                    break;
                }

                case STATE_CURLY_OPEN:
                    scanner.eat(curlyOpenPattern, "{");
                    state = STATE_PARAMETERS;
                    break;

                case STATE_PARAMETERS: {
                    KeyValueMap params = readKeyValueAssignments(scanner, curlyClosePattern);
                    mCommands.add(new InitFilterCommand(params));
                    state = STATE_CURLY_CLOSE;
                    break;
                }

                case STATE_CURLY_CLOSE:
                    scanner.eat(curlyClosePattern, "}");
                    state = STATE_COMMAND;
                    break;

                case STATE_SOURCE_FILTERNAME:
                    curSourceFilterName = scanner.eat(wordPattern, "<source-filter-name>");
                    state = STATE_SOURCE_PORT;
                    break;

                case STATE_SOURCE_PORT: {
                    String portString = scanner.eat(portPattern, "[<source-port-name>]");
                    curSourcePortName = portString.substring(1, portString.length() - 1);
                    state = STATE_RIGHT_ARROW;
                    break;
                }

                case STATE_RIGHT_ARROW:
                    scanner.eat(rightArrowPattern, "=>");
                    state = STATE_TARGET_FILTERNAME;
                    break;

                case STATE_TARGET_FILTERNAME:
                    curTargetFilterName = scanner.eat(wordPattern, "<target-filter-name>");
                    state = STATE_TARGET_PORT;
                    break;

                case STATE_TARGET_PORT: {
                    String portString = scanner.eat(portPattern, "[<target-port-name>]");
                    curTargetPortName = portString.substring(1, portString.length() - 1);
                    mCommands.add(new ConnectCommand(curSourceFilterName,
                                                     curSourcePortName,
                                                     curTargetFilterName,
                                                     curTargetPortName));
                    state = STATE_SEMICOLON;
                    break;
                }

                case STATE_ASSIGNMENT: {
                    KeyValueMap assignment = readKeyValueAssignments(scanner, semicolonPattern);
                    mBoundReferences.putAll(assignment);
                    state = STATE_SEMICOLON;
                    break;
                }

                case STATE_EXTERNAL: {
                    String externalName = scanner.eat(wordPattern, "<external-identifier>");
                    bindExternal(externalName);
                    state = STATE_SEMICOLON;
                    break;
                }

                case STATE_SETTING: {
                    KeyValueMap setting = readKeyValueAssignments(scanner, semicolonPattern);
                    mSettings.putAll(setting);
                    state = STATE_SEMICOLON;
                    break;
                }

                case STATE_SEMICOLON:
                    scanner.eat(semicolonPattern, ";");
                    state = STATE_COMMAND;
                    break;
            }
        }

        // Make sure end of input was expected
        if (state != STATE_SEMICOLON && state != STATE_COMMAND) {
            throw new GraphIOException("Unexpected end of input!");
        }
    
public android.filterfw.core.FilterGraphreadGraphString(java.lang.String graphString)

        FilterGraph result = new FilterGraph();

        reset();
        mCurrentGraph = result;
        parseString(graphString);
        applySettings();
        executeCommands();
        reset();

        return result;
    
public android.filterfw.core.KeyValueMapreadKeyValueAssignments(java.lang.String assignments)

        final Pattern ignorePattern = Pattern.compile("\\s+");
        PatternScanner scanner = new PatternScanner(assignments, ignorePattern);
        return readKeyValueAssignments(scanner, null);
    
private android.filterfw.core.KeyValueMapreadKeyValueAssignments(android.filterfw.io.PatternScanner scanner, java.util.regex.Pattern endPattern)

        // Our parser is a state-machine, and these are our states
        final int STATE_IDENTIFIER = 0;
        final int STATE_EQUALS     = 1;
        final int STATE_VALUE      = 2;
        final int STATE_POST_VALUE = 3;

        final Pattern equalsPattern = Pattern.compile("=");
        final Pattern semicolonPattern = Pattern.compile(";");
        final Pattern wordPattern = Pattern.compile("[a-zA-Z]+[a-zA-Z0-9]*");
        final Pattern stringPattern = Pattern.compile("'[^']*'|\\\"[^\\\"]*\\\"");
        final Pattern intPattern = Pattern.compile("[0-9]+");
        final Pattern floatPattern = Pattern.compile("[0-9]*\\.[0-9]+f?");
        final Pattern referencePattern = Pattern.compile("\\$[a-zA-Z]+[a-zA-Z0-9]");
        final Pattern booleanPattern = Pattern.compile("true|false");

        int state = STATE_IDENTIFIER;
        KeyValueMap newVals = new KeyValueMap();
        String curKey = null;
        String curValue = null;

        while (!scanner.atEnd() && !(endPattern != null && scanner.peek(endPattern))) {
            switch (state) {
                case STATE_IDENTIFIER:
                    curKey = scanner.eat(wordPattern, "<identifier>");
                    state = STATE_EQUALS;
                    break;

                case STATE_EQUALS:
                    scanner.eat(equalsPattern, "=");
                    state = STATE_VALUE;
                    break;

                case STATE_VALUE:
                    if ((curValue = scanner.tryEat(stringPattern)) != null) {
                        newVals.put(curKey, curValue.substring(1, curValue.length() - 1));
                    } else if ((curValue = scanner.tryEat(referencePattern)) != null) {
                        String refName = curValue.substring(1, curValue.length());
                        Object referencedObject = mBoundReferences != null
                            ? mBoundReferences.get(refName)
                            : null;
                        if (referencedObject == null) {
                            throw new GraphIOException(
                                "Unknown object reference to '" + refName + "'!");
                        }
                        newVals.put(curKey, referencedObject);
                    } else if ((curValue = scanner.tryEat(booleanPattern)) != null) {
                        newVals.put(curKey, Boolean.parseBoolean(curValue));
                    } else if ((curValue = scanner.tryEat(floatPattern)) != null) {
                        newVals.put(curKey, Float.parseFloat(curValue));
                    } else if ((curValue = scanner.tryEat(intPattern)) != null) {
                        newVals.put(curKey, Integer.parseInt(curValue));
                    } else {
                        throw new GraphIOException(scanner.unexpectedTokenMessage("<value>"));
                    }
                    state = STATE_POST_VALUE;
                    break;

                case STATE_POST_VALUE:
                    scanner.eat(semicolonPattern, ";");
                    state = STATE_IDENTIFIER;
                    break;
            }
        }

        // Make sure end is expected
        if (state != STATE_IDENTIFIER && state != STATE_POST_VALUE) {
            throw new GraphIOException(
                "Unexpected end of assignments on line " + scanner.lineNo() + "!");
        }

        return newVals;
    
private voidreset()

        mCurrentGraph = null;
        mCurrentFilter = null;
        mCommands.clear();
        mBoundReferences = new KeyValueMap();
        mSettings = new KeyValueMap();
        mFactory = new FilterFactory();