You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by sa...@apache.org on 2012/05/17 19:12:21 UTC
svn commit: r1339718 [5/10] - in /incubator/airavata/trunk: ./
modules/airavata-client/ modules/distribution/
modules/distribution/src/main/assembly/ modules/workflow-model/
modules/workflow-model/src/ modules/workflow-model/src/main/
modules/workflow-...
Added: incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/InstanceNode.java
URL: http://svn.apache.org/viewvc/incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/InstanceNode.java?rev=1339718&view=auto
==============================================================================
--- incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/InstanceNode.java (added)
+++ incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/InstanceNode.java Thu May 17 17:12:15 2012
@@ -0,0 +1,300 @@
+/*
+ *
+ * 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.model.graph.amazon;
+
+import org.apache.airavata.workflow.model.component.Component;
+import org.apache.airavata.workflow.model.component.amazon.InstanceComponent;
+import org.apache.airavata.workflow.model.graph.ControlEdge;
+import org.apache.airavata.workflow.model.graph.Edge;
+import org.apache.airavata.workflow.model.graph.Graph;
+import org.apache.airavata.workflow.model.graph.GraphException;
+import org.apache.airavata.workflow.model.graph.GraphSchema;
+import org.apache.airavata.workflow.model.graph.Node;
+import org.apache.airavata.workflow.model.graph.Port;
+import org.xmlpull.infoset.XmlElement;
+
+public class InstanceNode extends ResourceNode {
+
+ /*
+ * XML configuration
+ */
+ private static final String NEW_TAG_NAME = "newInstance";
+ private static final String AMI_ID_TAG_NAME = "ami";
+ private static final String INSTANCE_ID_TAG_NAME = "instance";
+ private static final String INSTANCE_TYPE_TAG_NAME = "type";
+ private static final String USERNAME_TAG_NAME = "username";
+
+ private boolean startNewInstance;
+
+ private String instanceId;
+
+ private String amiId;
+
+ private String username;
+
+ private String instanceType;
+
+ private String outputInstanceId;
+
+ /**
+ *
+ * Constructs a InstanceNode.
+ *
+ * @param graph
+ */
+ public InstanceNode(Graph graph) {
+ super(graph);
+ this.startNewInstance = true;
+ }
+
+ /**
+ * Constructs an InstanceNode.
+ *
+ * @param nodeElement
+ * @throws GraphException
+ */
+ public InstanceNode(XmlElement nodeElement) throws GraphException {
+ super(nodeElement);
+ }
+
+ public boolean isStartNewInstance() {
+ return this.startNewInstance;
+ }
+
+ public void setStartNewInstance(boolean startNewInstance) {
+ this.startNewInstance = startNewInstance;
+ }
+
+ public String getUsername() {
+ return this.username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getInstanceType() {
+ return this.instanceType;
+ }
+
+ public void setInstanceType(String instanceType) {
+ this.instanceType = instanceType;
+ }
+
+ /**
+ * Returns the instanceId.
+ *
+ * @return The instanceId
+ */
+ public String getInstanceId() {
+ return this.instanceId;
+ }
+
+ /**
+ * Sets instanceId.
+ *
+ * @param instanceId
+ * The instanceId to set.
+ */
+ public void setInstanceId(String instanceId) {
+ this.instanceId = instanceId;
+ }
+
+ /**
+ * Sets amiId.
+ *
+ * @param amiId
+ * The amiId to set.
+ */
+ public void setAmiId(String amiId) {
+ this.amiId = amiId;
+ }
+
+ /**
+ *
+ * @return AMI_ID or Instance ID depend on user's choice
+ */
+ public String getIdAsValue() {
+ if (this.startNewInstance)
+ return this.amiId;
+ else
+ return this.instanceId;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String getOutputInstanceId() {
+ return this.outputInstanceId;
+ }
+
+ /**
+ *
+ * @param outputInstanceId
+ */
+ public void setOutputInstanceId(String outputInstanceId) {
+ this.outputInstanceId = outputInstanceId;
+ }
+
+ /**
+ *
+ * @see org.apache.airavata.workflow.model.graph.impl.NodeImpl#getComponent()
+ */
+ @Override
+ public Component getComponent() {
+ Component component = super.getComponent();
+ if (component == null) {
+ // The component is null when read from the graph XML.
+ component = new InstanceComponent();
+ setComponent(component);
+ }
+ return component;
+ }
+
+ /**
+ *
+ * @see org.apache.airavata.workflow.model.graph.impl.NodeImpl#parseConfiguration(org.xmlpull.infoset.XmlElement)
+ */
+ @Override
+ protected void parseConfiguration(XmlElement configElement) {
+ super.parseConfiguration(configElement);
+
+ // new instance
+ XmlElement element = configElement.element(null, NEW_TAG_NAME);
+ if (element != null) {
+ for (Object child : element.children()) {
+ this.startNewInstance = Boolean.valueOf((String) child).booleanValue();
+ }
+ }
+
+ if (this.startNewInstance) {
+ // ami id
+ XmlElement element2 = configElement.element(null, AMI_ID_TAG_NAME);
+ if (element != null) {
+ for (Object child : element2.children()) {
+ this.amiId = (String) child;
+ }
+ }
+
+ // instance type
+ XmlElement element3 = configElement.element(null, INSTANCE_TYPE_TAG_NAME);
+ if (element != null) {
+ for (Object child : element3.children()) {
+ this.instanceType = (String) child;
+ }
+ }
+
+ } else {
+ // instance id
+ XmlElement element2 = configElement.element(null, INSTANCE_ID_TAG_NAME);
+ if (element != null) {
+ for (Object child : element2.children()) {
+ this.instanceId = (String) child;
+ }
+ }
+ }
+
+ // username
+ XmlElement element2 = configElement.element(null, USERNAME_TAG_NAME);
+ if (element != null) {
+ for (Object child : element2.children()) {
+ this.username = (String) child;
+ }
+ }
+ }
+
+ /**
+ *
+ * @see org.apache.airavata.workflow.model.graph.impl.NodeImpl#toXML()
+ */
+ @Override
+ protected XmlElement toXML() {
+ XmlElement nodeElement = super.toXML();
+ nodeElement.setAttributeValue(GraphSchema.NS, GraphSchema.NODE_TYPE_ATTRIBUTE, GraphSchema.NODE_TYPE_INSTANCE);
+ return nodeElement;
+ }
+
+ /**
+ *
+ * @see org.apache.airavata.workflow.model.graph.impl.NodeImpl#addConfigurationElement(org.xmlpull.infoset.XmlElement)
+ */
+ @Override
+ protected XmlElement addConfigurationElement(XmlElement nodeElement) {
+ XmlElement configElement = super.addConfigurationElement(nodeElement);
+
+ // save start new instance
+ XmlElement element = configElement.addElement(GraphSchema.NS, NEW_TAG_NAME);
+ element.addChild(String.valueOf(this.startNewInstance));
+
+ if (this.startNewInstance) {
+ // save ami id
+ if (this.amiId != null) {
+ XmlElement element2 = configElement.addElement(GraphSchema.NS, AMI_ID_TAG_NAME);
+ element2.addChild(this.amiId);
+ }
+
+ // save instance type
+ if (this.instanceType != null) {
+ XmlElement element3 = configElement.addElement(GraphSchema.NS, INSTANCE_TYPE_TAG_NAME);
+ element3.addChild(this.instanceType);
+ }
+ } else {
+ // save instance id
+ if (this.instanceId != null) {
+ XmlElement element2 = configElement.addElement(GraphSchema.NS, INSTANCE_ID_TAG_NAME);
+ element2.addChild(this.instanceId);
+ }
+ }
+
+ // save username
+ if (this.username != null) {
+ XmlElement element2 = configElement.addElement(GraphSchema.NS, USERNAME_TAG_NAME);
+ element2.addChild(this.username);
+ }
+
+ return configElement;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.impl.NodeImpl#edgeWasAdded(org.apache.airavata.workflow.model.graph.Edge)
+ */
+ @Override
+ protected void edgeWasAdded(Edge edge) throws GraphException {
+ super.edgeWasAdded(edge);
+
+ if (edge instanceof ControlEdge) {
+ Port toPort = edge.getToPort();
+ Node toNode = toPort.getNode();
+ /*
+ * check if there is already more than instance node connecting to destination node
+ */
+ if (!(toNode instanceof InstanceNode)) {
+ for (Node node : toNode.getControlInPort().getFromNodes()) {
+ if ((node instanceof InstanceNode) && this != node) {
+ throw new GraphException("Cannot connect more than one instance node to another node.");
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
Added: incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/ResourceNode.java
URL: http://svn.apache.org/viewvc/incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/ResourceNode.java?rev=1339718&view=auto
==============================================================================
--- incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/ResourceNode.java (added)
+++ incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/ResourceNode.java Thu May 17 17:12:15 2012
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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.model.graph.amazon;
+
+import org.apache.airavata.workflow.model.graph.DataEdge;
+import org.apache.airavata.workflow.model.graph.Edge;
+import org.apache.airavata.workflow.model.graph.Graph;
+import org.apache.airavata.workflow.model.graph.GraphException;
+import org.apache.airavata.workflow.model.graph.GraphSchema;
+import org.apache.airavata.workflow.model.graph.Node;
+import org.apache.airavata.workflow.model.graph.Port;
+import org.apache.airavata.workflow.model.graph.impl.NodeImpl;
+import org.xmlpull.infoset.XmlElement;
+
+/**
+ * The placeholder for Instance Nodes type. Using for easy checking
+ *
+ */
+public abstract class ResourceNode extends NodeImpl {
+
+ /**
+ *
+ * Constructs a ResourceNode.
+ *
+ * @param graph
+ */
+ public ResourceNode(Graph graph) {
+ super(graph);
+ }
+
+ /**
+ * Constructs an InstanceNode.
+ *
+ * @param nodeElement
+ * @throws GraphException
+ */
+ public ResourceNode(XmlElement nodeElement) throws GraphException {
+ super(nodeElement);
+ }
+
+ /**
+ *
+ * @see org.apache.airavata.workflow.model.graph.impl.NodeImpl#addConfigurationElement(org.xmlpull.infoset.XmlElement)
+ */
+ @Override
+ protected XmlElement addConfigurationElement(XmlElement nodeElement) {
+ XmlElement configElement = nodeElement.addElement(GraphSchema.NS, GraphSchema.NODE_CONFIG_TAG);
+ return configElement;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.impl.NodeImpl#edgeWasAdded(org.apache.airavata.workflow.model.graph.Edge)
+ */
+ @Override
+ protected void edgeWasAdded(Edge edge) throws GraphException {
+ super.edgeWasAdded(edge);
+
+ if (edge instanceof DataEdge) {
+ Port toPort = edge.getToPort();
+ Node toNode = toPort.getNode();
+ Port fromPort = edge.getFromPort();
+ Node fromNode = fromPort.getNode();
+
+ if (!(toNode instanceof ResourceNode && fromNode instanceof ResourceNode)) {
+ throw new GraphException("Cannot connect Resource Node to other type of nodes");
+ }
+ }
+ }
+}
\ No newline at end of file
Added: incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/TerminateInstanceNode.java
URL: http://svn.apache.org/viewvc/incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/TerminateInstanceNode.java?rev=1339718&view=auto
==============================================================================
--- incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/TerminateInstanceNode.java (added)
+++ incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/amazon/TerminateInstanceNode.java Thu May 17 17:12:15 2012
@@ -0,0 +1,89 @@
+/*
+ *
+ * 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.model.graph.amazon;
+
+import org.apache.airavata.workflow.model.component.Component;
+import org.apache.airavata.workflow.model.component.amazon.TerminateInstanceComponent;
+import org.apache.airavata.workflow.model.graph.Graph;
+import org.apache.airavata.workflow.model.graph.GraphException;
+import org.apache.airavata.workflow.model.graph.GraphSchema;
+import org.xmlpull.infoset.XmlElement;
+
+public class TerminateInstanceNode extends ResourceNode {
+
+ private boolean startNewInstance;
+
+ /**
+ *
+ * Constructs a InstanceNode.
+ *
+ * @param graph
+ */
+ public TerminateInstanceNode(Graph graph) {
+ super(graph);
+ this.startNewInstance = true;
+ }
+
+ /**
+ * Constructs an InstanceNode.
+ *
+ * @param nodeElement
+ * @throws GraphException
+ */
+ public TerminateInstanceNode(XmlElement nodeElement) throws GraphException {
+ super(nodeElement);
+ }
+
+ /**
+ *
+ * @see org.apache.airavata.workflow.model.graph.impl.NodeImpl#getComponent()
+ */
+ @Override
+ public Component getComponent() {
+ Component component = super.getComponent();
+ if (component == null) {
+ // The component is null when read from the graph XML.
+ component = new TerminateInstanceComponent();
+ setComponent(component);
+ }
+ return component;
+ }
+
+ /**
+ *
+ * @see org.apache.airavata.workflow.model.graph.impl.NodeImpl#toXML()
+ */
+ @Override
+ protected XmlElement toXML() {
+ XmlElement nodeElement = super.toXML();
+ nodeElement.setAttributeValue(GraphSchema.NS, GraphSchema.NODE_TYPE_ATTRIBUTE, GraphSchema.NODE_TYPE_TERMINATE);
+ return nodeElement;
+ }
+
+ public boolean isStartNewInstance() {
+ return this.startNewInstance;
+ }
+
+ public void setStartNewInstance(boolean startNewInstance) {
+ this.startNewInstance = startNewInstance;
+ }
+}
\ No newline at end of file
Added: incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/BasicTypeMapping.java
URL: http://svn.apache.org/viewvc/incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/BasicTypeMapping.java?rev=1339718&view=auto
==============================================================================
--- incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/BasicTypeMapping.java (added)
+++ incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/BasicTypeMapping.java Thu May 17 17:12:15 2012
@@ -0,0 +1,252 @@
+/*
+ *
+ * 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.model.graph.dynamic;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import javax.xml.namespace.QName;
+
+import org.apache.airavata.common.utils.XMLUtil;
+import org.apache.airavata.workflow.model.exceptions.WorkflowException;
+import org.apache.airavata.workflow.model.exceptions.WorkflowRuntimeException;
+import org.xmlpull.infoset.XmlAttribute;
+import org.xmlpull.infoset.XmlElement;
+import org.xmlpull.infoset.XmlNamespace;
+
+public class BasicTypeMapping {
+
+ /**
+ * STR_UNBOUNDED
+ */
+ private static final String STR_UNBOUNDED = "unbounded";
+
+ /**
+ * STR_MAX_OCCURS
+ */
+ private static final String STR_MAX_OCCURS = "maxOccurs";
+
+ /**
+ * STR_TYPE
+ */
+ private static final String STR_TYPE = "type";
+
+ /**
+ * NUM
+ */
+ private static final int NUM = 2;
+
+ private static QName[] TYPES = new QName[NUM];
+
+ private static String[] NAMES = new String[NUM * 2];
+
+ private static String[] DEFAULTS = new String[NUM * 2];
+
+ private static String[] VAR_NAMES = new String[NUM * 2];
+
+ public static final QName STRING_QNAME = new QName("http://www.w3.org/2001/XMLSchema", "string");
+ public static QName INT_QNAME = new QName("http://www.w3.org/2001/XMLSchema", "int");
+
+ /**
+ * Used to generate string1, string2, string3 ...
+ */
+ public static int uniqueVarappend = 0;
+
+ static {
+
+ TYPES[0] = INT_QNAME;
+
+ TYPES[1] = STRING_QNAME;
+
+ NAMES[0] = "int";
+ NAMES[1] = "String";
+ NAMES[0 + NUM] = "int[]";
+ NAMES[1 + NUM] = "String[]";
+
+ DEFAULTS[0] = "0";
+ DEFAULTS[1] = "null";
+ DEFAULTS[0 + NUM] = "null";
+ DEFAULTS[1 + NUM] = "null";
+
+ VAR_NAMES[0] = "intVal";
+ VAR_NAMES[1] = "string";
+ VAR_NAMES[0 + NUM] = "intArray";
+ VAR_NAMES[1 + NUM] = "stringArray";
+
+ }
+
+ /**
+ * REturns the index of the simple type which can be used to get the Java typename, etc. rerurns -1 if not a simple
+ * type.
+ *
+ * @param qname
+ * @return
+ */
+ public static int getSimpleTypeIndex(QName qname) {
+ for (int i = 0; i < TYPES.length; ++i) {
+ if (TYPES[i].equals(qname)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static String getTypeName(int index) {
+ if (index >= 2 * NUM || index < 0) {
+ throw new IllegalStateException("Invalid Index");
+ }
+ return NAMES[index];
+ }
+
+ public static String getTypeName(QName qName) {
+ return getTypeName(getSimpleTypeIndex(qName));
+ }
+
+ public static String getTypeDefault(int index) {
+ if (index >= 2 * NUM || index < 0) {
+ throw new IllegalStateException("Invalid Index");
+ }
+ return DEFAULTS[index];
+ }
+
+ public static String getTypeDefault(QName qName) {
+ return getTypeDefault(getSimpleTypeIndex(qName));
+ }
+
+ public static String getTypeVariableName(int index) {
+ if (index >= 2 * NUM || index < 0) {
+ throw new IllegalStateException("Invalid Index");
+ }
+ return VAR_NAMES[index] + getUniqueVarAppender();
+ }
+
+ public static String getTypeVariableName(QName qName) {
+ return getTypeVariableName(getSimpleTypeIndex(qName));
+ }
+
+ private synchronized static int getUniqueVarAppender() {
+ return uniqueVarappend++;
+ }
+
+ public static void reset() {
+ uniqueVarappend = 0;
+ }
+
+ public static Object getObjectOfType(int index, Object obj) {
+ switch (index) {
+ case 0:
+ return new Integer((String) obj);
+ case 1:
+ return obj;
+ }
+ throw new WorkflowRuntimeException("type Not Supported yet!!");
+ }
+
+ public static Object getObjectOfType(QName qName, Object obj) {
+ return getObjectOfType(getSimpleTypeIndex(qName), obj);
+ }
+
+ public static int getSimpleTypeIndex(XmlElement element) {
+
+ XmlAttribute type = element.attribute(STR_TYPE);
+ if (null == type) {
+ return -1;
+ }
+ String typeQNameString = type.getValue();
+ String typeName = XMLUtil.getLocalPartOfQName(typeQNameString);
+ String prefix = XMLUtil.getPrefixOfQName(typeQNameString);
+ XmlNamespace namespace = element.lookupNamespaceByPrefix(prefix);
+ if (namespace == null) {
+ return -1;
+ }
+ QName typeQname = new QName(namespace.getName(), typeName, prefix);
+ int simpleTypeIndex = getSimpleTypeIndex(typeQname);
+ if (-1 == simpleTypeIndex) {
+ return -1;
+ }
+
+ XmlAttribute maxOccurs = element.attribute(STR_MAX_OCCURS);
+ if (maxOccurs != null && STR_UNBOUNDED.equals(maxOccurs.getValue())) {
+ // this is the comvention the arraytype index is simplextye index + NUM
+ return NUM + simpleTypeIndex;
+ } else {
+ return simpleTypeIndex;
+ }
+ }
+
+ public static boolean isArrayType(XmlElement element) {
+ int index = getSimpleTypeIndex(element);
+ if (index >= NUM) {
+ return true;
+ }
+ return false;
+ }
+
+ public static Object getOutputArray(XmlElement element, String name, int simpleIndex) throws WorkflowException {
+ try {
+ // This code doesn't work when the output is a complex type.
+ // Object output = this.outputMessage.getObjectPart(name);
+ // return output;
+
+ XmlElement outputElement = (XmlElement) element;
+ Iterator valueElementItr = outputElement.elements(null, name).iterator();
+ LinkedList<String> ret = new LinkedList<String>();
+ while (valueElementItr.hasNext()) {
+ XmlElement valueElement = (XmlElement) valueElementItr.next();
+ Iterator childIt = valueElement.children().iterator();
+ int numberOfChildren = 0;
+ while (childIt.hasNext()) {
+ childIt.next();
+ numberOfChildren++;
+ }
+ if (numberOfChildren == 1) {
+ Object child = valueElement.children().iterator().next();
+ if (child instanceof String) {
+ // Value is a simple type. Return the string.
+ String value = (String) child;
+ ret.add(value);
+ }
+ }
+ }
+ switch (simpleIndex) {
+ case 0:
+ Integer[] intRet = new Integer[ret.size()];
+ for (int i = 0; i < ret.size(); i++) {
+ intRet[i] = Integer.parseInt(ret.get(i));
+ }
+ return intRet;
+ case 1:
+ String[] strRet = new String[ret.size()];
+ for (int i = 0; i < ret.size(); i++) {
+ strRet[i] = ret.get(i);
+ }
+ return strRet;
+ }
+ throw new WorkflowException("Unknown type");
+
+ } catch (RuntimeException e) {
+ String message = "Error in getting output. name: " + name;
+ throw new WorkflowException(message, e);
+ }
+ }
+
+}
\ No newline at end of file
Added: incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/DynamicNode.java
URL: http://svn.apache.org/viewvc/incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/DynamicNode.java?rev=1339718&view=auto
==============================================================================
--- incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/DynamicNode.java (added)
+++ incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/DynamicNode.java Thu May 17 17:12:15 2012
@@ -0,0 +1,133 @@
+/*
+ *
+ * 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.model.graph.dynamic;
+
+import java.net.URL;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.airavata.workflow.model.component.dynamic.DynamicComponent;
+import org.apache.airavata.workflow.model.component.dynamic.DynamicComponentPort;
+import org.apache.airavata.workflow.model.graph.DataPort;
+import org.apache.airavata.workflow.model.graph.Edge;
+import org.apache.airavata.workflow.model.graph.Graph;
+import org.apache.airavata.workflow.model.graph.GraphException;
+import org.apache.airavata.workflow.model.graph.Port;
+import org.apache.airavata.workflow.model.graph.impl.NodeImpl;
+import org.apache.airavata.workflow.model.graph.impl.PortImpl;
+import org.apache.airavata.workflow.model.graph.util.GraphUtil;
+
+public class DynamicNode extends NodeImpl implements PortAddable {
+
+ /**
+ * Constructs a WSNode.
+ *
+ * @param graph
+ */
+ public DynamicNode(Graph graph) {
+ super(graph);
+ Collection<PortImpl> allPorts = this.getAllPorts();
+ for (Port port : allPorts) {
+ ((DynamicPort) port).setNode(this);
+ }
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Node#getComponent()
+ */
+ @Override
+ public DynamicComponent getComponent() {
+ return (DynamicComponent) super.getComponent();
+ }
+
+ /**
+ * @throws GraphException
+ * @see org.apache.airavata.workflow.model.graph.impl.NodeImpl#edgeWasAdded(org.apache.airavata.workflow.model.graph.Edge)
+ */
+ @Override
+ protected void edgeWasAdded(Edge edge) throws GraphException {
+ GraphUtil.validateConnection(edge);
+ }
+
+ public DataPort getFreeInPort() {
+ List<DataPort> inputPorts = this.getInputPorts();
+ for (DataPort dataPort : inputPorts) {
+ if (null == dataPort.getFromNode()) {
+ return dataPort;
+ }
+ }
+ // none found, so make a new one.
+ DynamicComponentPort comPort = new DynamicComponentPort(getComponent());
+ getComponent().addInputPort(comPort);
+ DataPort port = comPort.createPort();
+ ((DynamicPort) port).setNode(this);
+ this.addInputPort(port);
+
+ return port;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.dynamic.PortAddable#removeLastDynamicallyAddedInPort()
+ */
+ @Override
+ public void removeLastDynamicallyAddedInPort() throws GraphException {
+
+ List<DataPort> inputPorts = this.getInputPorts();
+ if (inputPorts.size() == 1) {
+ // This is the initial port, so leave it alone
+ return;
+ }
+ DataPort portToBeRemoved = null;
+ for (DataPort dataPort : inputPorts) {
+ if (null == dataPort.getFromNode()) {
+ getComponent().removeInputPort((DynamicComponentPort) dataPort.getComponentPort());
+ portToBeRemoved = dataPort;
+ break;
+ }
+ }
+ if (null != portToBeRemoved) {
+ this.removeInputPort(portToBeRemoved);
+ }
+ }
+
+ /**
+ * @param url
+ */
+ public void setImplURL(URL url) {
+ this.getComponent().setImplJarLocation(url);
+ }
+
+ /**
+ * @param operationName
+ */
+ public void setOperationName(String operationName) {
+ this.getComponent().setOperationName(operationName);
+ }
+
+ /**
+ * @param className
+ */
+ public void setClassName(String className) {
+ this.getComponent().setClassName(className);
+ }
+
+}
\ No newline at end of file
Added: incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/DynamicPort.java
URL: http://svn.apache.org/viewvc/incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/DynamicPort.java?rev=1339718&view=auto
==============================================================================
--- incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/DynamicPort.java (added)
+++ incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/DynamicPort.java Thu May 17 17:12:15 2012
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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.model.graph.dynamic;
+
+import javax.xml.namespace.QName;
+
+import org.apache.airavata.workflow.model.component.ComponentPort;
+import org.apache.airavata.workflow.model.component.dynamic.DynamicComponentPort;
+import org.apache.airavata.workflow.model.exceptions.WorkflowRuntimeException;
+import org.apache.airavata.workflow.model.graph.DataPort;
+import org.apache.airavata.workflow.model.graph.GraphException;
+import org.apache.airavata.workflow.model.graph.impl.NodeImpl;
+
+public class DynamicPort extends DataPort {
+
+ private DynamicComponentPort componentPort;
+
+ /**
+ * Constructs a DynamicPort.
+ *
+ */
+ public DynamicPort() {
+ super();
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.DataPort#copyType(org.apache.airavata.workflow.model.graph.DataPort)
+ */
+ @Override
+ public void copyType(DataPort port) throws GraphException {
+
+ }
+
+ /**
+ * Returns the typeQName.
+ *
+ * @return The typeQName
+ */
+ @Override
+ public QName getType() {
+ return getComponentPort().getType();
+ }
+
+ public void setComponentPort(ComponentPort componentPort) {
+ super.setComponentPort(componentPort);
+ this.componentPort = (DynamicComponentPort) componentPort;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.impl.PortImpl#getComponentPort()
+ */
+ @Override
+ public DynamicComponentPort getComponentPort() {
+ if (this.componentPort == null) {
+ ComponentPort port = super.getComponentPort();
+ if (port instanceof DynamicComponentPort) {
+ this.componentPort = (DynamicComponentPort) port;
+ } else {
+ throw new WorkflowRuntimeException("UNEXPECTED ERROR: Unable to resolve Port");
+ }
+
+ }
+ return this.componentPort;
+ }
+
+ public void setNode(NodeImpl node) {
+ super.setNode(node);
+ }
+}
\ No newline at end of file
Added: incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/PortAddable.java
URL: http://svn.apache.org/viewvc/incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/PortAddable.java?rev=1339718&view=auto
==============================================================================
--- incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/PortAddable.java (added)
+++ incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/PortAddable.java Thu May 17 17:12:15 2012
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.model.graph.dynamic;
+
+import org.apache.airavata.workflow.model.graph.DataPort;
+import org.apache.airavata.workflow.model.graph.GraphException;
+
+public interface PortAddable {
+
+ public abstract void removeLastDynamicallyAddedInPort() throws GraphException;
+
+ public abstract DataPort getFreeInPort();
+}
\ No newline at end of file
Added: incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/SchemaCompilerUtil.java
URL: http://svn.apache.org/viewvc/incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/SchemaCompilerUtil.java?rev=1339718&view=auto
==============================================================================
--- incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/SchemaCompilerUtil.java (added)
+++ incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/dynamic/SchemaCompilerUtil.java Thu May 17 17:12:15 2012
@@ -0,0 +1,224 @@
+/*
+ *
+ * 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.model.graph.dynamic;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.airavata.workflow.model.exceptions.WorkflowRuntimeException;
+import org.apache.xmlbeans.SchemaCodePrinter;
+import org.apache.xmlbeans.impl.common.IOUtil;
+import org.apache.xmlbeans.impl.common.XmlErrorPrinter;
+import org.apache.xmlbeans.impl.tool.CodeGenUtil;
+import org.apache.xmlbeans.impl.tool.CommandLine;
+import org.apache.xmlbeans.impl.tool.SchemaCompiler;
+import org.apache.xmlbeans.impl.values.XmlListImpl;
+
+public class SchemaCompilerUtil extends SchemaCompiler {
+
+ public static void compile(String[] args) {
+ if (args.length == 0) {
+ return;
+ }
+
+ Set flags = new HashSet();
+ flags.add("h");
+ flags.add("help");
+ flags.add("usage");
+ flags.add("license");
+ flags.add("quiet");
+ flags.add("verbose");
+ flags.add("version");
+ flags.add("dl");
+ flags.add("noupa");
+ flags.add("nopvr");
+ flags.add("noann");
+ flags.add("novdoc");
+ flags.add("noext");
+ flags.add("srconly");
+ flags.add("debug");
+
+ Set opts = new HashSet();
+ opts.add("out");
+ opts.add("name");
+ opts.add("src");
+ opts.add("d");
+ opts.add("cp");
+ opts.add("compiler");
+ opts.add("javasource");
+ opts.add("jar"); // deprecated
+ opts.add("ms");
+ opts.add("mx");
+ opts.add("repackage");
+ opts.add("schemaCodePrinter");
+ opts.add("extension");
+ opts.add("extensionParms");
+ opts.add("allowmdef");
+ opts.add("catalog");
+ CommandLine cl = new CommandLine(args, flags, opts);
+
+ String[] badopts = cl.getBadOpts();
+ if (badopts.length > 0) {
+ for (int i = 0; i < badopts.length; i++)
+ System.out.println("Unrecognized option: " + badopts[i]);
+ return;
+ }
+
+ boolean verbose = (cl.getOpt("verbose") != null);
+ boolean quiet = (cl.getOpt("quiet") != null);
+ if (verbose)
+ quiet = false;
+
+ String outputfilename = cl.getOpt("out");
+
+ String repackage = cl.getOpt("repackage");
+
+ cl.getOpt("schemaCodePrinter");
+ SchemaCodePrinter codePrinter = null;
+ String name = cl.getOpt("name");
+
+ boolean download = (cl.getOpt("dl") != null);
+ boolean noUpa = (cl.getOpt("noupa") != null);
+ boolean noPvr = (cl.getOpt("nopvr") != null);
+ boolean noAnn = (cl.getOpt("noann") != null);
+ boolean noVDoc = (cl.getOpt("novdoc") != null);
+ boolean noExt = (cl.getOpt("noext") != null);
+ boolean nojavac = (cl.getOpt("srconly") != null);
+ boolean debug = (cl.getOpt("debug") != null);
+
+ String allowmdef = cl.getOpt("allowmdef");
+ Set mdefNamespaces = (allowmdef == null ? Collections.EMPTY_SET : new HashSet(Arrays.asList(XmlListImpl
+ .split_list(allowmdef))));
+
+ List extensions = new ArrayList();
+
+ String classesdir = cl.getOpt("d");
+ File classes = null;
+ if (classesdir != null)
+ classes = new File(classesdir);
+
+ String srcdir = cl.getOpt("src");
+ File src = null;
+ if (srcdir != null)
+ src = new File(srcdir);
+ if (nojavac && srcdir == null && classes != null)
+ src = classes;
+
+ // create temp directory
+ File tempdir = null;
+ if (src == null || classes == null) {
+ throw new WorkflowRuntimeException("Code gen src directory or classes directory is null");
+ }
+
+ File jarfile = null;
+ if (outputfilename == null && classes == null && !nojavac)
+ outputfilename = "xmltypes.jar";
+ if (outputfilename != null)
+ jarfile = new File(outputfilename);
+
+ if (src == null)
+ src = IOUtil.createDir(tempdir, "src");
+ if (classes == null)
+ classes = IOUtil.createDir(tempdir, "classes");
+
+ File[] classpath = null;
+ String cpString = cl.getOpt("cp");
+ if (cpString != null) {
+ String[] cpparts = cpString.split(File.pathSeparator);
+ List cpList = new ArrayList();
+ for (int i = 0; i < cpparts.length; i++)
+ cpList.add(new File(cpparts[i]));
+ classpath = (File[]) cpList.toArray(new File[cpList.size()]);
+ } else {
+ classpath = CodeGenUtil.systemClasspath();
+ }
+
+ String javasource = cl.getOpt("javasource");
+ String compiler = cl.getOpt("compiler");
+ String jar = cl.getOpt("jar");
+ if (verbose && jar != null)
+ System.out.println("The 'jar' option is no longer supported.");
+
+ String memoryInitialSize = cl.getOpt("ms");
+ String memoryMaximumSize = cl.getOpt("mx");
+
+ File[] xsdFiles = cl.filesEndingWith(".xsd");
+ File[] wsdlFiles = cl.filesEndingWith(".wsdl");
+ File[] javaFiles = cl.filesEndingWith(".java");
+ File[] configFiles = cl.filesEndingWith(".xsdconfig");
+ URL[] urlFiles = cl.getURLs();
+
+ if (xsdFiles.length + wsdlFiles.length + urlFiles.length == 0) {
+ System.out.println("Could not find any xsd or wsdl files to process.");
+ return;
+ }
+ File baseDir = cl.getBaseDir();
+ URI baseURI = baseDir == null ? null : baseDir.toURI();
+
+ XmlErrorPrinter err = new XmlErrorPrinter(verbose, baseURI);
+
+ String catString = cl.getOpt("catalog");
+
+ Parameters params = new Parameters();
+ params.setBaseDir(baseDir);
+ params.setXsdFiles(xsdFiles);
+ params.setWsdlFiles(wsdlFiles);
+ params.setJavaFiles(javaFiles);
+ params.setConfigFiles(configFiles);
+ params.setUrlFiles(urlFiles);
+ params.setClasspath(classpath);
+ params.setOutputJar(jarfile);
+ params.setName(name);
+ params.setSrcDir(src);
+ params.setClassesDir(classes);
+ params.setCompiler(compiler);
+ params.setJavaSource(javasource);
+ params.setMemoryInitialSize(memoryInitialSize);
+ params.setMemoryMaximumSize(memoryMaximumSize);
+ params.setNojavac(nojavac);
+ params.setQuiet(quiet);
+ params.setVerbose(verbose);
+ params.setDownload(download);
+ params.setNoUpa(noUpa);
+ params.setNoPvr(noPvr);
+ params.setNoAnn(noAnn);
+ params.setNoVDoc(noVDoc);
+ params.setNoExt(noExt);
+ params.setDebug(debug);
+ params.setErrorListener(err);
+ params.setRepackage(repackage);
+ params.setExtensions(extensions);
+ params.setMdefNamespaces(mdefNamespaces);
+ params.setCatalogFile(catString);
+ params.setSchemaCodePrinter(codePrinter);
+
+ compile(params);
+
+ }
+}
\ No newline at end of file
Added: incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/impl/EdgeImpl.java
URL: http://svn.apache.org/viewvc/incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/impl/EdgeImpl.java?rev=1339718&view=auto
==============================================================================
--- incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/impl/EdgeImpl.java (added)
+++ incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/impl/EdgeImpl.java Thu May 17 17:12:15 2012
@@ -0,0 +1,164 @@
+/*
+ *
+ * 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.model.graph.impl;
+
+import org.apache.airavata.common.utils.XMLUtil;
+import org.apache.airavata.workflow.model.graph.Edge;
+import org.apache.airavata.workflow.model.graph.GraphException;
+import org.apache.airavata.workflow.model.graph.GraphSchema;
+import org.xmlpull.infoset.XmlElement;
+
+/**
+ * The Edge represents an edge that connects a uses port to a provide port.
+ *
+ */
+public abstract class EdgeImpl implements Edge {
+
+ private GraphImpl graph;
+
+ private PortImpl fromPort;
+
+ private PortImpl toPort;
+ // The followings are used only during parsing the XML.
+
+ private String fromPortID;
+
+ private String toPortID;
+
+ private String label;
+
+ /**
+ * Creates an Edge.
+ */
+ public EdgeImpl() {
+ // Do nothing
+ }
+
+ /**
+ * Constructs a EdgeImpl.
+ *
+ * @param edgeXml
+ */
+ public EdgeImpl(XmlElement edgeXml) {
+ parse(edgeXml);
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Edge#getFromPort()
+ */
+ public PortImpl getFromPort() {
+ return this.fromPort;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Edge#getToPort()
+ */
+ public PortImpl getToPort() {
+ return this.toPort;
+ }
+
+ /**
+ * Sets a graph this edge belogs to.
+ *
+ * @param graph
+ * The graph
+ */
+ protected void setGraph(GraphImpl graph) {
+ this.graph = graph;
+ }
+
+ /**
+ * @param fromPort
+ */
+ protected void setFromPort(PortImpl fromPort) {
+ this.fromPort = fromPort;
+ }
+
+ /**
+ * @param toPort
+ */
+ protected void setToPort(PortImpl toPort) {
+ this.toPort = toPort;
+ }
+
+ protected void indexToPointer() throws GraphException {
+ this.fromPort = this.graph.getPort(this.fromPortID);
+ if (this.fromPort == null) {
+ throw new GraphException("Cannot find a port with the ID, " + this.fromPortID + ".");
+ }
+ this.toPort = this.graph.getPort(this.toPortID);
+ if (this.toPort == null) {
+ throw new GraphException("Cannot find a port with the ID, " + this.toPortID + ".");
+ }
+
+ // Has to do the above first because they are used in the edgeWasAdded
+ // method.
+ this.fromPort.addEdge(this);
+ this.toPort.addEdge(this);
+ }
+
+ /**
+ * @param edgeElement
+ */
+ protected void parse(XmlElement edgeElement) {
+ XmlElement fromPortElement = edgeElement.element(GraphSchema.EDGE_FROM_PORT_TAG);
+ this.fromPortID = fromPortElement.requiredText();
+
+ XmlElement toPortElement = edgeElement.element(GraphSchema.EDGE_TO_PORT_TAG);
+ this.toPortID = toPortElement.requiredText();
+ }
+
+ /**
+ * @return the XmlElement
+ */
+ protected XmlElement toXML() {
+ XmlElement edgeXml = XMLUtil.BUILDER.newFragment(GraphSchema.NS, GraphSchema.EDGE_TAG);
+
+ XmlElement fromEle = edgeXml.addElement(GraphSchema.NS, GraphSchema.EDGE_FROM_PORT_TAG);
+ fromEle.addChild(this.fromPort.getID());
+
+ XmlElement toEle = edgeXml.addElement(GraphSchema.NS, GraphSchema.EDGE_TO_PORT_TAG);
+ toEle.addChild(this.toPort.getID());
+
+ return edgeXml;
+ }
+
+ /**
+ * Returns the label.
+ *
+ * @return The label
+ */
+ public String getLabel() {
+ return this.label;
+ }
+
+ /**
+ * Sets label.
+ *
+ * @param label
+ * The label to set.
+ */
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+}
\ No newline at end of file
Added: incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/impl/GraphImpl.java
URL: http://svn.apache.org/viewvc/incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/impl/GraphImpl.java?rev=1339718&view=auto
==============================================================================
--- incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/impl/GraphImpl.java (added)
+++ incubator/airavata/trunk/modules/workflow-model/src/main/java/org/apache/airavata/workflow/model/graph/impl/GraphImpl.java Thu May 17 17:12:15 2012
@@ -0,0 +1,656 @@
+/*
+ *
+ * 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.model.graph.impl;
+
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.airavata.common.utils.XMLUtil;
+import org.apache.airavata.workflow.model.exceptions.WorkflowRuntimeException;
+import org.apache.airavata.workflow.model.graph.ControlPort;
+import org.apache.airavata.workflow.model.graph.DataEdge;
+import org.apache.airavata.workflow.model.graph.DataPort;
+import org.apache.airavata.workflow.model.graph.Edge;
+import org.apache.airavata.workflow.model.graph.Graph;
+import org.apache.airavata.workflow.model.graph.GraphException;
+import org.apache.airavata.workflow.model.graph.GraphFactory;
+import org.apache.airavata.workflow.model.graph.GraphSchema;
+import org.apache.airavata.workflow.model.graph.Node;
+import org.apache.airavata.workflow.model.graph.Port;
+import org.apache.airavata.workflow.model.graph.Port.Kind;
+import org.apache.airavata.workflow.model.graph.system.InputNode;
+import org.apache.airavata.workflow.model.graph.system.OutputNode;
+import org.apache.airavata.workflow.model.graph.system.StreamSourceNode;
+import org.apache.airavata.workflow.model.graph.system.SystemDataPort;
+import org.apache.airavata.workflow.model.graph.util.GraphUtil;
+import org.apache.airavata.workflow.model.graph.ws.WSPort;
+import org.apache.airavata.workflow.model.utils.ApplicationVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xmlpull.infoset.XmlElement;
+
+public abstract class GraphImpl implements Graph {
+
+ private static final Logger logger = LoggerFactory.getLogger(GraphImpl.class);
+
+ /**
+ * Unique ID of this workflow
+ */
+ private String id;
+
+ /**
+ * Name of the workflow. It has to have one.
+ */
+ private String name = "Workflow";
+
+ /**
+ * Default to empty string to avoid null check.
+ */
+ private String description = "";
+
+ private List<NodeImpl> nodes = new LinkedList<NodeImpl>();
+
+ private List<PortImpl> ports = new LinkedList<PortImpl>();
+
+ private List<EdgeImpl> edges = new LinkedList<EdgeImpl>();
+
+ private GraphFactory factory;
+
+ /**
+ * @param factory
+ */
+ public GraphImpl(GraphFactory factory) {
+ this.factory = factory;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#getID()
+ */
+ public String getID() {
+ if (this.id == null) {
+ this.id = this.name;
+ // If its still null
+ if (null == this.id) {
+ throw new WorkflowRuntimeException("The workflow ID is null");
+ }
+ }
+ return this.id;
+ }
+
+
+ /**
+ * This will only be done for the ODE
+ *
+ * @param id
+ */
+ public void setID(String id) {
+ this.id = id;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#setName(java.lang.String)
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#getName()
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#getDescription()
+ */
+ public String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#setDescription(java.lang.String)
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#getNodes()
+ */
+ public List<NodeImpl> getNodes() {
+ return this.nodes;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#getPorts()
+ */
+ public List<PortImpl> getPorts() {
+ return this.ports;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#getEdges()
+ */
+ public List<EdgeImpl> getEdges() {
+ return this.edges;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#removeNode(org.apache.airavata.workflow.model.graph.Node)
+ */
+ public void removeNode(Node node) throws GraphException {
+ if (node == null) {
+ throw new IllegalArgumentException("null");
+ }
+ if (!this.nodes.contains(node)) {
+ throw new GraphException("The graph doesn't contain the node that is being removed.");
+ }
+
+ NodeImpl nodeImpl = (NodeImpl) node;
+
+ // Have to be very careful to remove the node.
+ // The extended for loop cannot be used to remove the elements.
+
+ // Remove edges connected to input ports.
+ for (Iterator<DataPort> portItr = nodeImpl.getInputPorts().iterator(); portItr.hasNext();) {
+ DataPort port = portItr.next();
+ for (Iterator<DataEdge> edgeItr = port.getEdges().iterator(); edgeItr.hasNext();) {
+ DataEdge edge = edgeItr.next();
+ // Remove the edge from from-port.
+ DataPort fromPort = edge.getFromPort();
+ fromPort.removeEdge(edge);
+ // remove the edge from this port. This is necessary so that
+ // type update works properly.
+ edgeItr.remove();
+
+ // Remove the edge from the graph.
+ this.edges.remove(edge);
+ fromPort.getNode().edgeWasRemoved(edge);
+ }
+ // Remove the port from the node.
+ portItr.remove();
+ // Remove the port from the graph.
+ this.ports.remove(port);
+ }
+
+ // Remove edges connected to output ports.
+ for (Iterator<DataPort> portItr = nodeImpl.getOutputPorts().iterator(); portItr.hasNext();) {
+ DataPort port = portItr.next();
+ for (Iterator<DataEdge> edgeItr = port.getEdges().iterator(); edgeItr.hasNext();) {
+ DataEdge edge = edgeItr.next();
+ DataPort toPort = edge.getToPort();
+ toPort.removeEdge(edge);
+ edgeItr.remove();
+ this.edges.remove(edge);
+ toPort.getNode().edgeWasRemoved(edge);
+ }
+ portItr.remove();
+ this.ports.remove(port);
+ }
+
+ for (Iterator<ControlPort> portItr = nodeImpl.getControlOutPorts().iterator(); portItr.hasNext();) {
+ PortImpl port = portItr.next();
+ for (Iterator<? extends EdgeImpl> edgeItr = port.getEdges().iterator(); edgeItr.hasNext();) {
+ EdgeImpl edge = edgeItr.next();
+ PortImpl toPort = edge.getToPort();
+ toPort.removeEdge(edge);
+ edgeItr.remove();
+ this.edges.remove(edge);
+ toPort.getNode().edgeWasRemoved(edge);
+ }
+ portItr.remove();
+ this.ports.remove(port);
+ }
+
+ PortImpl controlInPort = nodeImpl.getControlInPort();
+ if (controlInPort != null) {
+ for (Iterator<? extends EdgeImpl> edgeItr = controlInPort.getEdges().iterator(); edgeItr.hasNext();) {
+ EdgeImpl edge = edgeItr.next();
+ PortImpl fromPort = edge.getFromPort();
+ fromPort.removeEdge(edge);
+ edgeItr.remove();
+ this.edges.remove(edge);
+ fromPort.getNode().edgeWasRemoved(edge);
+ }
+ this.ports.remove(controlInPort);
+ }
+
+ PortImpl eprPort = nodeImpl.getEPRPort();
+ if (eprPort != null) {
+ for (Iterator<? extends EdgeImpl> edgeItr = eprPort.getEdges().iterator(); edgeItr.hasNext();) {
+ EdgeImpl edge = edgeItr.next();
+ PortImpl toPort = edge.getToPort();
+ toPort.removeEdge(edge);
+ edgeItr.remove();
+ this.edges.remove(edge);
+ toPort.getNode().edgeWasRemoved(edge);
+ }
+ this.ports.remove(eprPort);
+ }
+
+ this.nodes.remove(node);
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#getNode(java.lang.String)
+ */
+ public NodeImpl getNode(String nodeID) {
+ for (NodeImpl node : this.nodes) {
+ if (nodeID.equals(node.getID())) {
+ return node;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @param port
+ * @throws GraphException
+ */
+ public void removePort(Port port) throws GraphException {
+ if (port == null) {
+ throw new IllegalArgumentException("null");
+ }
+ if (!this.ports.contains(port)) {
+ throw new GraphException("The graph doesn't contain the port that is being removed.");
+ }
+
+ // copy it so that we can remove edge without worrying about the
+ // iteration issue.
+ ArrayList<Edge> edgesToBeRemoved = new ArrayList<Edge>(port.getEdges());
+ for (Edge edge : edgesToBeRemoved) {
+ removeEdge(edge);
+ }
+
+ this.ports.remove(port);
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#getPort(java.lang.String)
+ */
+ public PortImpl getPort(String portID) {
+ for (PortImpl port : this.ports) {
+ if (portID.equals(port.getID())) {
+ return port;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#addEdge(org.apache.airavata.workflow.model.graph.Port,
+ * org.apache.airavata.workflow.model.graph.Port)
+ */
+ public Edge addEdge(Port fromPort, Port toPort) throws GraphException {
+ if (containsEdge(fromPort, toPort)) {
+ // The edge already exists. Doesn't create a new one.
+ return null;
+ }
+
+ if (!this.ports.contains(fromPort) || !this.ports.contains(toPort)) {
+ // The specified port doesn't belong to the graph.
+ throw new GraphException("The graph doesn't contain the specified port.");
+ }
+
+ PortImpl fromPortImpl = (PortImpl) fromPort;
+ PortImpl toPortImpl = (PortImpl) toPort;
+ NodeImpl fromNode = fromPortImpl.getNode();
+ NodeImpl toNode = toPortImpl.getNode();
+
+ EdgeImpl edge = this.factory.createEdge(fromPort, toPort);
+
+ edge.setFromPort(fromPortImpl);
+ edge.setToPort(toPortImpl);
+ fromPortImpl.addEdge(edge);
+ toPortImpl.addEdge(edge);
+ addEdge(edge);
+
+ try {
+ fromNode.edgeWasAdded(edge);
+ toNode.edgeWasAdded(edge);
+ return edge;
+ } catch (GraphException e) {
+ removeEdge(edge);
+ throw e;
+ }
+
+ }
+
+ /**
+ * @throws GraphException
+ * @see org.apache.airavata.workflow.model.graph.Graph#removeEdge(org.apache.airavata.workflow.model.graph.Edge)
+ */
+ public void removeEdge(Edge edge) throws GraphException {
+ if (!this.edges.contains(edge)) {
+ throw new GraphException("The graph doesn't contain the specified edge.");
+ }
+ EdgeImpl edgeImpl = (EdgeImpl) edge;
+
+ PortImpl fromPort = edgeImpl.getFromPort();
+ PortImpl toPort = edgeImpl.getToPort();
+
+ NodeImpl fromNode = fromPort.getNode();
+ NodeImpl toNode = toPort.getNode();
+
+ fromPort.removeEdge(edgeImpl);
+ toPort.removeEdge(edgeImpl);
+
+ this.edges.remove(edgeImpl);
+
+ // This has to be after removing edges.
+ fromNode.edgeWasRemoved(edge);
+ toNode.edgeWasRemoved(edge);
+ }
+
+ /**
+ * @throws GraphException
+ * @see org.apache.airavata.workflow.model.graph.Graph#removeEdge(org.apache.airavata.workflow.model.graph.Port,
+ * org.apache.airavata.workflow.model.graph.Port)
+ */
+ public void removeEdge(Port fromPort, Port toPort) throws GraphException {
+ Collection<? extends Edge> fromEdges = fromPort.getEdges();
+ for (Edge fromEdge : fromEdges) {
+ if (fromEdge.getToPort() == toPort) {
+ // It's OK to remove this way because it will exit the loop
+ // right away.
+ removeEdge(fromEdge);
+ return;
+ }
+ }
+ throw new WorkflowRuntimeException("No edge exist between two ports.");
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#containsEdge(org.apache.airavata.workflow.model.graph.Port,
+ * org.apache.airavata.workflow.model.graph.Port)
+ */
+ public boolean containsEdge(Port fromPort, Port toPort) {
+ for (Edge fromEdge : fromPort.getEdges()) {
+ Collection<? extends Edge> toEdges = toPort.getEdges();
+ if (toEdges.contains(fromEdge)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @throws GraphException
+ * @see org.apache.airavata.workflow.model.graph.Graph#importGraph(org.apache.airavata.workflow.model.graph.Graph)
+ */
+ public void importGraph(Graph graph) throws GraphException {
+
+ // Does not support other implementations.
+ if (!(graph instanceof GraphImpl)) {
+ throw new GraphException("Cannot import this graph implementation");
+ }
+
+ GraphImpl graphImpl = (GraphImpl) graph;
+
+ for (NodeImpl node : graphImpl.getNodes()) {
+ addNode(node);
+ // Recreates the ID so that it doesn't conflict with the existing
+ // one.
+ node.createID();
+ // Changes the position.
+ Point position = node.getPosition();
+ node.setPosition(new Point(position.x + 5, position.y + 5));
+ }
+
+ for (PortImpl port : graphImpl.getPorts()) {
+ addPort(port);
+ }
+
+ for (EdgeImpl edge : graphImpl.getEdges()) {
+ addEdge(edge);
+ }
+ }
+
+ /**
+ * @see org.apache.airavata.workflow.model.graph.Graph#toXML()
+ */
+ public XmlElement toXML() {
+
+ XmlElement graphElement = XMLUtil.BUILDER.newFragment(GraphSchema.NS, GraphSchema.GRAPH_TAG);
+
+ graphElement.setAttributeValue(GraphSchema.NS, GraphSchema.XBAYA_VERSION_ATTRIBUTE, ApplicationVersion.VERSION);
+
+ XmlElement idElement = graphElement.addElement(GraphSchema.NS, GraphSchema.GRAPH_ID_TAG);
+ idElement.addChild(getID());
+
+ if (this.name != null) {
+ XmlElement nameElement = graphElement.addElement(GraphSchema.NS, GraphSchema.GRAPH_NAME_TAG);
+ nameElement.addChild(getName());
+ }
+
+ if (this.description != null) {
+ XmlElement descriptionElement = graphElement.addElement(GraphSchema.NS, GraphSchema.GRAPH_DESCRIPTION_TAG);
+ descriptionElement.addChild(getDescription());
+ }
+
+ toXML(graphElement);
+
+ for (NodeImpl node : this.nodes) {
+ XmlElement nodeElement = node.toXML();
+ graphElement.addChild(nodeElement);
+ }
+
+ for (PortImpl port : this.ports) {
+ XmlElement portElement = port.toXML();
+ graphElement.addChild(portElement);
+ }
+
+ for (EdgeImpl edge : this.edges) {
+ XmlElement edgeElement = edge.toXML();
+ graphElement.addChild(edgeElement);
+ }
+
+ return graphElement;
+ }
+
+ /**
+ * @param graphElement
+ */
+ protected void toXML(@SuppressWarnings("unused") XmlElement graphElement) {
+ // For subclass to overwrite.
+ }
+
+ /**
+ * @param graphElement
+ * @throws GraphException
+ */
+ protected void parse(XmlElement graphElement) throws GraphException {
+ String version = graphElement.attributeValue(GraphSchema.NS, GraphSchema.XBAYA_VERSION_ATTRIBUTE);
+ logger.info("parsing a workflow created by version " + version);
+
+ XmlElement idElement = graphElement.element(GraphSchema.GRAPH_ID_TAG);
+ if (idElement != null) {
+ this.id = idElement.requiredText();
+ }
+
+ XmlElement nameElement = graphElement.element(GraphSchema.GRAPH_NAME_TAG);
+ if (nameElement != null) {
+ this.name = nameElement.requiredText();
+ }
+
+ XmlElement descriptionElement = graphElement.element(GraphSchema.GRAPH_DESCRIPTION_TAG);
+ if (descriptionElement != null) {
+ this.description = descriptionElement.requiredText();
+ }
+
+ for (XmlElement nodeElement : graphElement.elements(null, GraphSchema.NODE_TAG)) {
+ NodeImpl nodeImpl = this.factory.createNode(nodeElement);
+ // need to call this to set this graph to the node.
+ addNode(nodeImpl);
+ }
+
+ for (XmlElement portElement : graphElement.elements(null, GraphSchema.PORT_TAG)) {
+ PortImpl port = this.factory.createPort(portElement);
+ // need to call this to set this graph to the port.
+ this.addPort(port);
+ }
+
+ for (XmlElement edgeElement : graphElement.elements(null, GraphSchema.EDGE_TAG)) {
+ EdgeImpl edge = this.factory.createEdge(edgeElement);
+ // need to call this to set this graph to the edge.
+ this.addEdge(edge);
+ }
+
+ indexToPointer();
+ }
+
+ /**
+ * Adds a node.
+ *
+ * @param node
+ * the node to add
+ */
+ protected void addNode(NodeImpl node) {
+ node.setGraph(this);
+ // if this is a Stream now put it at the begining
+ if (node instanceof StreamSourceNode) {
+ this.nodes.add(0, node);
+ } else {
+ this.nodes.add(node);
+ }
+ }
+
+ /**
+ * @param port
+ */
+ protected void addPort(PortImpl port) {
+ port.setGraph(this);
+ this.ports.add(port);
+ }
+
+ /**
+ * Converts indexes to references. This method is called after reading the graph from an XML file.
+ *
+ * @throws GraphException
+ */
+ protected void indexToPointer() throws GraphException {
+ for (NodeImpl node : this.nodes) {
+ node.indexToPointer();
+ }
+ for (PortImpl port : this.ports) {
+ port.indexToPointer();
+ }
+ for (EdgeImpl edge : this.edges) {
+ edge.indexToPointer();
+ }
+ }
+
+ /**
+ * @param edge
+ */
+ private void addEdge(EdgeImpl edge) {
+ edge.setGraph(this);
+ this.edges.add(edge);
+ }
+
+ // private void createID() {
+ // Date date = new Date();
+ // SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmss_S");
+ // String time = format.format(date);
+ //
+ // this.id = StringUtil.convertToJavaIdentifier(this.name) + "_" + time;
+ // }
+
+ /**
+ * @throws GraphException
+ */
+ public void fixParameterNodes() {
+ // XXX fix the ports of parameter nodes for 2.6.3 or before.
+ for (InputNode node : GraphUtil.getNodes(this, InputNode.class)) {
+ DataPort oldPort = node.getOutputPort(0);
+ if (oldPort instanceof WSPort) {
+ node.getOutputPorts().remove(oldPort);
+ this.ports.remove(oldPort);
+ SystemDataPort newPort = new SystemDataPort();
+ this.ports.add(newPort);
+ newPort.setKind(Kind.DATA_OUT);
+ newPort.setName(oldPort.getName());
+ newPort.setGraph(this);
+ newPort.setNode(node);
+ newPort.createID();
+ node.getOutputPorts().add(newPort);
+ for (DataEdge edge : oldPort.getEdges()) {
+ edge.setFromPort(newPort);
+ newPort.getEdges().add(edge);
+ }
+ }
+ }
+ for (OutputNode node : GraphUtil.getNodes(this, OutputNode.class)) {
+ DataPort oldPort = node.getInputPort(0);
+ if (oldPort instanceof WSPort) {
+ node.getInputPorts().remove(oldPort);
+ this.ports.remove(oldPort);
+ SystemDataPort newPort = new SystemDataPort();
+ this.ports.add(newPort);
+ newPort.setKind(Kind.DATA_IN);
+ newPort.setName(oldPort.getName());
+ newPort.setGraph(this);
+ newPort.setNode(node);
+ newPort.createID();
+ node.getInputPorts().add(newPort);
+ for (DataEdge edge : oldPort.getEdges()) {
+ edge.setToPort(newPort);
+ newPort.getEdges().add(edge);
+ }
+ }
+ }
+ }
+
+ /**
+ * This returns the number of input Nodes, this will be useful when adding unique Id for nodes
+ * @return
+ */
+ public int getCurrentInputNodeCount(){
+ int index=0;
+ for(Node node:nodes){
+ if(node instanceof InputNode){
+ index++;
+ }
+ }
+ return index;
+ }
+ /**
+ * This returns the number of input Nodes, this will be useful when adding unique Id for nodes
+ * @return
+ */
+ public int getCurrentOutputNodeCount(){
+ int index=0;
+ for(Node node:nodes){
+ if(node instanceof OutputNode){
+ index++;
+ }
+ }
+ return index;
+ }
+
+
+}
\ No newline at end of file