1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/*
2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2011 The Android Open Source Project
3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License");
5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License.
6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at
7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *      http://www.apache.org/licenses/LICENSE-2.0
9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software
11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS,
12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and
14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License.
15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw;
18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.text.TextUtils;
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.io.InputStream;
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.io.IOException;
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.io.StringReader;
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.ArrayList;
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport javax.xml.parsers.ParserConfigurationException;
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport javax.xml.parsers.SAXParser;
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport javax.xml.parsers.SAXParserFactory;
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport org.xml.sax.Attributes;
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport org.xml.sax.InputSource;
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport org.xml.sax.SAXException;
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport org.xml.sax.XMLReader;
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport org.xml.sax.helpers.DefaultHandler;
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/**
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * A GraphReader allows obtaining filter graphs from XML graph files or strings.
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class GraphReader {
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static interface Command {
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void execute(CommandStack stack);
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class CommandStack {
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private ArrayList<Command> mCommands = new ArrayList<Command>();
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private FilterGraph.Builder mBuilder;
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private FilterFactory mFactory;
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private MffContext mContext;
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public CommandStack(MffContext context) {
52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mContext = context;
53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBuilder = new FilterGraph.Builder(mContext);
54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mFactory = new FilterFactory();
55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void execute() {
58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            for (Command command : mCommands) {
59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                command.execute(this);
60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void append(Command command) {
64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mCommands.add(command);
65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public FilterFactory getFactory() {
68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mFactory;
69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public MffContext getContext() {
72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mContext;
73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected FilterGraph.Builder getBuilder() {
76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mBuilder;
77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class ImportPackageCommand implements Command {
81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mPackageName;
82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public ImportPackageCommand(String packageName) {
84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mPackageName = packageName;
85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void execute(CommandStack stack) {
89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            try {
90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                stack.getFactory().addPackage(mPackageName);
91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } catch (IllegalArgumentException e) {
92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException(e.getMessage());
93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class AddLibraryCommand implements Command {
98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mLibraryName;
99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public AddLibraryCommand(String libraryName) {
101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mLibraryName = libraryName;
102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void execute(CommandStack stack) {
106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            FilterFactory.addFilterLibrary(mLibraryName);
107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class AllocateFilterCommand implements Command {
111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mClassName;
112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mFilterName;
113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public AllocateFilterCommand(String className, String filterName) {
115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mClassName = className;
116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mFilterName = filterName;
117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
1208a985d24ce9a38f40ed88fecbdcd0e75e3a68f44John Spurlock        public void execute(CommandStack stack) {
121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Filter filter = null;
122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            try {
123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                filter = stack.getFactory().createFilterByClassName(mClassName,
124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                                                    mFilterName,
125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                                                    stack.getContext());
126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } catch (IllegalArgumentException e) {
127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("Error creating filter " + mFilterName + "!", e);
128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            stack.getBuilder().addFilter(filter);
130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class AddSourceSlotCommand implements Command {
134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mName;
135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mSlotName;
136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public AddSourceSlotCommand(String name, String slotName) {
138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mName = name;
139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mSlotName = slotName;
140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void execute(CommandStack stack) {
144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            stack.getBuilder().addFrameSlotSource(mName, mSlotName);
145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class AddTargetSlotCommand implements Command {
149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mName;
150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mSlotName;
151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public AddTargetSlotCommand(String name, String slotName) {
153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mName = name;
154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mSlotName = slotName;
155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void execute(CommandStack stack) {
159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            stack.getBuilder().addFrameSlotTarget(mName, mSlotName);
160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class AddVariableCommand implements Command {
164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mName;
165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private Object mValue;
166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public AddVariableCommand(String name, Object value) {
168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mName = name;
169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mValue = value;
170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void execute(CommandStack stack) {
174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            stack.getBuilder().addVariable(mName, mValue);
175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class SetFilterInputCommand implements Command {
179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mFilterName;
180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mFilterInput;
181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private Object mValue;
182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public SetFilterInputCommand(String filterName, String input, Object value) {
184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mFilterName = filterName;
185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mFilterInput = input;
186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mValue = value;
187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void execute(CommandStack stack) {
191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mValue instanceof Variable) {
192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String varName = ((Variable)mValue).name;
193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                stack.getBuilder().assignVariableToFilterInput(varName, mFilterName, mFilterInput);
194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else {
195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                stack.getBuilder().assignValueToFilterInput(mValue, mFilterName, mFilterInput);
196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class ConnectCommand implements Command {
201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mSourceFilter;
202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mSourcePort;
203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mTargetFilter;
204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private String mTargetPort;
205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public ConnectCommand(String sourceFilter,
207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                              String sourcePort,
208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                              String targetFilter,
209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                              String targetPort) {
210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mSourceFilter = sourceFilter;
211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mSourcePort = sourcePort;
212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mTargetFilter = targetFilter;
213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mTargetPort = targetPort;
214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void execute(CommandStack stack) {
218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            stack.getBuilder().connect(mSourceFilter, mSourcePort, mTargetFilter, mTargetPort);
219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class Variable {
223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public String name;
224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public Variable(String name) {
226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            this.name = name;
227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class XmlGraphReader {
231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private SAXParserFactory mParserFactory;
233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private static class GraphDataHandler extends DefaultHandler {
235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private CommandStack mCommandStack;
237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private boolean mInGraph = false;
238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private String mCurFilterName = null;
239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            public GraphDataHandler(CommandStack commandStack) {
241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCommandStack = commandStack;
242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            @Override
245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            public void startElement(String uri, String localName, String qName, Attributes attr)
246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    throws SAXException {
247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (localName.equals("graph")) {
248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    beginGraph();
249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else {
250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    assertInGraph(localName);
251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    if (localName.equals("import")) {
252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        addImportCommand(attr);
253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    } else if (localName.equals("library")) {
254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        addLibraryCommand(attr);
255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    } else if (localName.equals("connect")) {
256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        addConnectCommand(attr);
257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    } else if (localName.equals("var")) {
258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        addVarCommand(attr);
259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    } else if (localName.equals("filter")) {
260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        beginFilter(attr);
261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    } else if (localName.equals("input")) {
262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        addFilterInput(attr);
263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    } else {
264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        throw new SAXException("Unknown XML element '" + localName + "'!");
265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    }
266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            @Override
270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            public void endElement (String uri, String localName, String qName) {
271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (localName.equals("graph")) {
272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    endGraph();
273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else if (localName.equals("filter")) {
274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    endFilter();
275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private void addImportCommand(Attributes attributes) throws SAXException {
279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String packageName = getRequiredAttribute(attributes, "package");
280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCommandStack.append(new ImportPackageCommand(packageName));
281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private void addLibraryCommand(Attributes attributes) throws SAXException {
284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String libraryName = getRequiredAttribute(attributes, "name");
285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCommandStack.append(new AddLibraryCommand(libraryName));
286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private void addConnectCommand(Attributes attributes) {
289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String sourcePortName   = null;
290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String sourceFilterName = null;
291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String targetPortName   = null;
292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String targetFilterName = null;
293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                // check for shorthand: <connect source="filter:port" target="filter:port"/>
295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String sourceTag = attributes.getValue("source");
296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (sourceTag != null) {
297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    String[] sourceParts = sourceTag.split(":");
298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    if (sourceParts.length == 2) {
299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        sourceFilterName = sourceParts[0];
300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        sourcePortName   = sourceParts[1];
301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    } else {
302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        throw new RuntimeException(
303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                            "'source' tag needs to have format \"filter:port\"! " +
304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                            "Alternatively, you may use the form " +
305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                            "'sourceFilter=\"filter\" sourcePort=\"port\"'.");
306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    }
307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else {
308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    sourceFilterName = attributes.getValue("sourceFilter");
309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    sourcePortName   = attributes.getValue("sourcePort");
310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String targetTag = attributes.getValue("target");
313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (targetTag != null) {
314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    String[] targetParts = targetTag.split(":");
315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    if (targetParts.length == 2) {
316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        targetFilterName = targetParts[0];
317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        targetPortName   = targetParts[1];
318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    } else {
319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        throw new RuntimeException(
320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                            "'target' tag needs to have format \"filter:port\"! " +
321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                            "Alternatively, you may use the form " +
322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                            "'targetFilter=\"filter\" targetPort=\"port\"'.");
323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    }
324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else {
325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    targetFilterName = attributes.getValue("targetFilter");
326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    targetPortName   = attributes.getValue("targetPort");
327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String sourceSlotName = attributes.getValue("sourceSlot");
330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String targetSlotName = attributes.getValue("targetSlot");
331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (sourceSlotName != null) {
332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    sourceFilterName = "sourceSlot_" + sourceSlotName;
333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mCommandStack.append(new AddSourceSlotCommand(sourceFilterName,
334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                                                  sourceSlotName));
335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    sourcePortName = "frame";
336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (targetSlotName != null) {
338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    targetFilterName = "targetSlot_" + targetSlotName;
339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mCommandStack.append(new AddTargetSlotCommand(targetFilterName,
340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                                                  targetSlotName));
341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    targetPortName = "frame";
342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                assertValueNotNull("sourceFilter", sourceFilterName);
344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                assertValueNotNull("sourcePort", sourcePortName);
345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                assertValueNotNull("targetFilter", targetFilterName);
346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                assertValueNotNull("targetPort", targetPortName);
347227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                // TODO: Should slot connections auto-branch?
348227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCommandStack.append(new ConnectCommand(sourceFilterName,
349227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                                        sourcePortName,
350227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                                        targetFilterName,
351227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                                        targetPortName));
352227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
353227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
354227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private void addVarCommand(Attributes attributes) throws SAXException {
355227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String varName = getRequiredAttribute(attributes, "name");
356227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                Object varValue = getAssignmentValue(attributes);
357227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCommandStack.append(new AddVariableCommand(varName, varValue));
358227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
359227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
360227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private void beginGraph() throws SAXException {
361227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (mInGraph) {
362227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    throw new SAXException("Found more than one graph element in XML!");
363227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
364227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mInGraph = true;
365227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
366227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
367227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private void endGraph() {
368227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mInGraph = false;
369227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
370227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
371227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private void beginFilter(Attributes attributes) throws SAXException {
372227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String className = getRequiredAttribute(attributes, "class");
373227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCurFilterName = getRequiredAttribute(attributes, "name");
374227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCommandStack.append(new AllocateFilterCommand(className, mCurFilterName));
375227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
376227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
377227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private void endFilter() {
378227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCurFilterName = null;
379227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
380227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
381227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private void addFilterInput(Attributes attributes) throws SAXException {
382227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                // Make sure we are in a filter element
383227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (mCurFilterName == null) {
384227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    throw new SAXException("Found 'input' element outside of 'filter' "
385227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        + "element!");
386227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
387227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
388227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                // Get input name and value
389227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String inputName = getRequiredAttribute(attributes, "name");
390227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                Object inputValue = getAssignmentValue(attributes);
391227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (inputValue == null) {
392227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    throw new SAXException("No value specified for input '" + inputName + "' "
393227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        + "of filter '" + mCurFilterName + "'!");
394227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
395227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
396227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                // Push commmand
397227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCommandStack.append(new SetFilterInputCommand(mCurFilterName,
398227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                                               inputName,
399227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                                               inputValue));
400227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
401227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
402227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private void assertInGraph(String localName) throws SAXException {
403227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (!mInGraph) {
404227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    throw new SAXException("Encountered '" + localName + "' element outside of "
405227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        + "'graph' element!");
406227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
407227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
408227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
409227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private static Object getAssignmentValue(Attributes attributes) {
410227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String strValue = null;
411227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if ((strValue = attributes.getValue("stringValue")) != null) {
412227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return strValue;
413227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else if ((strValue = attributes.getValue("booleanValue")) != null) {
414227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return Boolean.parseBoolean(strValue);
415227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else if ((strValue = attributes.getValue("intValue")) != null) {
416227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return Integer.parseInt(strValue);
417227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else if ((strValue = attributes.getValue("floatValue")) != null) {
418227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return Float.parseFloat(strValue);
419227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else if ((strValue = attributes.getValue("floatsValue")) != null) {
420227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    String[] floatStrings = TextUtils.split(strValue, ",");
421227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    float[] result = new float[floatStrings.length];
422227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    for (int i = 0; i < floatStrings.length; ++i) {
423227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        result[i] = Float.parseFloat(floatStrings[i]);
424227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    }
425227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return result;
426227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else if ((strValue = attributes.getValue("varValue")) != null) {
427227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return new Variable(strValue);
428227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else {
429227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return null;
430227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
431227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
432227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
433227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private static String getRequiredAttribute(Attributes attributes, String name)
434227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    throws SAXException {
435227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                String result = attributes.getValue(name);
436227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (result == null) {
437227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    throw new SAXException("Required attribute '" + name + "' not found!");
438227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
439227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                return result;
440227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
441227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
442227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            private static void assertValueNotNull(String valueName, Object value) {
443227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (value == null) {
444227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    throw new NullPointerException("Required value '" + value + "' not specified!");
445227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
446227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
447227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
448227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
449227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
450227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public XmlGraphReader() {
451227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mParserFactory = SAXParserFactory.newInstance();
452227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
453227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
454227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void parseString(String graphString, CommandStack commandStack) throws IOException {
455227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            try {
456227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                XMLReader reader = getReaderForCommandStack(commandStack);
457227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                reader.parse(new InputSource(new StringReader(graphString)));
458227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } catch (SAXException e) {
459227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new IOException("XML parse error during graph parsing!", e);
460227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
461227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
462227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
463227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void parseInput(InputStream inputStream, CommandStack commandStack)
464227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throws IOException {
465227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            try {
466227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                XMLReader reader = getReaderForCommandStack(commandStack);
467227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                reader.parse(new InputSource(inputStream));
468227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } catch (SAXException e) {
469227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new IOException("XML parse error during graph parsing!", e);
470227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
471227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
472227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
473227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private XMLReader getReaderForCommandStack(CommandStack commandStack) throws IOException {
474227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            try {
475227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                SAXParser parser = mParserFactory.newSAXParser();
476227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                XMLReader reader = parser.getXMLReader();
477227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                GraphDataHandler graphHandler = new GraphDataHandler(commandStack);
478227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                reader.setContentHandler(graphHandler);
479227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                return reader;
480227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } catch (ParserConfigurationException e) {
481227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new IOException("Error creating SAXParser for graph parsing!", e);
482227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } catch (SAXException e) {
483227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new IOException("Error creating XMLReader for graph parsing!", e);
484227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
485227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
486227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
487227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
488227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
489227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Read an XML graph from a String.
490227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
491227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This function automatically checks each filters' signatures and throws a Runtime Exception
492227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * if required ports are unconnected. Use the 3-parameter version to avoid this behavior.
493227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
494227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param context the MffContext into which to load the graph.
495227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param xmlSource the graph specified in XML.
496227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the FilterGraph instance for the XML source.
497227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @throws IOException if there was an error parsing the source.
498227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
499227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static FilterGraph readXmlGraph(MffContext context, String xmlSource)
500227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throws IOException {
501227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FilterGraph.Builder builder = getBuilderForXmlString(context, xmlSource);
502227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return builder.build();
503227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
504227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
505227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
506227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Read an XML sub-graph from a String.
507227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
508227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param context the MffContext into which to load the graph.
509227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param xmlSource the graph specified in XML.
510227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param parentGraph the parent graph.
511227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the FilterGraph instance for the XML source.
512227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @throws IOException if there was an error parsing the source.
513227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
514227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static FilterGraph readXmlSubGraph(
515227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            MffContext context, String xmlSource, FilterGraph parentGraph)
516227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throws IOException {
517227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FilterGraph.Builder builder = getBuilderForXmlString(context, xmlSource);
518227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return builder.buildSubGraph(parentGraph);
519227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
520227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
521227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
522227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Read an XML graph from a resource.
523227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
524227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This function automatically checks each filters' signatures and throws a Runtime Exception
525227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * if required ports are unconnected. Use the 3-parameter version to avoid this behavior.
526227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
527227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param context the MffContext into which to load the graph.
528227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param resourceId the XML resource ID.
529227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the FilterGraph instance for the XML source.
530227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @throws IOException if there was an error reading or parsing the resource.
531227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
532227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static FilterGraph readXmlGraphResource(MffContext context, int resourceId)
533227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throws IOException {
534227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FilterGraph.Builder builder = getBuilderForXmlResource(context, resourceId);
535227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return builder.build();
536227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
537227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
538227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
539227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Read an XML graph from a resource.
540227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
541227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This function automatically checks each filters' signatures and throws a Runtime Exception
542227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * if required ports are unconnected. Use the 3-parameter version to avoid this behavior.
543227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
544227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param context the MffContext into which to load the graph.
545227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param resourceId the XML resource ID.
546227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the FilterGraph instance for the XML source.
547227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @throws IOException if there was an error reading or parsing the resource.
548227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
549227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static FilterGraph readXmlSubGraphResource(
550227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            MffContext context, int resourceId, FilterGraph parentGraph)
551227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throws IOException {
552227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FilterGraph.Builder builder = getBuilderForXmlResource(context, resourceId);
553227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return builder.buildSubGraph(parentGraph);
554227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
555227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
556227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static FilterGraph.Builder getBuilderForXmlString(MffContext context, String source)
557227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throws IOException {
558227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        XmlGraphReader reader = new XmlGraphReader();
559227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        CommandStack commands = new CommandStack(context);
560227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        reader.parseString(source, commands);
561227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        commands.execute();
562227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return commands.getBuilder();
563227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
564227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
565227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static FilterGraph.Builder getBuilderForXmlResource(MffContext context, int resourceId)
566227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throws IOException {
567227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        InputStream inputStream = context.getApplicationContext().getResources()
568227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                .openRawResource(resourceId);
569227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        XmlGraphReader reader = new XmlGraphReader();
570227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        CommandStack commands = new CommandStack(context);
571227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        reader.parseInput(inputStream, commands);
572227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        commands.execute();
573227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return commands.getBuilder();
574227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
575227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks}
576227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
577