Home | History | Annotate | Download | only in split-select
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "Rule.h"
     18 
     19 #include <utils/String8.h>
     20 
     21 using namespace android;
     22 
     23 namespace split {
     24 
     25 inline static void indentStr(String8& str, int indent) {
     26     while (indent > 0) {
     27         str.append("  ");
     28         indent--;
     29     }
     30 }
     31 
     32 Rule::Rule(const Rule& rhs)
     33     : RefBase()
     34     , op(rhs.op)
     35     , key(rhs.key)
     36     , negate(rhs.negate)
     37     , stringArgs(rhs.stringArgs)
     38     , longArgs(rhs.longArgs)
     39     , subrules(rhs.subrules) {
     40 }
     41 
     42 String8 Rule::toJson(int indent) const {
     43     String8 str;
     44     indentStr(str, indent);
     45     str.append("{\n");
     46     indent++;
     47     indentStr(str, indent);
     48     str.append("\"op\": \"");
     49     switch (op) {
     50         case ALWAYS_TRUE:
     51             str.append("ALWAYS_TRUE");
     52             break;
     53         case GREATER_THAN:
     54             str.append("GREATER_THAN");
     55             break;
     56         case LESS_THAN:
     57             str.append("LESS_THAN");
     58             break;
     59         case EQUALS:
     60             str.append("EQUALS");
     61             break;
     62         case AND_SUBRULES:
     63             str.append("AND_SUBRULES");
     64             break;
     65         case OR_SUBRULES:
     66             str.append("OR_SUBRULES");
     67             break;
     68         case CONTAINS_ANY:
     69             str.append("CONTAINS_ANY");
     70             break;
     71         default:
     72             str.appendFormat("%d", op);
     73             break;
     74     }
     75     str.append("\"");
     76 
     77     if (negate) {
     78         str.append(",\n");
     79         indentStr(str, indent);
     80         str.append("\"negate\": true");
     81     }
     82 
     83     bool includeKey = true;
     84     switch (op) {
     85         case AND_SUBRULES:
     86         case OR_SUBRULES:
     87             includeKey = false;
     88             break;
     89         default:
     90             break;
     91     }
     92 
     93     if (includeKey) {
     94         str.append(",\n");
     95         indentStr(str, indent);
     96         str.append("\"property\": \"");
     97         switch (key) {
     98             case NONE:
     99                 str.append("NONE");
    100                 break;
    101             case SDK_VERSION:
    102                 str.append("SDK_VERSION");
    103                 break;
    104             case SCREEN_DENSITY:
    105                 str.append("SCREEN_DENSITY");
    106                 break;
    107             case NATIVE_PLATFORM:
    108                 str.append("NATIVE_PLATFORM");
    109                 break;
    110             case LANGUAGE:
    111                 str.append("LANGUAGE");
    112                 break;
    113             default:
    114                 str.appendFormat("%d", key);
    115                 break;
    116         }
    117         str.append("\"");
    118     }
    119 
    120     if (op == AND_SUBRULES || op == OR_SUBRULES) {
    121         str.append(",\n");
    122         indentStr(str, indent);
    123         str.append("\"subrules\": [\n");
    124         const size_t subruleCount = subrules.size();
    125         for (size_t i = 0; i < subruleCount; i++) {
    126             str.append(subrules[i]->toJson(indent + 1));
    127             if (i != subruleCount - 1) {
    128                 str.append(",");
    129             }
    130             str.append("\n");
    131         }
    132         indentStr(str, indent);
    133         str.append("]");
    134     } else {
    135         switch (key) {
    136             case SDK_VERSION:
    137             case SCREEN_DENSITY: {
    138                 str.append(",\n");
    139                 indentStr(str, indent);
    140                 str.append("\"args\": [");
    141                 const size_t argCount = longArgs.size();
    142                 for (size_t i = 0; i < argCount; i++) {
    143                     if (i != 0) {
    144                         str.append(", ");
    145                     }
    146                     str.appendFormat("%d", longArgs[i]);
    147                 }
    148                 str.append("]");
    149                 break;
    150             }
    151             case LANGUAGE:
    152             case NATIVE_PLATFORM: {
    153                 str.append(",\n");
    154                 indentStr(str, indent);
    155                 str.append("\"args\": [");
    156                 const size_t argCount = stringArgs.size();
    157                 for (size_t i = 0; i < argCount; i++) {
    158                     if (i != 0) {
    159                         str.append(", ");
    160                     }
    161                     str.append(stringArgs[i]);
    162                 }
    163                 str.append("]");
    164                 break;
    165             }
    166             default:
    167                 break;
    168         }
    169     }
    170     str.append("\n");
    171     indent--;
    172     indentStr(str, indent);
    173     str.append("}");
    174     return str;
    175 }
    176 
    177 sp<Rule> Rule::simplify(sp<Rule> rule) {
    178     if (rule->op != AND_SUBRULES && rule->op != OR_SUBRULES) {
    179         return rule;
    180     }
    181 
    182     Vector<sp<Rule> > newSubrules;
    183     newSubrules.setCapacity(rule->subrules.size());
    184     const size_t subruleCount = rule->subrules.size();
    185     for (size_t i = 0; i < subruleCount; i++) {
    186         sp<Rule> simplifiedRule = simplify(rule->subrules.editItemAt(i));
    187         if (simplifiedRule != NULL) {
    188             if (simplifiedRule->op == rule->op) {
    189                 newSubrules.appendVector(simplifiedRule->subrules);
    190             } else {
    191                 newSubrules.add(simplifiedRule);
    192             }
    193         }
    194     }
    195 
    196     const size_t newSubruleCount = newSubrules.size();
    197     if (newSubruleCount == 0) {
    198         return NULL;
    199     } else if (subruleCount == 1) {
    200         return newSubrules.editTop();
    201     }
    202     rule->subrules = newSubrules;
    203     return rule;
    204 }
    205 
    206 } // namespace split
    207