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       */
61      public static <T> Result<T> success( T model )
62      {
63          return success( model, Collections.<ModelProblem>emptyList() );
64      }
65  
66      /**
67       * Success with warnings
68       *
69       * @param model
70       * @param problems
71       */
72      public static <T> Result<T> success( T model, Iterable<? extends ModelProblem> problems )
73      {
74          assert !hasErrors( problems );
75          return new Result<>( false, model, problems );
76      }
77  
78      /**
79       * Success with warnings
80       *
81       * @param model
82       * @param results
83       */
84      public static <T> Result<T> success( T model, Result<?>... results )
85      {
86          return success( model, Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
87      }
88  
89      /**
90       * Error with problems describing the cause
91       *
92       * @param problems
93       */
94      public static <T> Result<T> error( Iterable<? extends ModelProblem> problems )
95      {
96          return error( null, problems );
97      }
98  
99      public static <T> Result<T> error( T model )
100     {
101         return error( model, Collections.<ModelProblem>emptyList() );
102     }
103 
104     public static <T> Result<T> error( Result<?> result )
105     {
106         return error( result.getProblems() );
107     }
108 
109     public static <T> Result<T> error( Result<?>... results )
110     {
111         return error( Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
112     }
113 
114     /**
115      * Error with partial result and problems describing the cause
116      *
117      * @param model
118      * @param problems
119      */
120     public static <T> Result<T> error( T model, Iterable<? extends ModelProblem> problems )
121     {
122         return new Result<>( true, model, problems );
123     }
124 
125     /**
126      * New result - determine whether error or success by checking problems for errors
127      *
128      * @param model
129      * @param problems
130      */
131     public static <T> Result<T> newResult( T model, Iterable<? extends ModelProblem> problems )
132     {
133         return new Result<>( hasErrors( problems ), model, problems );
134     }
135 
136     /**
137      * New result consisting of given result and new problem. Convenience for newResult(result.get(),
138      * concat(result.getProblems(),problems)).
139      *
140      * @param result
141      * @param problem
142      */
143     public static <T> Result<T> addProblem( Result<T> result, ModelProblem problem )
144     {
145         return addProblems( result, singleton( problem ) );
146     }
147 
148     /**
149      * New result that includes the given
150      *
151      * @param result
152      * @param problems
153      */
154     public static <T> Result<T> addProblems( Result<T> result, Iterable<? extends ModelProblem> problems )
155     {
156         return new Result<>( result.hasErrors() || hasErrors( problems ), result.get(), concat( result.getProblems(),
157                                                                                                  problems ) );
158     }
159 
160     public static <T> Result<T> addProblems( Result<T> result, Result<?>... results )
161     {
162         return addProblems( result, Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) );
163     }
164 
165     /**
166      * Turns the given results into a single result by combining problems and models into single collection.
167      *
168      * @param results
169      */
170     public static <T> Result<Iterable<T>> newResultSet( Iterable<? extends Result<? extends T>> results )
171     {
172         final boolean hasErrors = any( transform( results, new Function<Result<?>, Boolean>()
173         {
174             @Override
175             public Boolean apply( Result<?> input )
176             {
177                 return input.hasErrors();
178             }
179         } ), Predicates.equalTo( true ) );
180         final Iterable<T> models = transform( results, new Function<Result<? extends T>, T>()
181         {
182             @Override
183             public T apply( Result<? extends T> input )
184             {
185                 return input.get();
186             }
187         } );
188         final Iterable<ModelProblem> problems = concat( transform( results, GET_PROBLEMS ) );
189         return new Result<>( hasErrors, models, problems );
190     }
191 
192     // helper to determine if problems contain error
193     private static boolean hasErrors( Iterable<? extends ModelProblem> problems )
194     {
195         return any( transform( problems, new Function<ModelProblem, Severity>()
196         {
197             @Override
198             public Severity apply( ModelProblem input )
199             {
200                 return input.getSeverity();
201             }
202         } ), in( of( ERROR, FATAL ) ) );
203     }
204 
205     /**
206      * Class definition
207      */
208 
209     private final boolean errors;
210 
211     private final T value;
212 
213     private final Iterable<? extends ModelProblem> problems;
214 
215     private Result( boolean errors, T model, Iterable<? extends ModelProblem> problems )
216     {
217         this.errors = errors;
218         this.value = model;
219         this.problems = problems;
220     }
221 
222     public Iterable<? extends ModelProblem> getProblems()
223     {
224         return problems;
225     }
226 
227     public T get()
228     {
229         return value;
230     }
231 
232     public boolean hasErrors()
233     {
234         return errors;
235     }
236 
237     private static final Function<Result<?>, Iterable<? extends ModelProblem>> GET_PROBLEMS =
238         new Function<Result<?>, Iterable<? extends ModelProblem>>()
239         {
240             @Override
241             public Iterable<? extends ModelProblem> apply( Result<?> input )
242             {
243                 return input.getProblems();
244             }
245         };
246 }