Search in sources :

Example 1 with DataType

use of org.robolectric.res.android.DataType in project robolectric by robolectric.

the class AttributeSetBuilderImpl method build.

@Override
public AttributeSet build() {
    Class<?> xmlBlockClass = ReflectionHelpers.loadClass(this.getClass().getClassLoader(), "android.content.res.XmlBlock");
    ByteBuffer buf = ByteBuffer.allocate(16 * 1024).order(ByteOrder.LITTLE_ENDIAN);
    Writer resStringPoolWriter = new Writer();
    final SparseArray<Integer> resIds = new SparseArray<>();
    final int[] maxAttrNameIndex = new int[] { 0 };
    ResXMLTree_attrExt.Writer dummyStart = new ResXMLTree_attrExt.Writer(buf, resStringPoolWriter, null, "dummy") {

        {
            String packageName = resourceResolver.getPackageName();
            for (Entry<Integer, String> entry : attrToValue.entrySet()) {
                Integer attrId = entry.getKey();
                String attrNs = "";
                String attrName;
                ResName attrResName = null;
                String magicAttr = MAGIC_ATTRS.get(attrId);
                if (magicAttr != null) {
                    attrId = null;
                    attrName = magicAttr;
                } else {
                    String attrNameStr = resourceResolver.getResourceName(attrId);
                    attrResName = ResName.qualifyResName(attrNameStr, packageName, "attr");
                    attrNs = attrResName.packageName.equals("android") ? ANDROID_NS : AUTO_NS;
                    attrName = attrResName.name;
                }
                String value = entry.getValue();
                DataType type;
                int valueInt;
                if (value == null || AttributeResource.isNull(value)) {
                    type = DataType.NULL;
                    valueInt = TypedValue.DATA_NULL_EMPTY;
                } else if (AttributeResource.isResourceReference(value)) {
                    ResName resRef = AttributeResource.getResourceReference(value, packageName, null);
                    Integer valueResId = resourceResolver.getIdentifier(resRef.name, resRef.type, resRef.packageName);
                    if (valueResId == 0) {
                        throw new IllegalArgumentException("no such resource " + value + " while resolving value for " + (attrResName == null ? attrName : attrResName.getFullyQualifiedName()));
                    }
                    type = DataType.REFERENCE;
                    if (attrResName != null) {
                        value = "@" + valueResId;
                    }
                    valueInt = valueResId;
                } else if (AttributeResource.isStyleReference(value)) {
                    ResName resRef = AttributeResource.getStyleReference(value, packageName, "attr");
                    Integer valueResId = resourceResolver.getIdentifier(resRef.name, resRef.type, resRef.packageName);
                    if (valueResId == 0) {
                        throw new IllegalArgumentException("no such attr " + value + " while resolving value for " + (attrResName == null ? attrName : attrResName.getFullyQualifiedName()));
                    }
                    type = DataType.ATTRIBUTE;
                    valueInt = valueResId;
                } else if (attrResName == null) {
                    // class, id, or style
                    type = DataType.STRING;
                    valueInt = resStringPoolWriter.string(value);
                } else {
                    TypedValue outValue = parse(attrId, attrResName, value, packageName);
                    type = DataType.fromCode(outValue.type);
                    value = (String) outValue.string;
                    if (type == DataType.STRING && outValue.data == 0) {
                        valueInt = resStringPoolWriter.string(value);
                    } else {
                        valueInt = outValue.data;
                    }
                }
                Res_value resValue = new Res_value(type.code(), valueInt);
                int attrNameIndex = resStringPoolWriter.uniqueString(attrName);
                attr(resStringPoolWriter.string(attrNs), attrNameIndex, resStringPoolWriter.string(value), resValue, attrNs + ":" + attrName);
                if (attrId != null) {
                    resIds.put(attrNameIndex, attrId);
                }
                maxAttrNameIndex[0] = Math.max(maxAttrNameIndex[0], attrNameIndex);
            }
        }
    };
    ResXMLTree_endElementExt.Writer dummyEnd = new ResXMLTree_endElementExt.Writer(buf, resStringPoolWriter, null, "dummy");
    int finalMaxAttrNameIndex = maxAttrNameIndex[0];
    ResXMLTree_header.write(buf, resStringPoolWriter, () -> {
        if (finalMaxAttrNameIndex > 0) {
            ResChunk_header.write(buf, (short) RES_XML_RESOURCE_MAP_TYPE, () -> {
            }, () -> {
                // not particularly compact, but no big deal for our purposes...
                for (int i = 0; i <= finalMaxAttrNameIndex; i++) {
                    Integer value = resIds.get(i);
                    buf.putInt(value == null ? 0 : value);
                }
            });
        }
        ResXMLTree_node.write(buf, RES_XML_START_ELEMENT_TYPE, dummyStart::write);
        ResXMLTree_node.write(buf, RES_XML_END_ELEMENT_TYPE, dummyEnd::write);
    });
    int size = buf.position();
    byte[] bytes = new byte[size];
    // Cast to Buffer because generated covariant return type that returns ByteBuffer is not
    // available on Java 8
    ((Buffer) buf).position(0);
    buf.get(bytes, 0, size);
    Object xmlBlockInstance = ReflectionHelpers.callConstructor(xmlBlockClass, ClassParameter.from(byte[].class, bytes));
    AttributeSet parser = ReflectionHelpers.callInstanceMethod(xmlBlockClass, xmlBlockInstance, "newParser");
    ReflectionHelpers.callInstanceMethod(parser, "next");
    ReflectionHelpers.callInstanceMethod(parser, "next");
    return parser;
}
Also used : Res_value(org.robolectric.res.android.ResourceTypes.Res_value) ResXMLTree_attrExt(org.robolectric.res.android.ResourceTypes.ResXMLTree_attrExt) DataType(org.robolectric.res.android.DataType) ResXMLTree_endElementExt(org.robolectric.res.android.ResourceTypes.ResXMLTree_endElementExt) TypedValue(android.util.TypedValue) ByteBuffer(java.nio.ByteBuffer) Buffer(java.nio.Buffer) ByteBuffer(java.nio.ByteBuffer) SparseArray(android.util.SparseArray) AttributeSet(android.util.AttributeSet) ResName(org.robolectric.res.ResName) Writer(org.robolectric.res.android.ResourceTypes.ResStringPool_header.Writer)

Aggregations

AttributeSet (android.util.AttributeSet)1 SparseArray (android.util.SparseArray)1 TypedValue (android.util.TypedValue)1 Buffer (java.nio.Buffer)1 ByteBuffer (java.nio.ByteBuffer)1 ResName (org.robolectric.res.ResName)1 DataType (org.robolectric.res.android.DataType)1 Writer (org.robolectric.res.android.ResourceTypes.ResStringPool_header.Writer)1 ResXMLTree_attrExt (org.robolectric.res.android.ResourceTypes.ResXMLTree_attrExt)1 ResXMLTree_endElementExt (org.robolectric.res.android.ResourceTypes.ResXMLTree_endElementExt)1 Res_value (org.robolectric.res.android.ResourceTypes.Res_value)1