View Javadoc
1   package org.apache.maven.model.building;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static com.google.common.base.Predicates.in;
23  import static com.google.common.collect.Iterables.any;
24  import static com.google.common.collect.Iterables.concat;
25  import static com.google.common.collect.Iterables.transform;
26  import static java.util.Collections.singleton;
27  import static java.util.EnumSet.of;
28  import static org.apache.maven.model.building.ModelProblem.Severity.ERROR;
29  import static org.apache.maven.model.building.ModelProblem.Severity.FATAL;
30  
31  import java.util.Arrays;
32  import java.util.Collections;
33  
34  import org.apache.maven.model.building.ModelProblem.Severity;
35  
36  import com.google.common.base.Function;
37  import com.google.common.base.Predicates;
38  import com.google.common.collect.Iterables;
39  
40  /**
41   * There are various forms of results that are represented by this class:
42   * <ol>
43   * <li>success - in which case only the model field is set
44   * <li>success with warnings - model field + non-error model problems
45   * <li>error - no model, but diagnostics
46   * <li>error - (partial) model and diagnostics
47   * </ol>
48   * Could encode these variants as subclasses, but kept in one for now
49   * 
50   * @author bbusjaeger
51   * @param <T>
52   */
53  public class Result<T>
54  {
55  
56      /**
57       * Success without warnings
58       * 
59       * @param model
60       * @return
61       */
62      public static <T> Result<T> success( T model )
63      {
64          return success( model, Collections.<ModelProblem>emptyList() );
65      }
66  
67      /**
68       * Success with warnings
69       * 
70       * @param model
71       * @param problems
72       * @return
73       */
74      public static <T> Result<T> success( T model, Iterable<? extends ModelProblem> problems )
75      {
76          assert !hasErrors( problems );
77          return new Result<>( false, model, problems );
78      }
79  
80      /**
81       * Success with warnings
82       * 
83       * @param model
84       * @param results
85       * @return
86       */
87      public static <T> Result<T> success( T model, Result<?>... results )
88      {
89          return success( model, Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
90      }
91  
92      /**
93       * Error with problems describing the cause
94       *
95       * @param problems
96       * @return
97       */
98      public static <T> Result<T> error( Iterable<? extends ModelProblem> problems )
99      {
100         return error( null, problems );
101     }
102 
103     public static <T> Result<T> error( T model )
104     {
105         return error( model, Collections.<ModelProblem>emptyList() );
106     }
107 
108     public static <T> Result<T> error( Result<?> result )
109     {
110         return error( result.getProblems() );
111     }
112 
113     public static <T> Result<T> error( Result<?>... results )
114     {
115         return error( Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
116     }
117 
118     /**
119      * Error with partial result and problems describing the cause
120      *
121      * @param model
122      * @param problems
123      * @return
124      */
125     public static <T> Result<T> error( T model, Iterable<? extends ModelProblem> problems )
126     {
127         return new Result<>( true, model, problems );
128     }
129 
130     /**
131      * New result - determine whether error or success by checking problems for errors
132      * 
133      * @param model
134      * @param problems
135      * @return
136      */
137     public static <T> Result<T> newResult( T model, Iterable<? extends ModelProblem> problems )
138     {
139         return new Result<>( hasErrors( problems ), model, problems );
140     }
141 
142     /**
143      * New result consisting of given result and new problem. Convenience for newResult(result.get(),
144      * concat(result.getProblems(),problems)).
145      * 
146      * @param result
147      * @param problem
148      * @return
149      */
150     public static <T> Result<T> addProblem( Result<T> result, ModelProblem problem )
151     {
152         return addProblems( result, singleton( problem ) );
153     }
154 
155     /**
156      * New result that includes the given
157      *
158      * @param result
159      * @param problems
160      * @return
161      */
162     public static <T> Result<T> addProblems( Result<T> result, Iterable<? extends ModelProblem> problems )
163     {
164         return new Result<>( result.hasErrors() || hasErrors( problems ), result.get(), concat( result.getProblems(),
165                                                                                                  problems ) );
166     }
167 
168     public static <T> Result<T> addProblems( Result<T> result, Result<?>... results )
169     {
170         return addProblems( result, Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
171     }
172 
173     /**
174      * Turns the given results into a single result by combining problems and models into single collection.
175      * 
176      * @param results
177      * @return
178      */
179     public static <T> Result<Iterable<T>> newResultSet( Iterable<? extends Result<? extends T>> results )
180     {
181         final boolean hasErrors = any( transform( results, new Function<Result<?>, Boolean>()
182         {
183             @Override
184             public Boolean apply( Result<?> input )
185             {
186                 return input.hasErrors();
187             }
188         } ), Predicates.equalTo( true ) );
189         final Iterable<T> models = transform( results, new Function<Result<? extends T>, T>()
190         {
191             @Override
192             public T apply( Result<? extends T> input )
193             {
194                 return input.get();
195             }
196         } );
197         final Iterable<ModelProblem> problems = concat( transform( results, GET_PROBLEMS ) );
198         return new Result<>( hasErrors, models, problems );
199     }
200 
201     // helper to determine if problems contain error
202     private static boolean hasErrors( Iterable<? extends ModelProblem> problems )
203     {
204         return any( transform( problems, new Function<ModelProblem, Severity>()
205         {
206             @Override
207             public Severity apply( ModelProblem input )
208             {
209                 return input.getSeverity();
210             }
211         } ), in( of( ERROR, FATAL ) ) );
212     }
213 
214     /**
215      * Class definition
216      */
217 
218     private final boolean errors;
219 
220     private final T value;
221 
222     private final Iterable<? extends ModelProblem> problems;
223 
224     private Result( boolean errors, T model, Iterable<? extends ModelProblem> problems )
225     {
226         this.errors = errors;
227         this.value = model;
228         this.problems = problems;
229     }
230 
231     public Iterable<? extends ModelProblem> getProblems()
232     {
233         return problems;
234     }
235 
236     public T get()
237     {
238         return value;
239     }
240 
241     public boolean hasErrors()
242     {
243         return errors;
244     }
245 
246     private static final Function<Result<?>, Iterable<? extends ModelProblem>> GET_PROBLEMS =
247         new Function<Result<?>, Iterable<? extends ModelProblem>>()
248         {
249             @Override
250             public Iterable<? extends ModelProblem> apply( Result<?> input )
251             {
252                 return input.getProblems();
253             }
254         };
255 }