001/*
002 * Copyright (c) 2010-2024 Mark Allen, Norbert Bartels.
003 *
004 * Permission is hereby granted, free of charge, to any person obtaining a copy
005 * of this software and associated documentation files (the "Software"), to deal
006 * in the Software without restriction, including without limitation the rights
007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008 * copies of the Software, and to permit persons to whom the Software is
009 * furnished to do so, subject to the following conditions:
010 *
011 * The above copyright notice and this permission notice shall be included in
012 * all copies or substantial portions of the Software.
013 *
014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
020 * THE SOFTWARE.
021 */
022package com.restfb.types.ads;
023
024import java.util.List;
025
026import com.restfb.json.JsonArray;
027import com.restfb.json.JsonObject;
028import com.restfb.json.JsonValue;
029
030public class RuleFactory {
031
032  public static JsonObject createJsonFromRule(Rule rule) {
033    if (rule == null) {
034      return null;
035    }
036
037    JsonObject result = new JsonObject();
038
039    if (rule instanceof RuleOpAnd) {
040      RuleOpAnd ruleOpAnd = (RuleOpAnd) rule;
041      List<Rule> ruleList = ruleOpAnd.getRuleList();
042      JsonArray jsonValues = new JsonArray();
043      for (Rule ruleListItem : ruleList) {
044        JsonObject obj = RuleFactory.createJsonFromRule(ruleListItem);
045        if (obj != null) {
046          jsonValues.add(obj);
047        }
048      }
049      result.add(ruleOpAnd.getType(), jsonValues);
050      return result;
051    }
052
053    if (rule instanceof RuleOpOr) {
054      RuleOpOr ruleOpOr = (RuleOpOr) rule;
055      List<Rule> ruleList = ruleOpOr.getRuleList();
056      JsonArray jsonValues = new JsonArray();
057      for (Rule ruleListItem : ruleList) {
058        JsonObject obj = RuleFactory.createJsonFromRule(ruleListItem);
059        if (obj != null) {
060          jsonValues.add(obj);
061        }
062      }
063      result.add(ruleOpOr.getType(), jsonValues);
064      return result;
065    }
066
067    if (rule instanceof RuleData) {
068      RuleData ruleData = (RuleData) rule;
069      result.add(ruleData.getType(), RuleFactory.createJsonFromRule(ruleData.getOperator()));
070      return result;
071    }
072
073    if (rule instanceof RuleOp) {
074      RuleOp ruleOp = (RuleOp) rule;
075      result.add(ruleOp.getType(), ruleOp.getValue());
076      return result;
077    }
078
079    if (result.names().isEmpty()) {
080      throw new IllegalArgumentException("unknown rule found");
081    } else {
082      return result;
083    }
084
085  }
086
087  public static Rule createRuleFromJson(JsonObject ruleJson) {
088
089    // null check,
090    if (ruleJson == null) {
091      return null;
092    }
093
094    // size check, rules with more than one key are not allowed
095    if (ruleJson.names().size() > 1) {
096      throw new IllegalArgumentException("only one key is supported, found " + ruleJson.names().size());
097    }
098
099    String key = ruleJson.names().get(0);
100
101    // create data
102    if (isCreateData(key)) {
103      return createRuleData(ruleJson, key);
104    }
105
106    // create "simple" operator
107    if (isCreateSimpleOperator(key)) {
108      return createRuleOperator(ruleJson, key);
109    }
110
111    // create a more complex operator (OR, AND)
112    if ("and".equals(key)) {
113      JsonValue andList = ruleJson.get(key);
114      RuleOpAnd rOp = new RuleOpAnd(key);
115      if (andList.isArray()) {
116        for (JsonValue item : andList.asArray()) {
117          Rule r = RuleFactory.createRuleFromJson(item.asObject());
118          rOp.getRuleList().add(r);
119        }
120      }
121      return rOp;
122    }
123    if ("or".equals(key)) {
124      JsonValue andList = ruleJson.get(key);
125      RuleOpOr rOp = new RuleOpOr(key);
126      if (andList.isArray()) {
127        for (JsonValue item : andList.asArray()) {
128          Rule r = RuleFactory.createRuleFromJson(item.asObject());
129          rOp.getRuleList().add(r);
130        }
131      }
132      return rOp;
133    }
134
135    // fallback is the custom data object
136    return createRuleData(ruleJson, key);
137  }
138
139  private static boolean isCreateData(String key) {
140    return "url".equals(key) || //
141        "event".equals(key) || //
142        "path".equals(key) || //
143        "domain".equals(key) || //
144        "device_type".equals(key);
145  }
146
147  private static boolean isCreateSimpleOperator(String key) {
148    return "i_contains".equals(key) || //
149        "contains".equals(key) || //
150        "i_not_contains".equals(key) || //
151        "not_contains".equals(key) || //
152        "gte".equals(key) || //
153        "gt".equals(key) || //
154        "lte".equals(key) || //
155        "lt".equals(key) || //
156        "neq".equals(key) || //
157        "eq".equals(key) || //
158        "regex_match".equals(key);
159  }
160
161  private static Rule createRuleData(JsonObject ruleJson, String key) {
162    RuleData rData = new RuleData(key);
163    rData.setOperator((RuleOp) RuleFactory.createRuleFromJson(ruleJson.get(key).asObject()));
164    return rData;
165  }
166
167  private static Rule createRuleOperator(JsonObject ruleJson, String key) {
168    RuleOp rOp = new RuleOp(key);
169    if (ruleJson.get(key).isString()) {
170      rOp.setValue(ruleJson.get(key).asString());
171    } else {
172      rOp.setValue(ruleJson.get(key).toString());
173    }
174    return rOp;
175  }
176
177}