ErrorModel.java

  1. /*
  2.  * Copyright © 2017, Salesforce.com, Inc
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions are met:
  7.  *     * Redistributions of source code must retain the above copyright
  8.  *       notice, this list of conditions and the following disclaimer.
  9.  *     * Redistributions in binary form must reproduce the above copyright
  10.  *       notice, this list of conditions and the following disclaimer in the
  11.  *       documentation and/or other materials provided with the distribution.
  12.  *     * Neither the name of the <organization> nor the
  13.  *       names of its contributors may be used to endorse or promote products
  14.  *       derived from this software without specific prior written permission.
  15.  *
  16.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19.  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  20.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26.  */
  27. package com.salesforce.apt.graph.model.errors;

  28. import java.text.MessageFormat;
  29. import java.util.Collections;
  30. import java.util.List;
  31. import java.util.function.Function;
  32. import java.util.stream.Collectors;

  33. import com.salesforce.apt.graph.model.AbstractModel;

  34. public class ErrorModel {

  35.   private final ErrorType message;
  36.   private final List<AbstractModel> causes;
  37.   private final List<AbstractModel> involved;
  38.  
  39.   public ErrorType getMessage() {
  40.     return message;
  41.   }

  42.   public List<AbstractModel> getCauses() {
  43.     return causes;
  44.   }
  45.  
  46.   public List<AbstractModel> getInvolved() {
  47.     return involved;
  48.   }
  49.  
  50.   public boolean isCyclic() {
  51.     return message.isCycle();
  52.   }
  53.  
  54.   public String toString() {
  55.     return message.name() + " on " + involved.toString() + " caused by " + causes;
  56.   }
  57.  
  58.   /**
  59.    * A non cyclic error.
  60.    *
  61.    * @param message {@link ErrorType} of this represents
  62.    * @param causes models at fault.
  63.    * @param involved models the error should be displayed on.
  64.    */
  65.   public ErrorModel(ErrorType message, List<? extends AbstractModel> causes, List<? extends AbstractModel> involved) {
  66.     super();
  67.     this.message = message;
  68.     if (message.isCycle() && !causes.equals(involved)) {
  69.       throw new IllegalArgumentException("Malformed ErrorModel");
  70.     }
  71.     this.causes = Collections.unmodifiableList(causes);
  72.     this.involved = Collections.unmodifiableList(involved);  
  73.   }
  74.  
  75.   /**
  76.    * Returns a contextualized error message for the error, from the model's perspective.
  77.    *
  78.    * @param on an AbstractModel that is "involved" in this error
  79.    * @param converter presents an error message for this error model to be displayed on the AbstractModel, on,
  80.    *     that contributed to the error.
  81.    * @return an error message from the context of the failed model member.
  82.    */
  83.   public String getMessageOn(AbstractModel on, Function<ErrorType, String> converter) {
  84.     if (!isCyclic()) {
  85.       if (getCauses().size() == 1) {
  86.         return MessageFormat.format(converter.apply(getMessage()), getCauses().get(0));
  87.       } else {
  88.         return MessageFormat.format(converter.apply(getMessage()),
  89.             getCauses().stream().filter(m -> !m.equals(on)).map(m -> m.toString()).collect(Collectors.joining(", ")));
  90.       }
  91.     }
  92.     StringBuilder builder = new StringBuilder();
  93.     int index = getInvolved().indexOf(on);
  94.     if (index != -1) {
  95.       for (int i = index; i < getInvolved().size(); i++) {
  96.         builder.append(getInvolved().get(i).toString());
  97.         if (i + 1 < getInvolved().size() || index != 0) {
  98.           builder.append(" -> ");
  99.         }
  100.       }
  101.       for (int i = 0; i < index; i++) {
  102.         builder.append(getInvolved().get(i).toString());
  103.         if (i + 1 < index) {
  104.           builder.append(" -> ");
  105.         }
  106.       }
  107.     }
  108.     return MessageFormat.format(converter.apply(getMessage()), builder.toString());
  109.   }

  110. }