blob: b5ea456f756ebafc8969cb465c40fad20dc1cc97 [file] [log] [blame]
jaegonkim6a7b5242018-09-12 23:09:42 +09001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.workflow.api;
17
18import com.google.common.base.MoreObjects;
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.ImmutableSet;
21import com.google.common.collect.Lists;
22import com.google.common.collect.Sets;
23import org.onlab.osgi.DefaultServiceDirectory;
24import org.onlab.osgi.ServiceNotFoundException;
25
26import java.lang.reflect.Modifier;
27import java.net.URI;
28import java.util.List;
29import java.util.Objects;
30import java.util.Set;
31
32/**
33 * Class for immutable list workflow.
34 */
35public final class ImmutableListWorkflow extends AbstractWorkflow {
36
37 /**
38 * Init worklet type(class name of init worklet type).
39 */
40 private String initWorkletType;
41
42 /**
43 * List of worklet.
44 */
45 private List<String> workletTypeList;
46
47 /**
48 * Set of workflow attributes.
49 */
50 private Set<WorkflowAttribute> attributes;
51
52 /**
53 * Constructor of ImmutableListWorkflow.
54 * @param builder builder of ImmutableListWorkflow
55 */
56 private ImmutableListWorkflow(Builder builder) {
57 super(builder.id);
58 this.initWorkletType = builder.initWorkletType;
59 workletTypeList = ImmutableList.copyOf(builder.workletTypeList);
60 attributes = ImmutableSet.copyOf(builder.attributes);
61 }
62
63 @Override
64 public Worklet init(WorkflowContext context) throws WorkflowException {
65 if (Objects.isNull(initWorkletType)) {
66 return null;
67 }
68
69 return getWorkletInstance(initWorkletType);
70 }
71
72
73 @Override
74 public Worklet next(WorkflowContext context) throws WorkflowException {
75
76 int cnt = 0;
77 for (int i = 0; i < workletTypeList.size(); i++) {
78
79 if (cnt++ > Worklet.MAX_WORKS) {
80 throw new WorkflowException("Maximum worklet execution exceeded");
81 }
82
83 String workletType = workletTypeList.get(i);
84
85 if (Worklet.Common.COMPLETED.tag().equals(workletType)) {
86 return Worklet.Common.COMPLETED;
87 }
88
89 if (Worklet.Common.INIT.tag().equals(workletType)) {
90 continue;
91 }
92
93 Worklet worklet = getWorkletInstance(workletType);
94 Class workClass = worklet.getClass();
95
96 if (BranchWorklet.class.isAssignableFrom(workClass)) {
97 Class nextClass = ((BranchWorklet) worklet).next(context);
98 if (nextClass == null) {
99 throw new WorkflowException("Invalid next Worklet for " + workClass);
100 }
101
102 // TODO : it does not support duplicated use of WorkType. It needs to consider label concept
103 int nextIdx = getClassIndex(nextClass);
104 if (nextIdx == -1) {
105 throw new WorkflowException("Failed to find next " + nextClass + " for " + workClass);
106 }
107
108 i = nextIdx;
109 continue;
110
111 } else {
112 if (worklet.isNext(context)) {
113 return worklet;
114 }
115 }
116 }
117 return Worklet.Common.COMPLETED;
118 }
119
120 @Override
121 public Worklet getWorkletInstance(String workletType) throws WorkflowException {
122
123 WorkflowStore store;
124 try {
125 store = DefaultServiceDirectory.getService(WorkflowStore.class);
126 } catch (ServiceNotFoundException e) {
127 throw new WorkflowException(e);
128 }
129
130 Class workClass;
131 try {
132 workClass = store.getClass(workletType);
133 } catch (ClassNotFoundException e) {
134 throw new WorkflowException(e);
135 }
136
137 if (!isAllowed(workClass)) {
138 throw new WorkflowException("Not allowed class(" + workClass.getSimpleName() + ")");
139 }
140
141 Worklet worklet;
142 try {
143 worklet = (Worklet) workClass.newInstance();
144 } catch (Exception e) {
145 throw new WorkflowException(e);
146 }
147
148 return worklet;
149 }
150
151 @Override
152 public Set<WorkflowAttribute> attributes() {
153 return ImmutableSet.copyOf(attributes);
154 }
155
156 /**
157 * Gets index of class in worklet type list.
158 * @param aClass class to get index
159 * @return index of class in worklet type list
160 */
161 private int getClassIndex(Class aClass) {
162 for (int i = 0; i < workletTypeList.size(); i++) {
163 if (Objects.equals(aClass.getName(), workletTypeList.get(i))) {
164 return i;
165 }
166 }
167 return -1;
168 }
169
170 /**
171 * Checks whether class is allowed class or not.
172 * @param clazz class to check
173 * @return Check result
174 */
175 private boolean isAllowed(Class clazz) {
176 // non static inner class is not allowed
177 if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) {
178 return false;
179 }
180 // enum is not allowed
181 if (clazz.isEnum()) {
182 return false;
183 }
184 // class should be subclass of Work
185 if (!Worklet.class.isAssignableFrom(clazz)) {
186 return false;
187 }
188 return true;
189 }
190
191 @Override
192 public int hashCode() {
193 return Objects.hash(this.toString());
194 }
195
196 @Override
197 public boolean equals(Object obj) {
198 if (obj == this) {
199 return true;
200 }
201 if (!(obj instanceof EventTask)) {
202 return false;
203 }
204 return Objects.equals(this.id(), ((ImmutableListWorkflow) obj).id())
205 && Objects.equals(this.initWorkletType, ((ImmutableListWorkflow) obj).initWorkletType)
206 && Objects.equals(this.workletTypeList, ((ImmutableListWorkflow) obj).workletTypeList)
207 && Objects.equals(this.attributes, ((ImmutableListWorkflow) obj).attributes);
208 }
209
210 @Override
211 public String toString() {
212 return MoreObjects.toStringHelper(getClass())
213 .add("id", id())
214 .add("initWorklet", initWorkletType)
215 .add("workList", workletTypeList)
216 .add("attributes", attributes)
217 .toString();
218 }
219
220 /**
221 * Gets a instance of builder.
222 * @return instance of builder
223 */
224 public static Builder builder() {
225 return new Builder();
226 }
227
228 /**
229 * Builder of ImmutableListWorkflow.
230 */
231 public static class Builder {
232
233 private URI id;
234 private String initWorkletType;
235 private final List<String> workletTypeList = Lists.newArrayList();
236 private final Set<WorkflowAttribute> attributes = Sets.newHashSet();
237
238 /**
239 * Sets id of immutable list workflow.
240 * @param uri id of immutable list workflow
241 * @return builder
242 */
243 public Builder id(URI uri) {
244 this.id = uri;
245 workletTypeList.add(Worklet.Common.INIT.tag());
246 return this;
247 }
248
249 /**
250 * Sets init worklet class name of immutable list workflow.
251 * @param workletClassName class name of worklet
252 * @return builder
253 */
254 public Builder init(String workletClassName) {
255 this.initWorkletType = workletClassName;
256 return this;
257 }
258
259 /**
260 * Chains worklet class name of immutable list workflow.
261 * @param workletClassName class name of worklet
262 * @return builder
263 */
264 public Builder chain(String workletClassName) {
265 workletTypeList.add(workletClassName);
266 return this;
267 }
268
269 /**
270 * Adds workflow attribute.
271 * @param attribute workflow attribute to be added
272 * @return builder
273 */
274 public Builder attribute(WorkflowAttribute attribute) {
275 attributes.add(attribute);
276 return this;
277 }
278
279 /**
280 * Builds ImmutableListWorkflow.
281 * @return instance of ImmutableListWorkflow
282 */
283 public ImmutableListWorkflow build() {
284 workletTypeList.add(Worklet.Common.COMPLETED.tag());
285 return new ImmutableListWorkflow(this);
286 }
287 }
288}