You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by sh...@apache.org on 2016/02/08 23:18:36 UTC

airavata git commit: Implemented JsonWorkflowParser and added unit tests

Repository: airavata
Updated Branches:
  refs/heads/develop 54bb71925 -> 11ea5014a


Implemented JsonWorkflowParser and added unit tests


Project: http://git-wip-us.apache.org/repos/asf/airavata/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/11ea5014
Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/11ea5014
Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/11ea5014

Branch: refs/heads/develop
Commit: 11ea5014aaf16eadb02614aaa75cc2a18191d3e8
Parents: 54bb719
Author: Shameera Rathnayaka <sh...@gmail.com>
Authored: Mon Feb 8 17:18:20 2016 -0500
Committer: Shameera Rathnayaka <sh...@gmail.com>
Committed: Mon Feb 8 17:18:20 2016 -0500

----------------------------------------------------------------------
 modules/workflow/workflow-core/pom.xml          |   5 +
 .../airavata/workflow/core/WorkflowInfo.java    |  87 ++++
 .../workflow/core/dag/edge/DirectedEdge.java    |   4 +
 .../core/dag/nodes/ApplicationNode.java         |   5 +
 .../core/dag/nodes/ApplicationNodeImpl.java     |  11 +
 .../core/parser/JsonWorkflowParser.java         | 519 ++++++++++++++++++-
 .../workflow/core/parser/ParserException.java   |  40 ++
 .../workflow/core/parser/WorkflowParser.java    |   3 +-
 .../airavata/workflow/core/WorkflowDAGTest.java |  46 --
 .../core/parser/JsonWorkflowParserTest.java     |  83 ++-
 .../src/test/resources/TestWorkflow.json        |   8 +-
 11 files changed, 738 insertions(+), 73 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/pom.xml
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/pom.xml b/modules/workflow/workflow-core/pom.xml
index 72990c8..51d7735 100644
--- a/modules/workflow/workflow-core/pom.xml
+++ b/modules/workflow/workflow-core/pom.xml
@@ -37,6 +37,11 @@
             <artifactId>airavata-gfac-core</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.4</version>
+        </dependency>
         <!-- Airavata default parser dependency -->
         <dependency>
             <groupId>org.apache.airavata</groupId>

http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/WorkflowInfo.java
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/WorkflowInfo.java b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/WorkflowInfo.java
new file mode 100644
index 0000000..a0dd859
--- /dev/null
+++ b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/WorkflowInfo.java
@@ -0,0 +1,87 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.airavata.workflow.core;
+
+public class WorkflowInfo {
+    private String name;
+    private String id;
+    private String description;
+    private String version;
+    private int applicationCount;
+    private int inputCount;
+    private int outputCount;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public int getApplicationCount() {
+        return applicationCount;
+    }
+
+    public void setApplicationCount(int applicationCount) {
+        this.applicationCount = applicationCount;
+    }
+
+    public int getInputCount() {
+        return inputCount;
+    }
+
+    public void setInputCount(int inputCount) {
+        this.inputCount = inputCount;
+    }
+
+    public int getOutputCount() {
+        return outputCount;
+    }
+
+    public void setOutputCount(int outputCount) {
+        this.outputCount = outputCount;
+    }
+}

