1package com.xtremelabs.robolectric.res;
2
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.List;
6import java.util.Map;
7
8class ResourceReferenceResolver<T> {
9    private Map<String, T> attributeNamesToValues = new HashMap<String, T>();
10    private Map<String, List<String>> unresolvedReferences = new HashMap<String, List<String>>();
11    private String referenceType;
12    private String[] allowedReferenceTypesForRawValues;
13
14    ResourceReferenceResolver(String referenceType) {
15        this(referenceType, new String[] { referenceType });
16    }
17
18    ResourceReferenceResolver(String referenceType, String[] allowedReferenceTypesForRawValues) {
19        this.referenceType = referenceType;
20        this.allowedReferenceTypesForRawValues = allowedReferenceTypesForRawValues;
21    }
22
23    public T getValue(String resourceName) {
24        return attributeNamesToValues.get(resourceName);
25    }
26
27    public void processResource(String name, String rawValue, ResourceValueConverter loader, boolean isSystem) {
28        String valuePointer = referenceType + "/" + name;
29
30        boolean isAllowedReferenceType = false;
31        for (String allowedReferenceTypesForRawValue : allowedReferenceTypesForRawValues) {
32            if (rawValue.startsWith("@")
33                    && rawValue.contains(allowedReferenceTypesForRawValue + "/")) {
34                isAllowedReferenceType = true;
35                break;
36            }
37        }
38
39        if (isAllowedReferenceType) {
40            addAttributeReference(rawValue, valuePointer);
41        } else {
42            if (isSystem) {
43                valuePointer = "android:" + valuePointer;
44            }
45            addAttribute(valuePointer, (T) loader.convertRawValue(rawValue));
46        }
47    }
48
49    public void addAttribute(String valuePointer, T value) {
50        attributeNamesToValues.put(valuePointer, value);
51        resolveUnresolvedReferences(valuePointer, value);
52    }
53
54    private void resolveUnresolvedReferences(String attributeName, T value) {
55        List<String> references = unresolvedReferences.remove(attributeName);
56        if (references == null) {
57            return;
58        }
59        for (String reference : references) {
60            attributeNamesToValues.put(reference, value);
61        }
62    }
63
64    private void addUnresolvedReference(String valuePointer, String attributeName) {
65        List<String> references = unresolvedReferences.get(attributeName);
66        if (references == null) {
67            references = new ArrayList<String>();
68            unresolvedReferences.put(attributeName, references);
69        }
70        references.add(valuePointer);
71    }
72
73    private void addAttributeReference(String rawValue, String valuePointer) {
74        String attributeName = rawValue.substring(1);
75        T value = attributeNamesToValues.get(attributeName);
76        if (value == null) {
77            addUnresolvedReference(valuePointer, attributeName);
78        } else {
79            attributeNamesToValues.put(valuePointer, value);
80        }
81    }
82}
83