1package com.xtremelabs.robolectric.res;
2
3import java.lang.reflect.Field;
4import java.lang.reflect.Modifier;
5import java.util.HashMap;
6import java.util.Map;
7
8public class ResourceExtractor {
9    private Map<String, Integer> localResourceStringToId = new HashMap<String, Integer>();
10    private Map<String, Integer> systemResourceStringToId = new HashMap<String, Integer>();
11    private Map<Integer, String> resourceIdToString = new HashMap<Integer, String>();
12
13    public void addLocalRClass(Class rClass) throws Exception {
14        addRClass(rClass, false);
15    }
16
17    public void addSystemRClass(Class rClass) throws Exception {
18        addRClass(rClass, true);
19    }
20
21    private void addRClass(Class rClass, boolean isSystemRClass) throws Exception {
22        for (Class innerClass : rClass.getClasses()) {
23            for (Field field : innerClass.getDeclaredFields()) {
24                if (field.getType().equals(Integer.TYPE) && Modifier.isStatic(field.getModifiers())) {
25                    String section = innerClass.getSimpleName();
26                    String name = section + "/" + field.getName();
27                    int value = field.getInt(null);
28
29                    if (isSystemRClass) {
30                        name = "android:" + name;
31                    }
32
33                    if (!section.equals("styleable")) {
34                        if (isSystemRClass) {
35                            systemResourceStringToId.put(name, value);
36                        } else {
37                            localResourceStringToId.put(name, value);
38                        }
39
40                        if (resourceIdToString.containsKey(value)) {
41                            throw new RuntimeException(value + " is already defined with name: " + resourceIdToString.get(value) + " can't also call it: " + name);
42                        }
43                        resourceIdToString.put(value, name);
44                    }
45                }
46            }
47        }
48    }
49
50    public Integer getResourceId(String resourceName) {
51        if (resourceName.contains("android:")) { // namespace needed for platform files
52            return getResourceId(resourceName, true);
53        } else {
54            return getResourceId(resourceName, false);
55        }
56    }
57
58    public Integer getLocalResourceId(String value) {
59        boolean isSystem = false;
60        return getResourceId(value, isSystem);
61    }
62
63    public Integer getResourceId(String resourceName, boolean isSystemResource) {
64        if (resourceName == null ) {
65            return null;
66        }
67        if (resourceName.equals("@null")) {
68        	return 0;
69        }
70
71        if (resourceName.startsWith("@+id")) {
72            resourceName = resourceName.substring(2);
73        } else if (resourceName.startsWith("@+android:id")) {
74            resourceName = resourceName.substring(2);
75        } else if (resourceName.startsWith("@")) {
76            resourceName = resourceName.substring(1);
77        }
78
79        if (isSystemResource) {
80            return systemResourceStringToId.get(resourceName);
81        } else {
82            return localResourceStringToId.get(resourceName);
83        }
84    }
85
86    public String getResourceName(int resourceId) {
87        return resourceIdToString.get(resourceId);
88    }
89}