SheetErrorFormatter.java

  1. package com.gh.mygreen.xlsmapper.validation;

  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Optional;

  8. import com.gh.mygreen.xlsmapper.localization.MessageInterpolator;
  9. import com.gh.mygreen.xlsmapper.localization.MessageResolver;
  10. import com.gh.mygreen.xlsmapper.localization.ResourceBundleMessageResolver;
  11. import com.gh.mygreen.xlsmapper.util.ArgUtils;
  12. import com.gh.mygreen.xlsmapper.util.Utils;


  13. /**
  14.  * シート用のエラーオブジェクトを解釈して、メッセージに変換するクラス。
  15.  * <p>オブジェクトの種類ごとに、デフォルトメッセージ変数が利用できます。</p>
  16.  * <ul>
  17.  *  <li>'fieldLabel':フィールドのラベル。メッセージ用のプロパティファイルにフィールド名を定義している場合、自動的に設定されます。</li>
  18.  *  <li>'objectLabel':オブジェクトのラベル。メッセージ用のプロパティファイルにオブジェクト名を定義している場合、自動的に設定されます。</li>
  19.  *  <li>'label':ラベル変数'label'が指定されていない場合、エラー対象のオブジェクト名またはフィールド名から自動的に決定されます。</li>
  20.  *  <li>'sheetName':シート用のエラーの場合、シート名が設定されます。</li>
  21.  *  <li>'cellAddress':シート用のフィールドエラーの場合、セルのアドレスが設定されます。'A1'のような形式になります。</li>
  22.  * </ul>
  23.  *
  24.  * @version 2.3
  25.  * @since 2.0
  26.  * @author T.TSUCHIE
  27.  *
  28.  */
  29. public class SheetErrorFormatter {
  30.    
  31.     private MessageResolver messageResolver = new ResourceBundleMessageResolver();
  32.    
  33.     private MessageInterpolator messageInterporlator = new MessageInterpolator();
  34.    
  35.     private MessageCodeGenerator messageCodeGenerator = new MessageCodeGenerator();
  36.    
  37.     /** エラーメッセージの定義が見つからないときのデフォルトのエラーコード */
  38.     private String defaultErrorCode = "defaultError";
  39.    
  40.     public SheetErrorFormatter() {
  41.        
  42.     }
  43.    
  44.     /**
  45.      * エラーオブジェクトのリストをメッセージにフォーマットする。
  46.      * @param errors 変換対象のエラーオブジェクト。
  47.      * @return
  48.      * @throws IllegalArgumentException errors == null.
  49.      */
  50.     public List<String> format(final Collection<ObjectError> errors) {
  51.         ArgUtils.notNull(errors, "errors");
  52.        
  53.         final List<String> messageList = new ArrayList<>();
  54.         for(ObjectError error : errors) {
  55.             messageList.add(format(error));
  56.         }
  57.        
  58.         return messageList;
  59.     }
  60.    
  61.     /**
  62.      * エラーオブジェクトをメッセージにフォーマットする。
  63.      * @param error エラーオブジェクト
  64.      * @return メッセージ
  65.      * @throws IllegalArgumentException {@literal error == null.}
  66.      */
  67.     public String format(final ObjectError error) {
  68.         ArgUtils.notNull(error, "error");
  69.        
  70.         final Map<String, Object> vars = new HashMap<>();
  71.         vars.putAll(error.getVariables());
  72.        
  73.         if(error instanceof FieldError) {
  74.             // フィールドエラーのメッセージを処理する
  75.            
  76.             final FieldError fieldError = (FieldError) error;
  77.             final String[] labelCode = messageCodeGenerator.generateFieldNameCodes(fieldError.getObjectName(), fieldError.getField());
  78.            
  79.             try {
  80.                 vars.put("fieldLabel", getMessage(labelCode, null));
  81.             } catch(Throwable e) {
  82.             }
  83.            
  84.             final Optional<String> label = error.getLabelAsOptional();
  85.             if(label.isPresent()) {
  86.                 vars.put("label", label.get());
  87.             } else {
  88.                 try {
  89.                     vars.put("label", getMessage(labelCode, null));
  90.                 } catch(Throwable e) {
  91.                 }
  92.             }
  93.            
  94.             try {
  95.                 // 親のラベル名を取得する
  96.                 String[] parentCode = messageCodeGenerator.generateParentNameCodes(fieldError.getObjectName(), fieldError.getField());
  97.                 vars.put("parentLabel", getMessage(parentCode, null));
  98.             } catch(Throwable e) {
  99.             }
  100.            
  101.             try {
  102.                 String[] objectCode = messageCodeGenerator.generateObjectNameCodes(fieldError.getObjectName());
  103.                 vars.put("objectLabel", getMessage(objectCode, null));
  104.             } catch(Throwable e) {
  105.                
  106.             }
  107.            
  108.             fieldError.getSheetName().ifPresent(s -> vars.put("sheetName", s));
  109.             fieldError.getAddressAsOptional().ifPresent(a -> vars.put("cellAddress", a));
  110.            
  111.         } else {
  112.             // オブジェクトエラーのメッセージを処理する。
  113.            
  114.             final String[] labelCode = messageCodeGenerator.generateObjectNameCodes(error.getObjectName());
  115.            
  116.             final Optional<String> label = error.getLabelAsOptional();
  117.             if(label.isPresent()) {
  118.                 vars.put("label", label.get());
  119.             } else {
  120.                 try {
  121.                     vars.put("label", getMessage(labelCode, null));
  122.                 } catch(Throwable e) {
  123.                 }
  124.             }
  125.            
  126.             try {
  127.                 String[] objectCode = messageCodeGenerator.generateObjectNameCodes(error.getObjectName());
  128.                 vars.put("objectLabel", getMessage(objectCode, null));
  129.             } catch(Throwable e) {
  130.                
  131.             }
  132.            
  133.             error.getSheetName().ifPresent(s -> vars.put("sheetName", s));
  134.            
  135.         }

  136.         final String message;
  137.         if(Utils.isEmpty(error.getCodes())) {
  138.             // エラーコードの指定がない場合は、ユーザー指定のメッセージとして処理する。
  139.             message = error.getDefaultMessage().orElse(defaultErrorCode);
  140.         } else {
  141.             message = getMessage(error.getCodes(), error.getDefaultMessage());
  142.         }
  143.         return messageInterporlator.interpolate(message, vars, true, messageResolver);
  144.        
  145.     }
  146.    
  147.     /**
  148.      * 指定した引数の候補からメッセージを取得する。
  149.      * @param codes メッセージコードの候補
  150.      * @param defaultMessage メッセージコードが見つからない場合のメッセージ
  151.      * @return メッセージ
  152.      * @throws RuntimeException メッセージコード 'codes' で指定したメッセージキーが見つからない場合。
  153.      */
  154.     private String getMessage(final String[] codes, final Optional<String> defaultMessage) {
  155.         for(String code : codes) {
  156.             try {
  157.                 final Optional<String> message = messageResolver.getMessage(code);
  158.                 if(message.isPresent()) {
  159.                     return message.get();
  160.                 }
  161.                
  162.             } catch(Throwable e) {
  163.                 continue;
  164.             }
  165.         }
  166.        
  167.         if(defaultMessage.isPresent()) {
  168.             return defaultMessage.get();
  169.         }
  170.        
  171.         throw new RuntimeException(String.format("not found message code [%s].", Utils.join(codes, ",")));
  172.     }
  173.    
  174.     public MessageResolver getMessageResolver() {
  175.         return messageResolver;
  176.     }
  177.    
  178.     public void setMessageResolver(MessageResolver messageResolver) {
  179.         this.messageResolver = messageResolver;
  180.     }
  181.    
  182.     public MessageInterpolator getMessageInterporlator() {
  183.         return messageInterporlator;
  184.     }
  185.    
  186.     public void setMessageInterporlator(MessageInterpolator messageInterporlator) {
  187.         this.messageInterporlator = messageInterporlator;
  188.     }
  189.    
  190.     public MessageCodeGenerator getMessageCodeGenerator() {
  191.         return messageCodeGenerator;
  192.     }
  193.    
  194.     public void setMessageCodeGenerator(MessageCodeGenerator messageCodeGenerator) {
  195.         this.messageCodeGenerator = messageCodeGenerator;
  196.     }
  197. }