001package org.apache.maven.model.building; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import static com.google.common.base.Predicates.in; 023import static com.google.common.collect.Iterables.any; 024import static com.google.common.collect.Iterables.concat; 025import static com.google.common.collect.Iterables.transform; 026import static java.util.Collections.singleton; 027import static java.util.EnumSet.of; 028import static org.apache.maven.model.building.ModelProblem.Severity.ERROR; 029import static org.apache.maven.model.building.ModelProblem.Severity.FATAL; 030 031import java.util.Arrays; 032import java.util.Collections; 033 034import org.apache.maven.model.building.ModelProblem.Severity; 035 036import com.google.common.base.Function; 037import com.google.common.base.Predicates; 038import com.google.common.collect.Iterables; 039 040/** 041 * There are various forms of results that are represented by this class: 042 * <ol> 043 * <li>success - in which case only the model field is set 044 * <li>success with warnings - model field + non-error model problems 045 * <li>error - no model, but diagnostics 046 * <li>error - (partial) model and diagnostics 047 * </ol> 048 * Could encode these variants as subclasses, but kept in one for now 049 * 050 * @author bbusjaeger 051 * @param <T> 052 */ 053public class Result<T> 054{ 055 056 /** 057 * Success without warnings 058 * 059 * @param model 060 * @return 061 */ 062 public static <T> Result<T> success( T model ) 063 { 064 return success( model, Collections.<ModelProblem>emptyList() ); 065 } 066 067 /** 068 * Success with warnings 069 * 070 * @param model 071 * @param problems 072 * @return 073 */ 074 public static <T> Result<T> success( T model, Iterable<? extends ModelProblem> problems ) 075 { 076 assert !hasErrors( problems ); 077 return new Result<>( false, model, problems ); 078 } 079 080 /** 081 * Success with warnings 082 * 083 * @param model 084 * @param results 085 * @return 086 */ 087 public static <T> Result<T> success( T model, Result<?>... results ) 088 { 089 return success( model, Iterables.concat( Iterables.transform( Arrays.asList( results ), GET_PROBLEMS ) ) ); 090 } 091 092 /** 093 * Error with problems describing the cause 094 * 095 * @param problems 096 * @return 097 */ 098 public static <T> Result<T> error( Iterable<? extends ModelProblem> problems ) 099 { 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}