140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski/*
240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * Copyright (C) 2014 The Android Open Source Project
340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski *
440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * you may not use this file except in compliance with the License.
640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * You may obtain a copy of the License at
740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski *
840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski *
1040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * Unless required by applicable law or agreed to in writing, software
1140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
1240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * See the License for the specific language governing permissions and
1440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * limitations under the License.
1540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski */
1640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
1740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "Rule.h"
1840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
1940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <utils/String8.h>
2040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
2140e8eefbedcafc51948945647d746daaee092f16Adam Lesinskiusing namespace android;
2240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
2340e8eefbedcafc51948945647d746daaee092f16Adam Lesinskinamespace split {
2440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
2540e8eefbedcafc51948945647d746daaee092f16Adam Lesinskiinline static void indentStr(String8& str, int indent) {
2640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    while (indent > 0) {
2740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        str.append("  ");
2840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        indent--;
2940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
3040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}
3140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
32dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam LesinskiRule::Rule(const Rule& rhs)
33dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    : RefBase()
34dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    , op(rhs.op)
35dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    , key(rhs.key)
36dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    , negate(rhs.negate)
37dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    , stringArgs(rhs.stringArgs)
38dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    , longArgs(rhs.longArgs)
39dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    , subrules(rhs.subrules) {
40dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski}
41dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
4240e8eefbedcafc51948945647d746daaee092f16Adam LesinskiString8 Rule::toJson(int indent) const {
4340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    String8 str;
4440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    indentStr(str, indent);
4540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    str.append("{\n");
4640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    indent++;
4740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    indentStr(str, indent);
4840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    str.append("\"op\": \"");
4940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    switch (op) {
5040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        case ALWAYS_TRUE:
5140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            str.append("ALWAYS_TRUE");
5240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            break;
5340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        case GREATER_THAN:
5440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            str.append("GREATER_THAN");
5540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            break;
5640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        case LESS_THAN:
5740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            str.append("LESS_THAN");
5840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            break;
5940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        case EQUALS:
6040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            str.append("EQUALS");
6140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            break;
6240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        case AND_SUBRULES:
6340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            str.append("AND_SUBRULES");
6440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            break;
6540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        case OR_SUBRULES:
6640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            str.append("OR_SUBRULES");
6740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            break;
6840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        case CONTAINS_ANY:
6940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            str.append("CONTAINS_ANY");
7040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            break;
7140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        default:
7240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            str.appendFormat("%d", op);
7340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            break;
7440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
7540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    str.append("\"");
7640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
7740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (negate) {
7840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        str.append(",\n");
7940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        indentStr(str, indent);
8040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        str.append("\"negate\": true");
8140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
8240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
8340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    bool includeKey = true;
8440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    switch (op) {
8540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        case AND_SUBRULES:
8640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        case OR_SUBRULES:
8740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            includeKey = false;
8840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            break;
8940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        default:
9040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            break;
9140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
9240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
9340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (includeKey) {
9440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        str.append(",\n");
9540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        indentStr(str, indent);
9640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        str.append("\"property\": \"");
9740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        switch (key) {
9840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            case NONE:
9940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append("NONE");
10040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                break;
10140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            case SDK_VERSION:
10240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append("SDK_VERSION");
10340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                break;
10440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            case SCREEN_DENSITY:
10540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append("SCREEN_DENSITY");
10640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                break;
10740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            case NATIVE_PLATFORM:
10840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append("NATIVE_PLATFORM");
10940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                break;
11040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            case LANGUAGE:
11140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append("LANGUAGE");
11240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                break;
11340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            default:
11440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.appendFormat("%d", key);
11540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                break;
11640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
11740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        str.append("\"");
11840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
11940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
12040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (op == AND_SUBRULES || op == OR_SUBRULES) {
12140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        str.append(",\n");
12240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        indentStr(str, indent);
12340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        str.append("\"subrules\": [\n");
12440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        const size_t subruleCount = subrules.size();
12540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        for (size_t i = 0; i < subruleCount; i++) {
12640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            str.append(subrules[i]->toJson(indent + 1));
12740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            if (i != subruleCount - 1) {
12840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append(",");
12940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            }
13040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            str.append("\n");
13140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
13240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        indentStr(str, indent);
13340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        str.append("]");
13440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    } else {
13540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        switch (key) {
13640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            case SDK_VERSION:
13740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            case SCREEN_DENSITY: {
13840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append(",\n");
13940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                indentStr(str, indent);
14040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append("\"args\": [");
14140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                const size_t argCount = longArgs.size();
14240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                for (size_t i = 0; i < argCount; i++) {
14340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                    if (i != 0) {
14440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                        str.append(", ");
14540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                    }
14640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                    str.appendFormat("%d", longArgs[i]);
14740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                }
14840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append("]");
14940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                break;
15040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            }
15140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            case LANGUAGE:
15240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            case NATIVE_PLATFORM: {
15340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append(",\n");
15440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                indentStr(str, indent);
15540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append("\"args\": [");
15640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                const size_t argCount = stringArgs.size();
15740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                for (size_t i = 0; i < argCount; i++) {
15840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                    if (i != 0) {
15940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                        str.append(", ");
16040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                    }
16140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                    str.append(stringArgs[i]);
16240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                }
16340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                str.append("]");
16440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                break;
16540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            }
16640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            default:
16740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                break;
16840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
16940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
17040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    str.append("\n");
17140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    indent--;
17240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    indentStr(str, indent);
17340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    str.append("}");
17440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    return str;
17540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}
17640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
17740e8eefbedcafc51948945647d746daaee092f16Adam Lesinskisp<Rule> Rule::simplify(sp<Rule> rule) {
17840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (rule->op != AND_SUBRULES && rule->op != OR_SUBRULES) {
17940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        return rule;
18040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
18140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
18240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    Vector<sp<Rule> > newSubrules;
18340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    newSubrules.setCapacity(rule->subrules.size());
18440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    const size_t subruleCount = rule->subrules.size();
18540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    for (size_t i = 0; i < subruleCount; i++) {
18640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        sp<Rule> simplifiedRule = simplify(rule->subrules.editItemAt(i));
18740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        if (simplifiedRule != NULL) {
18840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            if (simplifiedRule->op == rule->op) {
18940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                newSubrules.appendVector(simplifiedRule->subrules);
19040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            } else {
19140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                newSubrules.add(simplifiedRule);
19240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            }
19340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
19440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
19540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
19640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    const size_t newSubruleCount = newSubrules.size();
19740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (newSubruleCount == 0) {
19840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        return NULL;
19940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    } else if (subruleCount == 1) {
20040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        return newSubrules.editTop();
20140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
20240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    rule->subrules = newSubrules;
20340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    return rule;
20440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}
20540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
20640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} // namespace split
207