165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/* 265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project 365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License"); 565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License. 665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at 765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * http://www.apache.org/licenses/LICENSE-2.0 965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software 1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS, 1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and 1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License. 1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpackage android.filterfw.io; 1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.lang.Float; 2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.lang.Integer; 2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.lang.String; 2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.ArrayList; 2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.regex.Pattern; 2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.Filter; 2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FilterFactory; 2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FilterGraph; 3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.KeyValueMap; 3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.ProtocolException; 3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.io.GraphReader; 3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.io.GraphIOException; 3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.io.PatternScanner; 3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/** 3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @hide 3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class TextGraphReader extends GraphReader { 4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private ArrayList<Command> mCommands = new ArrayList<Command>(); 4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private Filter mCurrentFilter; 4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private FilterGraph mCurrentGraph; 4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private KeyValueMap mBoundReferences; 4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private KeyValueMap mSettings; 4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private FilterFactory mFactory; 4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private interface Command { 4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void execute(TextGraphReader reader) throws GraphIOException; 5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private class ImportPackageCommand implements Command { 5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private String mPackageName; 5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public ImportPackageCommand(String packageName) { 5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mPackageName = packageName; 5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void execute(TextGraphReader reader) throws GraphIOException { 6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn try { 6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reader.mFactory.addPackage(mPackageName); 6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } catch (IllegalArgumentException e) { 6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException(e.getMessage()); 6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private class AddLibraryCommand implements Command { 7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private String mLibraryName; 7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public AddLibraryCommand(String libraryName) { 7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mLibraryName = libraryName; 7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void execute(TextGraphReader reader) { 7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reader.mFactory.addFilterLibrary(mLibraryName); 7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private class AllocateFilterCommand implements Command { 8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private String mClassName; 8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private String mFilterName; 8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public AllocateFilterCommand(String className, String filterName) { 8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mClassName = className; 8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mFilterName = filterName; 8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void execute(TextGraphReader reader) throws GraphIOException { 9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Create the filter 9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Filter filter = null; 9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn try { 9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn filter = reader.mFactory.createFilterByClassName(mClassName, mFilterName); 9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } catch (IllegalArgumentException e) { 9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException(e.getMessage()); 9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Set it as the current filter 10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reader.mCurrentFilter = filter; 10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private class InitFilterCommand implements Command { 10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private KeyValueMap mParams; 10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public InitFilterCommand(KeyValueMap params) { 10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mParams = params; 11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void execute(TextGraphReader reader) throws GraphIOException { 11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Filter filter = reader.mCurrentFilter; 11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn try { 11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn filter.initWithValueMap(mParams); 11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } catch (ProtocolException e) { 11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException(e.getMessage()); 11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reader.mCurrentGraph.addFilter(mCurrentFilter); 12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private class ConnectCommand implements Command { 12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private String mSourceFilter; 12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private String mSourcePort; 12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private String mTargetFilter; 12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private String mTargetName; 12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public ConnectCommand(String sourceFilter, 13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String sourcePort, 13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String targetFilter, 13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String targetName) { 13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mSourceFilter = sourceFilter; 13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mSourcePort = sourcePort; 13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mTargetFilter = targetFilter; 13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mTargetName = targetName; 13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void execute(TextGraphReader reader) { 14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reader.mCurrentGraph.connect(mSourceFilter, mSourcePort, mTargetFilter, mTargetName); 14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public FilterGraph readGraphString(String graphString) throws GraphIOException { 14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn FilterGraph result = new FilterGraph(); 14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reset(); 15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCurrentGraph = result; 15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn parseString(graphString); 15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn applySettings(); 15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn executeCommands(); 15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reset(); 15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void reset() { 16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCurrentGraph = null; 16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCurrentFilter = null; 16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCommands.clear(); 16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mBoundReferences = new KeyValueMap(); 16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mSettings = new KeyValueMap(); 16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mFactory = new FilterFactory(); 16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void parseString(String graphString) throws GraphIOException { 17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern commandPattern = Pattern.compile("@[a-zA-Z]+"); 17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern curlyClosePattern = Pattern.compile("\\}"); 17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern curlyOpenPattern = Pattern.compile("\\{"); 17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern ignorePattern = Pattern.compile("(\\s+|//[^\\n]*\\n)+"); 17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern packageNamePattern = Pattern.compile("[a-zA-Z\\.]+"); 17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern libraryNamePattern = Pattern.compile("[a-zA-Z\\./:]+"); 17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern portPattern = Pattern.compile("\\[[a-zA-Z0-9\\-_]+\\]"); 17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern rightArrowPattern = Pattern.compile("=>"); 17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern semicolonPattern = Pattern.compile(";"); 17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern wordPattern = Pattern.compile("[a-zA-Z0-9\\-_]+"); 18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_COMMAND = 0; 18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_IMPORT_PKG = 1; 18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_ADD_LIBRARY = 2; 18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_FILTER_CLASS = 3; 18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_FILTER_NAME = 4; 18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_CURLY_OPEN = 5; 18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_PARAMETERS = 6; 18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_CURLY_CLOSE = 7; 18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_SOURCE_FILTERNAME = 8; 19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_SOURCE_PORT = 9; 19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_RIGHT_ARROW = 10; 19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_TARGET_FILTERNAME = 11; 19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_TARGET_PORT = 12; 19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_ASSIGNMENT = 13; 19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_EXTERNAL = 14; 19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_SETTING = 15; 19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_SEMICOLON = 16; 19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int state = STATE_COMMAND; 20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn PatternScanner scanner = new PatternScanner(graphString, ignorePattern); 20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String curClassName = null; 20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String curSourceFilterName = null; 20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String curSourcePortName = null; 20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String curTargetFilterName = null; 20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String curTargetPortName = null; 20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // State machine main loop 20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn while (!scanner.atEnd()) { 21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn switch (state) { 21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_COMMAND: { 21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String curCommand = scanner.eat(commandPattern, "<command>"); 21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (curCommand.equals("@import")) { 21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_IMPORT_PKG; 21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (curCommand.equals("@library")) { 21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_ADD_LIBRARY; 21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (curCommand.equals("@filter")) { 21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_FILTER_CLASS; 21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (curCommand.equals("@connect")) { 22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_SOURCE_FILTERNAME; 22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (curCommand.equals("@set")) { 22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_ASSIGNMENT; 22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (curCommand.equals("@external")) { 22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_EXTERNAL; 22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (curCommand.equals("@setting")) { 22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_SETTING; 22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException("Unknown command '" + curCommand + "'!"); 22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_IMPORT_PKG: { 23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String packageName = scanner.eat(packageNamePattern, "<package-name>"); 23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCommands.add(new ImportPackageCommand(packageName)); 23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_SEMICOLON; 23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_ADD_LIBRARY: { 24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String libraryName = scanner.eat(libraryNamePattern, "<library-name>"); 24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCommands.add(new AddLibraryCommand(libraryName)); 24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_SEMICOLON; 24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_FILTER_CLASS: 24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn curClassName = scanner.eat(wordPattern, "<class-name>"); 24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_FILTER_NAME; 25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_FILTER_NAME: { 25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String curFilterName = scanner.eat(wordPattern, "<filter-name>"); 25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCommands.add(new AllocateFilterCommand(curClassName, curFilterName)); 25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_CURLY_OPEN; 25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_CURLY_OPEN: 26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn scanner.eat(curlyOpenPattern, "{"); 26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_PARAMETERS; 26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 26465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_PARAMETERS: { 26565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn KeyValueMap params = readKeyValueAssignments(scanner, curlyClosePattern); 26665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCommands.add(new InitFilterCommand(params)); 26765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_CURLY_CLOSE; 26865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 26965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 27065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 27165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_CURLY_CLOSE: 27265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn scanner.eat(curlyClosePattern, "}"); 27365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_COMMAND; 27465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 27565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 27665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_SOURCE_FILTERNAME: 27765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn curSourceFilterName = scanner.eat(wordPattern, "<source-filter-name>"); 27865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_SOURCE_PORT; 27965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 28065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 28165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_SOURCE_PORT: { 28265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String portString = scanner.eat(portPattern, "[<source-port-name>]"); 28365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn curSourcePortName = portString.substring(1, portString.length() - 1); 28465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_RIGHT_ARROW; 28565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 28665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 28765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 28865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_RIGHT_ARROW: 28965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn scanner.eat(rightArrowPattern, "=>"); 29065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_TARGET_FILTERNAME; 29165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 29265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 29365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_TARGET_FILTERNAME: 29465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn curTargetFilterName = scanner.eat(wordPattern, "<target-filter-name>"); 29565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_TARGET_PORT; 29665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 29765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 29865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_TARGET_PORT: { 29965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String portString = scanner.eat(portPattern, "[<target-port-name>]"); 30065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn curTargetPortName = portString.substring(1, portString.length() - 1); 30165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCommands.add(new ConnectCommand(curSourceFilterName, 30265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn curSourcePortName, 30365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn curTargetFilterName, 30465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn curTargetPortName)); 30565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_SEMICOLON; 30665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 30765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 30865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 30965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_ASSIGNMENT: { 31065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn KeyValueMap assignment = readKeyValueAssignments(scanner, semicolonPattern); 31165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mBoundReferences.putAll(assignment); 31265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_SEMICOLON; 31365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 31465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 31565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 31665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_EXTERNAL: { 31765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String externalName = scanner.eat(wordPattern, "<external-identifier>"); 31865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn bindExternal(externalName); 31965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_SEMICOLON; 32065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 32165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 32265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 32365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_SETTING: { 32465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn KeyValueMap setting = readKeyValueAssignments(scanner, semicolonPattern); 32565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mSettings.putAll(setting); 32665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_SEMICOLON; 32765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 32865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 32965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 33065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_SEMICOLON: 33165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn scanner.eat(semicolonPattern, ";"); 33265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_COMMAND; 33365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 33465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 33565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 33665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 33765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure end of input was expected 33865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (state != STATE_SEMICOLON && state != STATE_COMMAND) { 33965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException("Unexpected end of input!"); 34065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 34165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 34265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 34365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 34465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public KeyValueMap readKeyValueAssignments(String assignments) throws GraphIOException { 34565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern ignorePattern = Pattern.compile("\\s+"); 34665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn PatternScanner scanner = new PatternScanner(assignments, ignorePattern); 34765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return readKeyValueAssignments(scanner, null); 34865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 34965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 35065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private KeyValueMap readKeyValueAssignments(PatternScanner scanner, 35165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Pattern endPattern) throws GraphIOException { 35265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Our parser is a state-machine, and these are our states 35365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_IDENTIFIER = 0; 35465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_EQUALS = 1; 35565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_VALUE = 2; 35665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final int STATE_POST_VALUE = 3; 35765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 35865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern equalsPattern = Pattern.compile("="); 35965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern semicolonPattern = Pattern.compile(";"); 36065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern wordPattern = Pattern.compile("[a-zA-Z]+[a-zA-Z0-9]*"); 36165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern stringPattern = Pattern.compile("'[^']*'|\\\"[^\\\"]*\\\""); 36265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern intPattern = Pattern.compile("[0-9]+"); 36365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern floatPattern = Pattern.compile("[0-9]*\\.[0-9]+f?"); 36465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern referencePattern = Pattern.compile("\\$[a-zA-Z]+[a-zA-Z0-9]"); 36565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final Pattern booleanPattern = Pattern.compile("true|false"); 36665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 36765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int state = STATE_IDENTIFIER; 36865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn KeyValueMap newVals = new KeyValueMap(); 36965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String curKey = null; 37065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String curValue = null; 37165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 37265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn while (!scanner.atEnd() && !(endPattern != null && scanner.peek(endPattern))) { 37365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn switch (state) { 37465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_IDENTIFIER: 37565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn curKey = scanner.eat(wordPattern, "<identifier>"); 37665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_EQUALS; 37765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 37865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 37965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_EQUALS: 38065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn scanner.eat(equalsPattern, "="); 38165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_VALUE; 38265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 38365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 38465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_VALUE: 38565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if ((curValue = scanner.tryEat(stringPattern)) != null) { 38665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn newVals.put(curKey, curValue.substring(1, curValue.length() - 1)); 38765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if ((curValue = scanner.tryEat(referencePattern)) != null) { 38865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn String refName = curValue.substring(1, curValue.length()); 38965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Object referencedObject = mBoundReferences != null 39065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ? mBoundReferences.get(refName) 39165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : null; 39265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (referencedObject == null) { 39365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException( 39465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "Unknown object reference to '" + refName + "'!"); 39565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 39665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn newVals.put(curKey, referencedObject); 39765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if ((curValue = scanner.tryEat(booleanPattern)) != null) { 39865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn newVals.put(curKey, Boolean.parseBoolean(curValue)); 39965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if ((curValue = scanner.tryEat(floatPattern)) != null) { 40065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn newVals.put(curKey, Float.parseFloat(curValue)); 40165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if ((curValue = scanner.tryEat(intPattern)) != null) { 40265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn newVals.put(curKey, Integer.parseInt(curValue)); 40365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 40465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException(scanner.unexpectedTokenMessage("<value>")); 40565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 40665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_POST_VALUE; 40765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 40865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 40965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case STATE_POST_VALUE: 41065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn scanner.eat(semicolonPattern, ";"); 41165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn state = STATE_IDENTIFIER; 41265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 41365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 41465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 41565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 41665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure end is expected 41765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (state != STATE_IDENTIFIER && state != STATE_POST_VALUE) { 41865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException( 41965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "Unexpected end of assignments on line " + scanner.lineNo() + "!"); 42065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 42165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 42265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return newVals; 42365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 42465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 42565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void bindExternal(String name) throws GraphIOException { 42665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (mReferences.containsKey(name)) { 42765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Object value = mReferences.get(name); 42865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mBoundReferences.put(name, value); 42965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 43065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException("Unknown external variable '" + name + "'! " 43165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn + "You must add a reference to this external in the host program using " 43265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn + "addReference(...)!"); 43365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 43465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 43565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 43665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** 43765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unused for now: Often you may want to declare references that are NOT in a certain graph, 43865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * e.g. when reading multiple graphs with the same reader. We could print a warning, but even 43965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * that may be too much. 44065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn **/ 44165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void checkReferences() throws GraphIOException { 44265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (String reference : mReferences.keySet()) { 44365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!mBoundReferences.containsKey(reference)) { 44465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException( 44565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "Host program specifies reference to '" + reference + "', which is not " 44665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn + "declared @external in graph file!"); 44765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 44865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 44965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 45065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 45165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void applySettings() throws GraphIOException { 45265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (String setting : mSettings.keySet()) { 45365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Object value = mSettings.get(setting); 45465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (setting.equals("autoBranch")) { 45565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn expectSettingClass(setting, value, String.class); 45665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (value.equals("synced")) { 45765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCurrentGraph.setAutoBranchMode(FilterGraph.AUTOBRANCH_SYNCED); 45865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (value.equals("unsynced")) { 45965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCurrentGraph.setAutoBranchMode(FilterGraph.AUTOBRANCH_UNSYNCED); 46065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (value.equals("off")) { 46165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCurrentGraph.setAutoBranchMode(FilterGraph.AUTOBRANCH_OFF); 46265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 46365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException("Unknown autobranch setting: " + value + "!"); 46465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 46565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (setting.equals("discardUnconnectedOutputs")) { 46665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn expectSettingClass(setting, value, Boolean.class); 46765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mCurrentGraph.setDiscardUnconnectedOutputs((Boolean)value); 46865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 46965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException("Unknown @setting '" + setting + "'!"); 47065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 47165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 47265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 47365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 47465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void expectSettingClass(String setting, 47565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Object value, 47665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Class expectedClass) throws GraphIOException { 47765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (value.getClass() != expectedClass) { 47865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new GraphIOException("Setting '" + setting + "' must have a value of type " 47965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn + expectedClass.getSimpleName() + ", but found a value of type " 48065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn + value.getClass().getSimpleName() + "!"); 48165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 48265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 48365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 48465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void executeCommands() throws GraphIOException { 48565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (Command command : mCommands) { 48665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn command.execute(this); 48765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 48865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 48965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 490