View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package com.github.dexecutor.executor.graph;
19  
20  import java.util.Collection;
21  import java.util.LinkedHashSet;
22  import java.util.Set;
23  
24  /**
25   * Dependency would be constructed based on this APIs, Dexecutor uses this data structure to represent the dependencies between tasks
26   * @author Nadeem Mohammad
27   *
28   * @param <T> Type of Node/Task ID
29   * @param <R> Type of Node/Task result
30   */
31  public interface Graph<T extends Comparable<T>, R> {
32  	/**
33  	 * Should add the two nodes in the datastructure in such a way that {@code evalFirstValue} should be evaluated before {@code evalAfterValue}.
34  	 * Nodes should be created only if it is not already added.
35  	 * 
36  	 * @param evalFirstValue
37  	 * @param evalAfterValue
38  	 */
39  	void addDependency(final T evalFirstValue, final T evalAfterValue);
40  	/**
41  	 * Adds the given node to the datastructure whith out any dependency
42  	 * Nodes should be created only if it is not already added.
43  	 * @param nodeValue
44  	 */
45  	void addIndependent(final T nodeValue);
46  	/**
47  	 * Returns the Set of nodes for which there is no incoming dependencies.
48  	 * @return set of initial nodes
49  	 */
50  	Set<Node<T, R>> getInitialNodes();
51  	/**
52  	 * Retruns the set of nodes for which there is no outgoing dependencies.
53  	 * @return set of leaf nodes
54  	 */
55  	Set<Node<T, R>> getLeafNodes();
56  	/**
57  	 * Returns all nodes in this graph
58  	 * @return all nodes in this graph
59  	 */
60  	Collection<Node<T, R>> allNodes();
61  	/**
62  	 * Returns the total number of nodes in this graph
63  	 * 
64  	 * @return total number of nodes in this graph
65  	 */
66  	int size();
67  	
68  	/**
69  	 * A node representation in this graph, every node may have set of incoming edges and outgoing edges, a node is represented by unique value
70  	 * 
71  	 * @author Nadeem Mohammad
72  	 *
73  	 * @param <T>
74  	 */
75  	public final class Node<T, R> {
76  		/**
77  		 * Unique id of the node
78  		 */
79  		private T value;
80  		/**
81  		 * Execution result of this node
82  		 */
83  		private R result;
84  		/**
85  		 * Execution status of this node
86  		 */
87  		private NodeStatus status;
88  		/**
89  		 * incoming dependencies for this node
90  		 */
91  	    private Set<Node<T, R>> inComingEdges = new LinkedHashSet<Graph.Node<T, R>>();
92  	    /**
93  	     * outgoing dependencies for this node
94  	     */
95  	    private Set<Node<T, R>> outGoingEdges = new LinkedHashSet<Graph.Node<T, R>>();
96  	    /**
97  	     * Constructs the node with the given node Id
98  	     * @param val
99  	     */
100 	    public Node(final T val) {
101 			this.value = val;
102 		}
103 	    /**
104 	     * Add the given node, to the set of incoming nodes
105 	     * @param node
106 	     */
107 	    public void addInComingNode(final Node<T, R> node) {	        
108 	        this.inComingEdges.add(node);
109 	    }
110 	    /**
111 	     * add the given to the set of out going nodes
112 	     * @param node
113 	     */
114 	    public void addOutGoingNode(final Node<T, R> node) {	        
115 	        this.outGoingEdges.add(node);
116 	    }
117 	    /**
118 	     * 
119 	     * @return the set of incoming nodes
120 	     */
121 	    public Set<Node<T, R>> getInComingNodes() {
122 	        return this.inComingEdges;
123 	    }
124 	    /**
125 	     * 
126 	     * @return set of out going nodes
127 	     */
128 	    public Set<Node<T, R>> getOutGoingNodes() {
129 	        return this.outGoingEdges;
130 	    }
131 	    /**
132 	     * 
133 	     * @return the node's value
134 	     */
135 		public T getValue() {
136 			return this.value;
137 		}
138 
139 		public R getResult() {
140 			return result;
141 		}
142 
143 		public void setResult(final R result) {
144 			this.result = result;
145 		}
146 		
147 		public boolean isSuccess() {
148 			return NodeStatus.SUCCESS.equals(this.status);
149 		}
150 		
151 		public boolean isErrored() {
152 			return NodeStatus.ERRORED.equals(this.status);
153 		}
154 
155 		public boolean isSkipped() {
156 			return NodeStatus.SKIPPED.equals(this.status);
157 		}
158 
159 		public void setSuccess() {
160 			this.status = NodeStatus.SUCCESS;
161 		}
162 		
163 		public void setErrored() {
164 			this.status = NodeStatus.ERRORED;
165 		}
166 		
167 		public void setSkipped() {
168 			this.status = NodeStatus.SKIPPED;
169 		}
170 
171 		@Override
172 		public int hashCode() {
173 			final int prime = 31;
174 			int result = 1;
175 			result = prime * result + ((this.value == null) ? 0 : this.value.hashCode());
176 			return result;
177 		}
178 
179 		@Override
180 		public boolean equals(final Object obj) {
181 			if (obj == this) {
182 				return true;
183 			}
184 			if (obj == null || obj.getClass() != this.getClass()) {
185 				return false;
186 			}
187 			@SuppressWarnings("unchecked")
188 			Node<T, R> other = (Node<T, R>) obj;
189 
190 			return this.value.equals(other.value);
191 		}
192 
193 	    @Override
194 	    public String toString() {
195 	    	return String.valueOf(this.value);
196 	    }
197 	}
198 	/**
199 	 * Represents node's execution status
200 	 * 
201 	 * @author Nadeem Mohammad
202 	 *
203 	 */
204 	public enum NodeStatus {
205 		ERRORED,SKIPPED,SUCCESS;
206 	}
207 }