1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.pipeline.validation;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.Iterator;
23 import java.util.List;
24 import org.apache.commons.pipeline.Pipeline;
25 import org.apache.commons.pipeline.Stage;
26 import org.apache.commons.pipeline.StageDriverFactory;
27
28
29
30
31
32
33
34
35 public class SimplePipelineValidator implements PipelineValidator {
36
37
38 public SimplePipelineValidator() {
39 }
40
41
42
43
44
45
46
47
48 public List<ValidationFailure> validate(Pipeline pipeline) {
49 List<ValidationFailure> errors = new ArrayList<ValidationFailure>();
50 Stage previous = null;
51 for (Iterator<Stage> iter = pipeline.getStages().iterator(); iter.hasNext();) {
52 Stage stage = iter.next();
53
54
55 if (previous != null) {
56 if (!ValidationUtils.canSucceed(previous, stage)) {
57 errors.add(new ValidationFailure(ValidationFailure.Type.STAGE_CONNECT,
58 "Stage cannot consume output of prior stage.", previous, stage));
59 }
60 }
61
62 if (stage.getClass().isAnnotationPresent(ProductionOnBranch.class)) {
63 ProductionOnBranch pob = stage.getClass().getAnnotation(ProductionOnBranch.class);
64 errors.addAll(validateBranchConnect(pipeline, pob.branchKey(), stage));
65 } else if (stage.getClass().isAnnotationPresent(Branches.class)) {
66 Branches branches = stage.getClass().getAnnotation(Branches.class);
67
68 for (ProductionOnBranch pob : branches.productionOnBranches()) {
69 errors.addAll(validateBranchConnect(pipeline, pob.branchKey(), stage));
70 }
71
72
73 if (previous != null) {
74 for (String branchKey : branches.producesConsumedOnBranches()) {
75 errors.addAll(validateBranchConnect(pipeline, branchKey, previous));
76 }
77 }
78 }
79
80
81
82 if (stage.getClass().isAnnotationPresent(ProducedTypes.class)) {
83
84 if (stage.getClass().getAnnotation(ProducedTypes.class).value().length == 0) {
85 if (iter.hasNext()) errors.add(new ValidationFailure(ValidationFailure.Type.STAGE_CONNECT,
86 "Stage with no production is not at terminus of pipeline.", stage, iter.next()));
87 break;
88 }
89
90 previous = stage;
91 }
92 }
93
94
95 for (Pipeline branch : pipeline.getBranches().values()) {
96 errors.addAll(validate(branch));
97 }
98
99 return errors;
100 }
101
102
103
104
105 private List<ValidationFailure> validateBranchConnect(Pipeline pipeline, String branchKey, Stage upstreamStage) {
106 List<ValidationFailure> errors = new ArrayList<ValidationFailure>();
107 Pipeline branch = pipeline.getBranches().get(branchKey);
108
109 if (branch == null) {
110 errors.add(new ValidationFailure(ValidationFailure.Type.BRANCH_NOT_FOUND,
111 "Branch not found for production key " + branchKey, upstreamStage, null));
112 } else if (branch.getStages().isEmpty()) {
113 errors.add(new ValidationFailure(ValidationFailure.Type.BRANCH_CONNECT,
114 "Branch pipeline for key " + branchKey + " has no stages.", upstreamStage, null));
115 } else if (!ValidationUtils.canSucceed(upstreamStage, branch.getStages().get(0))) {
116 errors.add(new ValidationFailure(ValidationFailure.Type.BRANCH_CONNECT,
117 "Branch " + branchKey + " cannot consume data produced by stage.", upstreamStage, branch.getStages().get(0)));
118 }
119
120 return errors;
121 }
122
123
124
125
126
127
128
129
130
131 public List<ValidationFailure> validateAddStage(Pipeline pipeline, Stage stage, StageDriverFactory driverFactory) {
132 if (pipeline.getStages().isEmpty()) return Collections.emptyList();
133
134
135 List<ValidationFailure> errors = new ArrayList<ValidationFailure>();
136
137
138 Stage previous = null;
139 for (int i = pipeline.getStages().size() - 1; i >= 0; i--) {
140 Stage test = pipeline.getStages().get(i);
141 if (test.getClass().isAnnotationPresent(ProducedTypes.class)) {
142 if (test.getClass().getAnnotation(ProducedTypes.class).value().length == 0) {
143 errors.add(new ValidationFailure(ValidationFailure.Type.STAGE_CONNECT,
144 "Attempt to add stage to pipeline with no production at terminus.", test, stage));
145 } else {
146 previous = test;
147 }
148
149 break;
150 }
151 }
152
153 if (previous != null) {
154 if (!ValidationUtils.canSucceed(previous, stage)) {
155 errors.add(new ValidationFailure(ValidationFailure.Type.STAGE_CONNECT,
156 "Stage cannot consume output of prior stage.", previous, stage));
157
158
159
160 }
161 }
162
163 return errors;
164 }
165
166
167
168
169
170
171
172
173
174 public List<ValidationFailure> validateAddBranch(Pipeline pipeline, String branchKey, Pipeline branch) {
175 return Collections.emptyList();
176 }
177 }