All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robolectric.res.ResBundle Maven / Gradle / Ivy

package org.robolectric.res;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

public class ResBundle {
  private final ResMap valuesMap = new ResMap();
  private final ResMap> valuesArrayMap = new ResMap>();
  private String overrideNamespace;

  public void put(String attrType, String name, T value, XmlLoader.XmlContext xmlContext) {
    ResName resName = new ResName(maybeOverride(xmlContext.packageName), attrType, name);
    Values values = valuesMap.find(resName);
    values.add(new Value(xmlContext.getQualifiers(), value, xmlContext));
    Collections.sort(values);
  }

  public T get(ResName resName, String qualifiers) {
    Value value = getValue(resName, qualifiers);
    return value == null ? null : value.value;
  }

  public Value getValue(ResName resName, String qualifiers) {
    Values values = valuesMap.find(maybeOverride(resName));
    return (values != null) ? pick(values, qualifiers) : null;
  }

  public static  Value pick(Values values, String qualifiers) {
    final int count = values.size();
    if (count == 0) return null;

    BigInteger possibles = BigInteger.ZERO;
    for (int i = 0; i < count; i++) possibles = possibles.setBit(i);

    StringTokenizer st = new StringTokenizer(qualifiers, "-");
    while (st.hasMoreTokens()) {
      String qualifier = st.nextToken();
      String paddedQualifier = "-" + qualifier + "-";
      BigInteger matches = BigInteger.ZERO;

      for (int i = 0; i < count; i++) {
        if (!possibles.testBit(i)) continue;

        if (values.get(i).qualifiers.contains(paddedQualifier)) {
          matches = matches.setBit(i);
        }
      }

      if (!matches.equals(BigInteger.ZERO)) {
        possibles = possibles.and(matches); // eliminate any that didn't match this qualifier
      }

      if (matches.bitCount() == 1) break;
    }

    for (int i = 0; i < count; i++) {
      if (possibles.testBit(i)) return values.get(i);
    }
    throw new IllegalStateException("couldn't handle qualifiers \"" + qualifiers + "\"");
  }

  public int size() {
    return valuesMap.size() + valuesArrayMap.size();
  }

  public void makeImmutable() {
    valuesMap.makeImmutable();
    valuesArrayMap.makeImmutable();
  }

  public void overrideNamespace(String overrideNamespace) {
    this.overrideNamespace = overrideNamespace;
    if (size() > 0) throw new RuntimeException();
  }

  String maybeOverride(String namespace) {
    return overrideNamespace == null ? namespace : overrideNamespace;
  }

  ResName maybeOverride(ResName resName) {
    return overrideNamespace == null ? resName : new ResName(overrideNamespace, resName.type, resName.name);
  }

  public void mergeLibraryStyle(ResBundle fromResBundle, String packageName) {
    valuesMap.merge(packageName, fromResBundle.valuesMap);
    valuesArrayMap.merge(packageName, fromResBundle.valuesArrayMap);
  }

  static class Value implements Comparable> {
    final String qualifiers;
    final T value;
    final XmlLoader.XmlContext xmlContext;

    Value(String qualifiers, T value, XmlLoader.XmlContext xmlContext) {
      if (value == null) {
        throw new NullPointerException();
      }

      this.xmlContext = xmlContext;
      this.qualifiers = qualifiers == null ? "--" : "-" + qualifiers + "-";
      this.value = value;
    }

    @Override
    public int compareTo(Value o) {
      return qualifiers.compareTo(o.qualifiers);
    }
  }

  static class Values extends ArrayList> {
  }

  private static class ResMap {
    private final Map> map = new HashMap>();
    private boolean immutable;

    public Values find(ResName resName) {
      Values values = map.get(resName);
      if (values == null) map.put(resName, values = new Values());
      return values;
    }

    private void merge(String packageName, ResMap sourceMap) {
      if (immutable) {
        throw new IllegalStateException("immutable!");
      }

      for (Map.Entry> entry : sourceMap.map.entrySet()) {
        ResName resName = entry.getKey().withPackageName(packageName);
        find(resName).addAll(entry.getValue());
      }
    }

    public int size() {
      return map.size();
    }

    public void makeImmutable() {
      immutable = true;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy