org.chromium.sdk/src/org/chromium/sdk/internal/protocolparser/dynamicimpl/FieldConditionLogic.java
changeset 2 e4420d2515f1
equal deleted inserted replaced
1:ef76fc2ac88c 2:e4420d2515f1
       
     1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style license that can be
       
     3 // found in the LICENSE file.
       
     4 
       
     5 package org.chromium.sdk.internal.protocolparser.dynamicimpl;
       
     6 
       
     7 import java.lang.reflect.Method;
       
     8 import java.util.ArrayList;
       
     9 import java.util.List;
       
    10 
       
    11 import org.chromium.sdk.internal.protocolparser.JsonProtocolModelParseException;
       
    12 import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;
       
    13 import org.chromium.sdk.internal.protocolparser.JsonSubtypeCondition;
       
    14 import org.chromium.sdk.internal.protocolparser.JsonSubtypeConditionBoolValue;
       
    15 import org.chromium.sdk.internal.protocolparser.JsonSubtypeConditionCustom;
       
    16 import org.chromium.sdk.internal.protocolparser.JsonValueCondition;
       
    17 
       
    18 /**
       
    19  * An interface to field conditions logic. Some conditions are simple and never need parsed
       
    20  * values, others are more fine-grained and require quick parser before making actual checks.
       
    21  */
       
    22 abstract class FieldConditionLogic {
       
    23   private final boolean logicRequiresQuickParser;
       
    24 
       
    25   FieldConditionLogic(boolean logicRequiresQuickParser) {
       
    26     this.logicRequiresQuickParser = logicRequiresQuickParser;
       
    27   }
       
    28 
       
    29   boolean requiresQuickParser() {
       
    30     return logicRequiresQuickParser;
       
    31   }
       
    32 
       
    33   /**
       
    34    * @param hasValue whether field exists in JSON object (however its value may be null)
       
    35    * @param quickParser parser that may be used if {@link #requiresQuickParser()} is true
       
    36    */
       
    37   abstract boolean checkValue(boolean hasValue, Object unparsedValue, QuickParser<?> quickParser)
       
    38       throws JsonProtocolParseException;
       
    39 
       
    40   /**
       
    41    * Constructor function that creates field condition logic from method annotations.
       
    42    */
       
    43   static FieldConditionLogic readLogic(Method m) throws JsonProtocolModelParseException {
       
    44     List<FieldConditionLogic> results = new ArrayList<FieldConditionLogic>(1);
       
    45     JsonSubtypeConditionBoolValue boolValueAnn =
       
    46         m.getAnnotation(JsonSubtypeConditionBoolValue.class);
       
    47     if (boolValueAnn != null) {
       
    48       final Boolean required = boolValueAnn.value();
       
    49       results.add(new FieldConditionLogic(true) {
       
    50         @Override
       
    51         boolean checkValue(boolean hasValue, Object unparsedValue, QuickParser<?> parser)
       
    52             throws JsonProtocolParseException {
       
    53           return hasValue && required == parser.parseValueQuick(unparsedValue);
       
    54         }
       
    55       });
       
    56     }
       
    57     JsonSubtypeConditionCustom customAnn = m.getAnnotation(JsonSubtypeConditionCustom.class);
       
    58     if (customAnn != null) {
       
    59       final CustomConditionWrapper<?> constraint =
       
    60           CustomConditionWrapper.create(customAnn.condition());
       
    61       results.add(new FieldConditionLogic(true) {
       
    62         @Override
       
    63         boolean checkValue(boolean hasValue, Object unparsedValue, QuickParser<?> parser)
       
    64             throws JsonProtocolParseException {
       
    65           return hasValue && constraint.checkValue(parser.parseValueQuick(unparsedValue));
       
    66         }
       
    67       });
       
    68     }
       
    69     JsonSubtypeCondition conditionAnn = m.getAnnotation(JsonSubtypeCondition.class);
       
    70     if (conditionAnn != null) {
       
    71       int savedResSize = results.size();
       
    72       if (conditionAnn.fieldIsAbsent()) {
       
    73         results.add(new FieldConditionLogic(false) {
       
    74           @Override
       
    75           boolean checkValue(boolean hasValue, Object unparsedValue, QuickParser<?> parser) {
       
    76             return !hasValue;
       
    77           }
       
    78         });
       
    79       }
       
    80       if (conditionAnn.valueIsNull()) {
       
    81         results.add(new FieldConditionLogic(false) {
       
    82           @Override
       
    83           boolean checkValue(boolean hasValue, Object unparsedValue, QuickParser<?> parser) {
       
    84             return hasValue && unparsedValue != null;
       
    85           }
       
    86         });
       
    87       }
       
    88       if (savedResSize == results.size()) {
       
    89         results.add(new FieldConditionLogic(false) {
       
    90           @Override
       
    91           boolean checkValue(boolean hasValue, Object unparsedValue, QuickParser<?> parser) {
       
    92             return hasValue;
       
    93           }
       
    94         });
       
    95       }
       
    96     }
       
    97     if (results.size() == 0) {
       
    98       return null;
       
    99     }
       
   100     if (results.size() > 1) {
       
   101       throw new JsonProtocolModelParseException("Too many constraints for field getter " + m);
       
   102     }
       
   103     return results.get(0);
       
   104   }
       
   105 
       
   106   private static class CustomConditionWrapper<T> {
       
   107     static <T, CL extends JsonValueCondition<T>> CustomConditionWrapper<T> create(
       
   108         Class<CL> constraintClass) {
       
   109       return new CustomConditionWrapper<T>(constraintClass);
       
   110     }
       
   111 
       
   112     private final JsonValueCondition<? super T> constraint;
       
   113 
       
   114     private CustomConditionWrapper(Class<? extends JsonValueCondition<? super T>> constraintClass) {
       
   115       try {
       
   116         constraint = constraintClass.newInstance();
       
   117       } catch (InstantiationException e) {
       
   118         throw new RuntimeException(e);
       
   119       } catch (IllegalAccessException e) {
       
   120         throw new RuntimeException(e);
       
   121       }
       
   122     }
       
   123 
       
   124     boolean checkValue(Object parsedValue) {
       
   125       return constraint.conforms((T)parsedValue);
       
   126     }
       
   127   }
       
   128 
       
   129 }