private RenderingRuleProperty registerRuleInternal(RenderingRuleProperty p) {
   if (get(p.getAttrName()) == null) {
     properties.put(p.getAttrName(), p);
     p.setId(rules.size());
     rules.add(p);
   }
   return get(p.getAttrName());
 }
 public boolean isSpecified(RenderingRuleProperty property) {
   if (property.isFloat()) {
     return fvalues[property.getId()] != 0 || values[property.getId()] != -1;
   } else {
     int val = values[property.getId()];
     if (property.isColor()) {
       return val != 0;
     } else {
       return val != -1;
     }
   }
 }
 public float getFloatPropertyValue(RenderingRuleProperty property, float defVal) {
   float f = fvalues[property.getId()];
   if (f == 0) {
     return defVal;
   }
   return f;
 }
 public String getStringPropertyValue(RenderingRuleProperty property) {
   int val = values[property.getId()];
   if (val < 0) {
     return null;
   }
   return storage.getStringValue(val);
 }
 public void clearValue(RenderingRuleProperty p) {
   if (p.isIntParse()) {
     values[p.getId()] = savedValues[p.getId()];
   } else {
     fvalues[p.getId()] = savedFvalues[p.getId()];
     values[p.getId()] = savedValues[p.getId()];
   }
 }
  public void createDefaultRenderingRuleProperties() {
    R_TEST = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(TEST));
    R_TAG = registerRuleInternal(RenderingRuleProperty.createInputStringProperty(TAG));
    R_VALUE = registerRuleInternal(RenderingRuleProperty.createInputStringProperty(VALUE));
    R_ADDITIONAL =
        registerRuleInternal(RenderingRuleProperty.createAdditionalStringProperty(ADDITIONAL));
    R_MINZOOM = registerRuleInternal(RenderingRuleProperty.createInputGreaterIntProperty(MINZOOM));
    R_MAXZOOM = registerRuleInternal(RenderingRuleProperty.createInputLessIntProperty(MAXZOOM));
    R_NIGHT_MODE =
        registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(NIGHT_MODE));
    R_LAYER = registerRuleInternal(RenderingRuleProperty.createInputIntProperty(LAYER));
    R_POINT = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(POINT));
    R_AREA = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(AREA));
    R_CYCLE = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(CYCLE));

    R_TEXT_LENGTH = registerRuleInternal(RenderingRuleProperty.createInputIntProperty(TEXT_LENGTH));
    R_NAME_TAG = registerRuleInternal(RenderingRuleProperty.createInputStringProperty(NAME_TAG));
    R_NAME_TAG2 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(NAME_TAG2));

    R_DISABLE = registerRuleInternal(RenderingRuleProperty.createOutputBooleanProperty(DISABLE));
    R_ATTR_INT_VALUE =
        registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(ATTR_INT_VALUE));
    R_ATTR_BOOL_VALUE =
        registerRuleInternal(RenderingRuleProperty.createOutputBooleanProperty(ATTR_BOOL_VALUE));
    R_ATTR_COLOR_VALUE =
        registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(ATTR_COLOR_VALUE));
    R_ATTR_STRING_VALUE =
        registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(ATTR_STRING_VALUE));

    // order - no sense to make it float
    R_ORDER = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(ORDER));
    R_OBJECT_TYPE =
        registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(OBJECT_TYPE));
    R_SHADOW_LEVEL =
        registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(SHADOW_LEVEL));

    // text properties
    R_TEXT_WRAP_WIDTH =
        registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(TEXT_WRAP_WIDTH));
    R_TEXT_DY = registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(TEXT_DY));
    R_TEXT_HALO_RADIUS =
        registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(TEXT_HALO_RADIUS));
    R_TEXT_HALO_COLOR =
        registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(TEXT_HALO_COLOR));
    R_TEXT_SIZE = registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(TEXT_SIZE));
    R_TEXT_ORDER = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_ORDER));
    R_ICON_ORDER = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(ICON_ORDER));
    R_ICON_VISIBLE_SIZE =
        registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(ICON_VISIBLE_SIZE));
    R_TEXT_MIN_DISTANCE =
        registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(TEXT_MIN_DISTANCE));
    R_TEXT_SHIELD =
        registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(TEXT_SHIELD));

    R_TEXT_COLOR =
        registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(TEXT_COLOR));

    R_TEXT_BOLD =
        registerRuleInternal(RenderingRuleProperty.createOutputBooleanProperty(TEXT_BOLD));
    R_TEXT_ON_PATH =
        registerRuleInternal(RenderingRuleProperty.createOutputBooleanProperty(TEXT_ON_PATH));

    // point
    R_ICON = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(ICON));

    // polygon/way
    R_COLOR = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR));
    R_COLOR_2 = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR_2));
    R_COLOR_3 = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR_3));
    R_COLOR_0 = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR_0));
    R_COLOR__1 = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR__1));
    R_STROKE_WIDTH =
        registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH));
    R_STROKE_WIDTH_2 =
        registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH_2));
    R_STROKE_WIDTH_3 =
        registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH_3));
    R_STROKE_WIDTH_0 =
        registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH_0));
    R_STROKE_WIDTH__1 =
        registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH__1));

    R_PATH_EFFECT =
        registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT));
    R_PATH_EFFECT_2 =
        registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT_2));
    R_PATH_EFFECT_3 =
        registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT_3));
    R_PATH_EFFECT_0 =
        registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT_0));
    R_PATH_EFFECT__1 =
        registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT__1));
    R_CAP = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP));
    R_CAP_2 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP_2));
    R_CAP_3 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP_3));
    R_CAP_0 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP_0));
    R_CAP__1 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP__1));
    R_SHADER = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(SHADER));

    R_SHADOW_COLOR =
        registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(SHADOW_COLOR));
    R_SHADOW_RADIUS =
        registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(SHADOW_RADIUS));
  }
 public void setBooleanFilter(RenderingRuleProperty p, boolean filter) {
   assert p.isInputProperty();
   values[p.getId()] =
       filter ? RenderingRuleProperty.TRUE_VALUE : RenderingRuleProperty.FALSE_VALUE;
 }
 public void setIntFilter(RenderingRuleProperty p, int filter) {
   assert p.isInputProperty();
   values[p.getId()] = filter;
 }
 public void setStringFilter(RenderingRuleProperty p, String filter) {
   assert p.isInputProperty();
   values[p.getId()] = storage.getDictionaryValue(filter);
 }
 public int getIntPropertyValue(RenderingRuleProperty property, int defValue) {
   int val = values[property.getId()];
   return val == -1 ? defValue : val;
 }
 public int getIntPropertyValue(RenderingRuleProperty property) {
   return values[property.getId()];
 }
 public String getColorStringPropertyValue(RenderingRuleProperty property) {
   return RenderingRuleProperty.colorToString(values[property.getId()]);
 }
 public float getFloatPropertyValue(RenderingRuleProperty property) {
   return fvalues[property.getId()];
 }
  private boolean visitRule(RenderingRule rule, boolean loadOutput) {
    RenderingRuleProperty[] properties = rule.getProperties();
    for (int i = 0; i < properties.length; i++) {
      RenderingRuleProperty rp = properties[i];
      if (rp.isInputProperty()) {
        boolean match;
        if (rp.isFloat()) {
          match = rp.accept(rule.getFloatProp(i), fvalues[rp.getId()], this);
        } else {
          match = rp.accept(rule.getIntProp(i), values[rp.getId()], this);
        }
        if (!match) {
          return false;
        }
      } else if (rp == storage.PROPS.R_DISABLE) {
        // quick disable return even without load output
        values[rp.getId()] = rule.getIntProp(i);
      }
    }
    if (!loadOutput) {
      return true;
    }
    // accept it
    for (int i = 0; i < properties.length; i++) {
      RenderingRuleProperty rp = properties[i];
      if (rp.isOutputProperty()) {
        searchResult = true;
        if (rp.isFloat()) {
          fvalues[rp.getId()] = rule.getFloatProp(i);
          values[rp.getId()] = rule.getIntProp(i);
        } else {
          values[rp.getId()] = rule.getIntProp(i);
        }
      }
    }

    for (RenderingRule rr : rule.getIfElseChildren()) {
      boolean match = visitRule(rr, loadOutput);
      if (match) {
        break;
      }
    }

    for (RenderingRule rr : rule.getIfChildren()) {
      visitRule(rr, loadOutput);
    }
    return true;
  }