http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/edge/DirectedEdge.java
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/edge/DirectedEdge.java b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/edge/DirectedEdge.java
index 3ad7afa..e8b7f07 100644
--- a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/edge/DirectedEdge.java
+++ b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/edge/DirectedEdge.java
@@ -32,6 +32,10 @@ public class DirectedEdge implements Edge {
     private OutPort outPort;
     private EdgeModel edgeModel;
 
+    public DirectedEdge(EdgeModel edgeModel) {
+        this.edgeModel = edgeModel;
+    }
+
     @Override
     public String getId() {
         return getEdgeModel().getEdgeId();

http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/nodes/ApplicationNode.java
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/nodes/ApplicationNode.java b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/nodes/ApplicationNode.java
index ab876cc..00eccb0 100644
--- a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/nodes/ApplicationNode.java
+++ b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/nodes/ApplicationNode.java
@@ -24,6 +24,7 @@ package org.apache.airavata.workflow.core.dag.nodes;
 import org.apache.airavata.workflow.core.dag.port.InPort;
 import org.apache.airavata.workflow.core.dag.port.OutPort;
 
+import java.util.Collection;
 import java.util.List;
 
 public interface ApplicationNode extends WorkflowNode {
@@ -40,4 +41,8 @@ public interface ApplicationNode extends WorkflowNode {
 
     public List<OutPort> getOutputPorts();
 
+    public void addInputPorts(Collection<? extends InPort> inPorts);
+
+    public void addOutPorts(Collection<? extends OutPort> outPorts);
+
 }

http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/nodes/ApplicationNodeImpl.java
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/nodes/ApplicationNodeImpl.java b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/nodes/ApplicationNodeImpl.java
index adc865f..cedf657 100644
--- a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/nodes/ApplicationNodeImpl.java
+++ b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/dag/nodes/ApplicationNodeImpl.java
@@ -28,6 +28,7 @@ import org.apache.airavata.workflow.core.dag.port.InPort;
 import org.apache.airavata.workflow.core.dag.port.OutPort;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 public class ApplicationNodeImpl implements ApplicationNode {
@@ -119,4 +120,14 @@ public class ApplicationNodeImpl implements ApplicationNode {
     public List<OutPort> getOutputPorts() {
         return this.outPorts;
     }
+
+    @Override
+    public void addInputPorts(Collection<? extends InPort> inPorts) {
+        this.inPorts.addAll(inPorts);
+    }
+
+    @Override
+    public void addOutPorts(Collection<? extends OutPort> outPorts) {
+        this.outPorts.addAll(outPorts);
+    }
 }

http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/JsonWorkflowParser.java
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/JsonWorkflowParser.java b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/JsonWorkflowParser.java
index f6bb084..7484f7e 100644
--- a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/JsonWorkflowParser.java
+++ b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/JsonWorkflowParser.java
@@ -22,63 +22,485 @@
 package org.apache.airavata.workflow.core.parser;
 
 import com.google.gson.JsonObject;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.airavata.model.EdgeModel;
+import org.apache.airavata.model.NodeModel;
+import org.apache.airavata.model.PortModel;
+import org.apache.airavata.workflow.core.WorkflowInfo;
+import org.apache.airavata.workflow.core.dag.edge.DirectedEdge;
 import org.apache.airavata.workflow.core.dag.edge.Edge;
 import org.apache.airavata.workflow.core.dag.nodes.ApplicationNode;
+import org.apache.airavata.workflow.core.dag.nodes.ApplicationNodeImpl;
 import org.apache.airavata.workflow.core.dag.nodes.InputNode;
+import org.apache.airavata.workflow.core.dag.nodes.InputNodeImpl;
 import org.apache.airavata.workflow.core.dag.nodes.OutputNode;
+import org.apache.airavata.workflow.core.dag.nodes.OutputNodeImpl;
+import org.apache.airavata.workflow.core.dag.nodes.WorkflowNode;
+import org.apache.airavata.workflow.core.dag.port.InPort;
+import org.apache.airavata.workflow.core.dag.port.InputPortIml;
+import org.apache.airavata.workflow.core.dag.port.OutPort;
+import org.apache.airavata.workflow.core.dag.port.OutPortImpl;
 import org.apache.airavata.workflow.core.dag.port.Port;
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 public class JsonWorkflowParser implements WorkflowParser {
 
-    private final String workflow;
+    private final JsonReader jsonReader;
+
     private List<InputNode> inputs;
     private List<OutputNode> outputs;
     private List<ApplicationNode> applications;
+    private Map<String, WorkflowNode> nodeMap;
     private List<Port> ports;
     private List<Edge> edges;
+    private List<Link> links;
+    private WorkflowInfo workflowInfo;
 
     public JsonWorkflowParser(String jsonWorkflowString) {
-        workflow = jsonWorkflowString;
+        this(new ByteArrayInputStream(jsonWorkflowString.getBytes()));
+    }
 
+    public JsonWorkflowParser(InputStream inputStream) {
+        this(new InputStreamReader(inputStream));
+    }
+
+    public JsonWorkflowParser(InputStreamReader inputStreamReader) {
+        this(new JsonReader(inputStreamReader));
+    }
+
+    public JsonWorkflowParser(JsonReader jsonReader) {
+        this.jsonReader = jsonReader;
+        init();
+    }
+
+    private void init() {
+        applications = new ArrayList<>();
+        nodeMap = new HashMap<>();
         inputs = new ArrayList<>();
         outputs = new ArrayList<>();
-        applications = new ArrayList<>();
-        ports = new ArrayList<>();
-        edges = new ArrayList<>();
+        links = new ArrayList<>();
+        workflowInfo = new WorkflowInfo();
+
     }
 
 
     @Override
-    public void parse() throws Exception {
+    public WorkflowInfo parse() throws Exception {
         // TODO parse json string and construct components
+        if (jsonReader.peek() != JsonToken.BEGIN_OBJECT) {
+            throw new Exception("Invalid Json data expected beginObject but found " + getTokenString(jsonReader.peek()));
+        }
+        jsonReader.beginObject();
+        while (jsonReader.hasNext()) {
+            String name = jsonReader.nextName(); // workflow
+            if (name.equals(WORKFLOW)) {
+                readWorkflowInfo(jsonReader);
+            } else {
+                jsonReader.skipValue();
+            }
+        }
+        jsonReader.endObject();
+
+        buildWorkflowDAG();
+        return workflowInfo;
+    }
+
+    private void buildWorkflowDAG() {
+        // TODO construct runtime model
+
+    }
+
+    private void readWorkflowInfo(JsonReader jsonReader) throws IOException, ParserException {
+        jsonReader.beginObject();
+        String name;
+        while (jsonReader.hasNext()) {
+            name = jsonReader.nextName();
+            if (name.equals(NAME)) {
+                workflowInfo.setName(jsonReader.nextString());
+            } else if (name.equals(ID)) {
+                workflowInfo.setId(jsonReader.nextString());
+            } else if (name.equals(DESCRIPTION)) {
+                workflowInfo.setDescription(jsonReader.nextString());
+            } else if (name.equals(VERSION)) {
+                workflowInfo.setVersion(jsonReader.nextString());
+            } else if (name.equals(APPLICATIONS)) {
+                readApplications(jsonReader);
+            } else if (name.equals(WORKFLOW_INPUTS)) {
+                readWorkflowInputs(jsonReader);
+            } else if (name.equals(WORKFLOW_OUTPUTS)) {
+                readWorkflowOutputs(jsonReader);
+            } else if (name.equals(LINKS)) {
+                readWorkflowLinks(jsonReader);
+            } else {
+                jsonReader.skipValue();
+            }
+        }
+        jsonReader.endObject();
+        //TODO: set count properties of workflow info object
+    }
+
+    private void readApplications(JsonReader jsonReader) throws IOException, ParserException {
+        jsonReader.beginArray();
+        ApplicationNode appNode = null;
+        while (jsonReader.hasNext()) {
+            appNode = readApplication(jsonReader);
+            applications.add(appNode);
+        }
+        jsonReader.endArray();
+    }
+
+    private void readWorkflowInputs(JsonReader jsonReader) throws ParserException, IOException {
+        JsonToken peek = jsonReader.peek();
+        InputNode inputNode;
+        NodeModel nodeModel;
+        String name;
+        if (peek == JsonToken.NULL) {
+            throw new ParserException("Error! workflow inputs can't be null");
+        } else if (peek == JsonToken.BEGIN_ARRAY) {
+            jsonReader.beginArray();
+            while (jsonReader.hasNext()) {
+                jsonReader.beginObject();
+                nodeModel = new NodeModel();
+                inputNode = new InputNodeImpl(nodeModel);
+                while (jsonReader.hasNext()) {
+                    name = jsonReader.nextName();
+                    if (name.equals(NAME)) {
+                        nodeModel.setName(jsonReader.nextString());
+                    } else if (name.equals(ID)) {
+                        nodeModel.setNodeId(jsonReader.nextString());
+                    } else if (name.equals(DATATYPE)) {
+                        jsonReader.skipValue();
+                    } else if (name.equals(DESCRIPTION)) {
+                        nodeModel.setDescription(jsonReader.nextString());
+                    } else if (name.equals(POSITION)) {
+                        readPosition(jsonReader);
+                    } else if (name.equals(NODE_ID)) {
+                        nodeModel.setNodeId(jsonReader.nextString());
+                    } else {
+                        jsonReader.skipValue();
+                    }
+                }
+                jsonReader.endObject();
+                inputs.add(inputNode);
+            }
+            jsonReader.endArray();
+        } else {
+            throw new ParserException("Error! Unsupported value for Workflow Inputs, exptected " +
+                    getTokenString(JsonToken.BEGIN_OBJECT) + " but found" + getTokenString(peek));
+        }
+    }
+
+    private void readWorkflowOutputs(JsonReader jsonReader) throws IOException, ParserException {
+        JsonToken peek = jsonReader.peek();
+        OutputNode outputNode;
+        NodeModel nodeModel;
+        String name;
+        if (peek == JsonToken.NULL) {
+            throw new ParserException("Error! workflow outputs can't be null");
+        } else if (peek == JsonToken.BEGIN_ARRAY) {
+            jsonReader.beginArray();
+            while (jsonReader.hasNext()) {
+                jsonReader.beginObject();
+                nodeModel = new NodeModel();
+                outputNode = new OutputNodeImpl(nodeModel);
+                while (jsonReader.hasNext()) {
+                    name = jsonReader.nextName();
+                    if (name.equals(NAME)) {
+                        nodeModel.setName(jsonReader.nextString());
+                    } else if (name.equals(ID)) {
+                        nodeModel.setNodeId(jsonReader.nextString());
+                    } else if (name.equals(DATATYPE)) {
+                        jsonReader.skipValue();
+                    } else if (name.equals(DESCRIPTION)) {
+                        nodeModel.setDescription(jsonReader.nextString());
+                    } else if (name.equals(POSITION)) {
+                        readPosition(jsonReader);
+                    } else if (name.equals(NODE_ID)) {
+                        nodeModel.setNodeId(jsonReader.nextString());
+                    } else if (name.equals(DEFAULT_VALUE)) {
+                        jsonReader.skipValue();
+                    } else {
+                        jsonReader.skipValue();
+                    }
+
+                }
+                jsonReader.endObject();
+                outputs.add(outputNode);
+            }
+            jsonReader.endArray();
+        } else {
+            throw new ParserException("Error! Unsupported value for Workflow Outputs, exptected " +
+                    getTokenString(JsonToken.BEGIN_OBJECT) + " but found" + getTokenString(peek));
+        }
+    }
+
+    private void readWorkflowLinks(JsonReader jsonReader) throws IOException, ParserException {
+        JsonToken peek = jsonReader.peek();
+        if (peek == JsonToken.NULL) {
+            throw new ParserException("Error! Workflow should have connecting links, found " + getTokenString(peek));
+        } else if (peek == JsonToken.BEGIN_ARRAY) {
+            jsonReader.beginArray();
+            while (jsonReader.hasNext()) {
+                links.add(readLink(jsonReader));
+            }
+            jsonReader.endArray();
+        } else {
+            throw new ParserException("Error! Unsupported value for workflow links, expected " +
+                    getTokenString(JsonToken.BEGIN_ARRAY) + " but found" + getTokenString(peek));
+
+        }
+    }
+
+    private Link readLink(JsonReader jsonReader) throws IOException {
+        jsonReader.beginObject();
+        String name = null;
+        Link link = new Link(null, null);
+        while (jsonReader.hasNext()) {
+            name = jsonReader.nextName();
+            if (name.equals(DESCRIPTION)) {
+                link.setDescription(jsonReader.nextString());
+            } else if (name.equals(FROM)) {
+                link.setFrom(readLinkHelper(jsonReader));
+            } else if (name.equals(TO)) {
+                link.setTo(readLinkHelper(jsonReader));
+            } else {
+                jsonReader.skipValue();
+            }
+        }
+        jsonReader.endObject();
+        return link;
+    }
+
+    private LinkHelper readLinkHelper(JsonReader jsonReader) throws IOException {
+        jsonReader.beginObject();
+        String name;
+        LinkHelper helper = new LinkHelper();
+        while (jsonReader.hasNext()) {
+            name = jsonReader.nextName();
+            if (name.equals(NODE_ID)) {
+                helper.setNodeId(jsonReader.nextString());
+            } else if (name.equals(OUTPUT_ID)) {
+                helper.setOutputId(jsonReader.nextString());
+            } else {
+                jsonReader.skipValue();
+            }
+        }
+        jsonReader.endObject();
+        return helper;
+    }
+
+    private ApplicationNode readApplication(JsonReader jsonReader) throws IOException, ParserException {
+        jsonReader.beginObject();
+        NodeModel nodeModel = new NodeModel();
+        ApplicationNode applicationNode = new ApplicationNodeImpl(nodeModel);
+        String name;
+        while (jsonReader.hasNext()) {
+            name = jsonReader.nextName();
+            if (name.equals(APPLICATION_ID)) {
+                nodeModel.setApplicationId(jsonReader.nextString());
+            } else if (name.equals(NAME)) {
+                nodeModel.setName(jsonReader.nextString());
+            } else if (name.equals(DESCRIPTION)) {
+                nodeModel.setDescription(jsonReader.nextString());
+            } else if (name.equals(APPTYPE)) {
+                jsonReader.skipValue();
+            } else if (name.equals(INPUTS)) {
+                applicationNode.addInputPorts(readApplicationInputs(jsonReader));
+            } else if (name.equals(OUTPUTS)) {
+                applicationNode.addOutPorts(readApplicationOutputs(jsonReader));
+            } else if (name.equals(POSITION)) {
+                readPosition(jsonReader);
+            } else if (name.equals(NODE_ID)) {
+                nodeModel.setNodeId(jsonReader.nextString());
+            } else if (name.equals(PARALLEL_EXECUTION)) {
+                jsonReader.skipValue();
+            } else if (name.equals(PROPERTIES)) {
+                readProperties(jsonReader);
+            }
+        }
+        jsonReader.endObject();
+        return applicationNode;
+    }
+
+    private List<InPort> readApplicationInputs(JsonReader jsonReader) throws IOException, ParserException {
+        List<InPort> inPorts = new ArrayList<>();
+        JsonToken peek = jsonReader.peek();
+        PortModel portModel;
+        InPort inPort;
+        String name;
+        if (peek == JsonToken.NULL) {
+            jsonReader.nextNull();
+        } else if (peek == JsonToken.BEGIN_ARRAY) {
+            jsonReader.beginArray();
+            while (jsonReader.hasNext()) {
+                portModel = new PortModel();
+                inPort = new InputPortIml(portModel);
+                jsonReader.beginObject();
+                while (jsonReader.hasNext()) {
+                    name = jsonReader.nextName();
+                    if (name.equals(NAME)) {
+                        portModel.setName(jsonReader.nextString());
+                    } else if (name.equals(ID)) {
+                        portModel.setPortId(jsonReader.nextString());
+                    } else if (name.equals(DATATYPE)) {
+                        jsonReader.skipValue();
+                    } else if (name.equals(DEFAULT_VALUE)) {
+                        inPort.setDefaultValue(jsonReader.nextString());
+                    } else if (name.equals(DESCRIPTION)) {
+                        portModel.setDescription(jsonReader.nextString());
+                    } else {
+                        jsonReader.skipValue();
+                    }
+                }
+                jsonReader.endObject();
+                inPorts.add(inPort);
+            }
+            jsonReader.endArray();
+        } else {
+            throw new ParserException("Error! reading application inputs, expected " + getTokenString(JsonToken.NULL) +
+                    " or " + getTokenString(JsonToken.BEGIN_ARRAY) + " but found " + getTokenString(peek));
+        }
+
+        return inPorts;
+    }
+
+    private List<OutPort> readApplicationOutputs(JsonReader jsonReader) throws IOException, ParserException {
+        List<OutPort> outPorts = new ArrayList<>();
+        PortModel portModel;
+        OutPort outPort;
+        String name;
+        JsonToken peek = jsonReader.peek();
+        if (peek == JsonToken.NULL) {
+            jsonReader.nextNull();
+        } else if (peek == JsonToken.BEGIN_ARRAY) {
+            jsonReader.beginArray();
+            while (jsonReader.hasNext()) {
+                portModel = new PortModel();
+                outPort = new OutPortImpl(portModel);
+                jsonReader.beginObject();
+                while (jsonReader.hasNext()) {
+                    name = jsonReader.nextName();
+                    if (name.equals(NAME)) {
+                        portModel.setName(jsonReader.nextString());
+                    } else if (name.equals(ID)) {
+                        portModel.setPortId(jsonReader.nextString());
+                    } else if (name.equals(DATATYPE)) {
+                        jsonReader.skipValue();
+                    } else if (name.equals(DEFAULT_VALUE)) {
+                        jsonReader.skipValue(); // can output has default values?
+                    } else if (name.equals(DESCRIPTION)) {
+                        portModel.setDescription(jsonReader.nextString());
+                    } else {
+                        jsonReader.skipValue();
+                    }
+                }
+                jsonReader.endObject();
+                outPorts.add(outPort);
+            }
+            jsonReader.endArray();
+        } else {
+            throw new ParserException("Error! reading application outputs, expected " + getTokenString(JsonToken.NULL) +
+                    " or " + getTokenString(JsonToken.BEGIN_ARRAY) + " but found " + getTokenString(peek));
+
+        }
+        return outPorts;
     }
 
+    private void readPosition(JsonReader jsonReader) throws IOException {
+        JsonToken peek = jsonReader.peek();
+        if (peek == JsonToken.NULL) {
+            jsonReader.nextNull();
+        } else if (peek == JsonToken.BEGIN_OBJECT) {
+            jsonReader.beginObject();
+            while (jsonReader.hasNext()) {
+                // skip position data.
+                jsonReader.nextName();
+                jsonReader.skipValue();
+            }
+            jsonReader.endObject();
+        } else {
+            jsonReader.skipValue();
+        }
+    }
+
+    private void readProperties(JsonReader jsonReader) throws IOException {
+        JsonToken peek = jsonReader.peek();
+        if (peek == JsonToken.NULL) {
+            jsonReader.nextNull();
+        } else if (peek == JsonToken.BEGIN_OBJECT) {
+            jsonReader.beginObject();
+            while (jsonReader.hasNext()) {
+                // TODO: Read and use proprety values
+                String name = jsonReader.nextName();
+                jsonReader.skipValue();
+            }
+            jsonReader.endObject();
+        } else {
+            jsonReader.skipValue();
+        }
+
+    }
+
+    private String getTokenString(JsonToken peek) {
+        switch (peek) {
+            case BEGIN_OBJECT:
+                return "Begin Object";
+            case BEGIN_ARRAY:
+                return "Begin Array";
+            case END_OBJECT:
+                return "End Object";
+            case END_ARRAY:
+                return "End Array";
+            case NAME:
+                return "Name";
+            case STRING:
+                return "String";
+            case NUMBER:
+                return "Number";
+            case BOOLEAN:
+                return "Boolean";
+            case NULL:
+                return "Null";
+            case END_DOCUMENT:
+                return "End Document";
+            default:
+                return "<Coudn't find token type>";
+        }
+    }
+
+
     @Override
     public List<InputNode> getInputNodes() throws Exception {
-        return null;
+        return inputs;
     }
 
     @Override
     public List<OutputNode> getOutputNodes() throws Exception {
-        return null;
+        return outputs;
     }
 
     @Override
     public List<ApplicationNode> getApplicationNodes() throws Exception {
-        return null;
+        return applications;
     }
 
     @Override
     public List<Port> getPorts() throws Exception {
-        return null;
+        return ports;
     }
 
     @Override
     public List<Edge> getEdges() throws Exception {
-        return null;
+        return edges;
     }
 
 
@@ -102,4 +524,79 @@ public class JsonWorkflowParser implements WorkflowParser {
     private Edge createEdge(JsonObject jEdge) {
         return null;
     }
+
+    public static final String WORKFLOW = "workflow";
+    private static final String NAME = "name";
+    public static final String ID = "id";
+    public static final String DESCRIPTION = "description";
+    public static final String VERSION = "version";
+    public static final String APPLICATIONS = "applications";
+    public static final String APPLICATION_ID = "applicationId";
+    public static final String APPTYPE = "appType";
+    public static final String INPUTS = "inputs";
+    public static final String DATATYPE = "dataType";
+    public static final String DEFAULT_VALUE = "defaultValue";
+    public static final String OUTPUTS = "outputs";
+    public static final String POSITION = "position";
+    public static final String X = "x";
+    public static final String Y = "y";
+    public static final String NODE_ID = "nodeId";
+    public static final String PARALLEL_EXECUTION = "parallelExecution";
+    public static final String PROPERTIES = "properties";
+    public static final String WORKFLOW_INPUTS = "workflowInputs";
+    public static final String WORKFLOW_OUTPUTS = "workflowOutputs";
+    public static final String LINKS = "links";
+    public static final String FROM = "from";
+    public static final String TO = "to";
+    public static final String OUTPUT_ID = "outputId";
+
+
+    class Link {
+        private LinkHelper from;
+        private LinkHelper to;
+        private String description;
+
+        public Link(LinkHelper from, LinkHelper to) {
+            this.from = from;
+            this.to = to;
+        }
+
+        public String getDescription() {
+            return description;
+        }
+
+        public void setDescription(String description) {
+            this.description = description;
+        }
+
+        public void setFrom(LinkHelper from) {
+            this.from = from;
+        }
+
+        public void setTo(LinkHelper to) {
+            this.to = to;
+        }
+    }
+
+    class LinkHelper {
+        private String nodeId;
+        private String outputId;
+
+        public String getNodeId() {
+            return nodeId;
+        }
+
+        public void setNodeId(String nodeId) {
+            this.nodeId = nodeId;
+        }
+
+        public String getOutputId() {
+            return outputId;
+        }
+
+        public void setOutputId(String outputId) {
+            this.outputId = outputId;
+        }
+    }
 }
+

http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/ParserException.java
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/ParserException.java b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/ParserException.java
new file mode 100644
index 0000000..173f485
--- /dev/null
+++ b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/ParserException.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.airavata.workflow.core.parser;
+
+public class ParserException extends Exception {
+
+    public ParserException(String message) {
+        super(message);
+    }
+
+    public ParserException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ParserException(Throwable cause) {
+        super(cause);
+    }
+
+    protected ParserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+}

http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/WorkflowParser.java
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/WorkflowParser.java b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/WorkflowParser.java
index dc18c9e..36e8fb0 100644
--- a/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/WorkflowParser.java
+++ b/modules/workflow/workflow-core/src/main/java/org/apache/airavata/workflow/core/parser/WorkflowParser.java
@@ -21,6 +21,7 @@
 
 package org.apache.airavata.workflow.core.parser;
 
+import org.apache.airavata.workflow.core.WorkflowInfo;
 import org.apache.airavata.workflow.core.dag.edge.Edge;
 import org.apache.airavata.workflow.core.dag.nodes.ApplicationNode;
 import org.apache.airavata.workflow.core.dag.nodes.InputNode;
@@ -31,7 +32,7 @@ import java.util.List;
 
 public interface WorkflowParser {
 
-    public void parse() throws Exception;
+    public WorkflowInfo parse() throws Exception;
 
     public List<InputNode> getInputNodes() throws Exception;
 

http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/src/test/java/org/apache/airavata/workflow/core/WorkflowDAGTest.java
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/src/test/java/org/apache/airavata/workflow/core/WorkflowDAGTest.java b/modules/workflow/workflow-core/src/test/java/org/apache/airavata/workflow/core/WorkflowDAGTest.java
deleted file mode 100644
index 09c1416..0000000
--- a/modules/workflow/workflow-core/src/test/java/org/apache/airavata/workflow/core/WorkflowDAGTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.airavata.workflow.core;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class WorkflowDAGTest {
-
-    @Before
-    public void setUp() throws Exception {
-
-    }
-
-    @After
-    public void tearDown() throws Exception {
-
-    }
-
-    @Test
-    public void testWorkflowDAG() throws Exception {
-
-
-
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/src/test/java/org/apache/airavata/workflow/core/parser/JsonWorkflowParserTest.java
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/src/test/java/org/apache/airavata/workflow/core/parser/JsonWorkflowParserTest.java b/modules/workflow/workflow-core/src/test/java/org/apache/airavata/workflow/core/parser/JsonWorkflowParserTest.java
index 3fedc9c..86e2f7e 100644
--- a/modules/workflow/workflow-core/src/test/java/org/apache/airavata/workflow/core/parser/JsonWorkflowParserTest.java
+++ b/modules/workflow/workflow-core/src/test/java/org/apache/airavata/workflow/core/parser/JsonWorkflowParserTest.java
@@ -1,34 +1,95 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
 package org.apache.airavata.workflow.core.parser;
 
+import org.apache.airavata.workflow.core.WorkflowInfo;
+import org.apache.airavata.workflow.core.dag.nodes.ApplicationNode;
+import org.apache.airavata.workflow.core.dag.nodes.InputNode;
+import org.apache.airavata.workflow.core.dag.nodes.OutputNode;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import java.io.File;
 import java.io.InputStream;
+import java.util.List;
 
-import static org.junit.Assert.*;
-
-/**
- * Created by syodage on 2/8/16.
- */
 public class JsonWorkflowParserTest {
 
-    private String workflowString;
-
-
+    private InputStream inputStream;
     @Before
     public void setUp() throws Exception {
-        InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("TestWorkflow.json");
+        inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("TestWorkflow.json");
+        if (inputStream == null) {
+            throw new Exception("Couldn't find TestWorkflow File");
+        }
     }
 
     @After
     public void tearDown() throws Exception {
-
+        if (inputStream != null) {
+            inputStream.close();
+        }
     }
 
     @Test
     public void testParse() throws Exception {
+        JsonWorkflowParser jwp = new JsonWorkflowParser(inputStream);
+
+        WorkflowInfo workflowInfo = jwp.parse();
+        Assert.assertNotNull(workflowInfo);
+        Assert.assertEquals("name", workflowInfo.getName());
+        Assert.assertEquals("default_id", workflowInfo.getId());
+        Assert.assertEquals("default description", workflowInfo.getDescription());
+        Assert.assertEquals("version", workflowInfo.getVersion());
+        testApplications(jwp);
+        testWorkflowInputs(jwp);
+        testWorkflowOutputs(jwp);
 
     }
+
+    private void testApplications(JsonWorkflowParser jwp) throws Exception {
+        List<ApplicationNode> applicationNodes = jwp.getApplicationNodes();
+        Assert.assertNotNull(applicationNodes);
+        Assert.assertEquals(1, applicationNodes.size());
+
+        ApplicationNode node = applicationNodes.get(0);
+        Assert.assertEquals("App Name", node.getName());
+        Assert.assertEquals("appId_1", node.getApplicationId());
+
+    }
+
+    private void testWorkflowInputs(JsonWorkflowParser jwp) throws Exception {
+        List<InputNode> inputNodes = jwp.getInputNodes();
+        Assert.assertEquals(2, inputNodes.size());
+
+    }
+
+    private void testWorkflowOutputs(JsonWorkflowParser jwp) throws Exception {
+        List<OutputNode> outputNodes = jwp.getOutputNodes();
+        Assert.assertEquals(2, outputNodes.size());
+
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/airavata/blob/11ea5014/modules/workflow/workflow-core/src/test/resources/TestWorkflow.json
----------------------------------------------------------------------
diff --git a/modules/workflow/workflow-core/src/test/resources/TestWorkflow.json b/modules/workflow/workflow-core/src/test/resources/TestWorkflow.json
index 5b64172..0dd4b35 100644
--- a/modules/workflow/workflow-core/src/test/resources/TestWorkflow.json
+++ b/modules/workflow/workflow-core/src/test/resources/TestWorkflow.json
@@ -69,16 +69,16 @@
     ],
     "links" : [
       { "description" : "link desc",
-         "from" : { "nodeId" : "" , "ouputId" : "" },
+         "from" : { "nodeId" : "" , "outputId" : "" },
          "to" : { "nodeId" : "" , "outputId" : "" }},
       { "description" : "link desc",
-         "from" : { "nodeId" : "" , "ouputId" : "" },
+         "from" : { "nodeId" : "" , "outputId" : "" },
          "to" : { "nodeId" : "" , "outputId" : "" }},
       { "description" : "link desc",
-         "from" : { "nodeId" : "" , "ouputId" : "" },
+         "from" : { "nodeId" : "" , "outputId" : "" },
          "to" : { "nodeId" : "" , "outputId" : "" }},
       { "description" : "link desc",
-         "from" : { "nodeId" : "" , "ouputId" : "" },
+         "from" : { "nodeId" : "" , "outputId" : "" },
          "to" : { "nodeId" : "" , "outputId" : "" }}
     ]
   }