better complex entry structure

This commit is contained in:
REAndroid 2023-05-09 12:49:13 +02:00
parent f0747a6b4f
commit 3a5e7087a8
12 changed files with 613 additions and 161 deletions

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -258,7 +258,7 @@ import java.util.zip.ZipEntry;
return false;
}
TableEntry<?, ?> tableEntry = entry.getTableEntry();
if(tableEntry instanceof ResTableMapEntry){
if(tableEntry instanceof CompoundEntry){
return false;
}
if(!(tableEntry instanceof ResTableEntry)){

View File

@ -16,10 +16,9 @@
package com.reandroid.apk.xmldecoder;
import com.reandroid.apk.XmlHelper;
import com.reandroid.arsc.array.CompoundItemArray;
import com.reandroid.arsc.util.HexUtil;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.arsc.value.*;
import com.reandroid.arsc.value.attribute.AttributeBag;
import com.reandroid.arsc.value.attribute.AttributeBagItem;
import com.reandroid.common.EntryStore;
@ -39,16 +38,18 @@ class BagDecoderAttr<OUTPUT> extends BagDecoder<OUTPUT>{
writer.startTag(tag);
writer.attribute("name", entry.getName());
AttributeBag attributeBag = AttributeBag.create(mapEntry.getValue());
writeParentAttributes(writer, attributeBag);
writeParentAttributes(writer, mapEntry.getValue());
ResValueMap formatsMap = mapEntry.getByType(AttributeType.FORMATS);
boolean is_flag = AttributeTypeFormat.FLAG.matches(formatsMap.getData());
boolean is_flag = attributeBag.isFlag();
String childTag = is_flag ? "flag" : "enum";
AttributeBagItem[] bagItems = attributeBag.getBagItems();
EntryStore entryStore = getEntryStore();
for(int i=0;i< bagItems.length;i++){
for(int i = 0; i < bagItems.length; i++){
AttributeBagItem item = bagItems[i];
if(item.isType()){
continue;
@ -63,7 +64,7 @@ class BagDecoderAttr<OUTPUT> extends BagDecoder<OUTPUT>{
if(item.getBagItem().getValueType() == ValueType.INT_HEX){
value = HexUtil.toHex8(rawVal);
}else {
value = String.valueOf(rawVal);
value = Integer.toString(rawVal);
}
writer.text(value);
@ -72,6 +73,24 @@ class BagDecoderAttr<OUTPUT> extends BagDecoder<OUTPUT>{
return writer.endTag(tag);
}
private void writeParentAttributes(EntryWriter<OUTPUT> writer, CompoundItemArray<? extends ResValueMap> itemArray) throws IOException {
String formats = AttributeTypeFormat.toString(itemArray.getFormats());
if(formats!=null){
writer.attribute(AttributeType.FORMATS.getName(), formats);
}
ResValueMap item = itemArray.getByType(AttributeType.MIN);
if(item != null){
writer.attribute(AttributeType.MIN.getName(), Integer.toString(item.getData()));
}
item = itemArray.getByType(AttributeType.MAX);
if(item != null){
writer.attribute(AttributeType.MAX.getName(), Integer.toString(item.getData()));
}
item = itemArray.getByType(AttributeType.L10N);;
if(item != null){
writer.attribute(AttributeType.L10N.getName(), Integer.toString(item.getData()));
}
}
private void writeParentAttributes(EntryWriter<OUTPUT> writer, AttributeBag attributeBag) throws IOException {
String formats= attributeBag.decodeValueType();
if(formats!=null){

View File

@ -17,11 +17,9 @@ package com.reandroid.apk.xmldecoder;
import com.reandroid.apk.XmlHelper;
import com.reandroid.arsc.chunk.PackageBlock;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.*;
import com.reandroid.arsc.value.plurals.PluralsQuantity;
import com.reandroid.common.EntryStore;
import com.reandroid.xml.XMLElement;
import java.io.IOException;
@ -46,12 +44,11 @@ class BagDecoderPlural<OUTPUT> extends BagDecoder<OUTPUT>{
writer.enableIndent(true);
writer.startTag(childTag);
PluralsQuantity quantity =
PluralsQuantity.valueOf((short) (valueMap.getName() & 0xffff));
if(quantity == null){
AttributeType quantity = valueMap.getAttributeType();
if(quantity == null || !quantity.isPlural()){
throw new IOException("Unknown plural quantity: " + valueMap);
}
writer.attribute("quantity", quantity.toString());
writer.attribute("quantity", quantity.getName());
writeText(writer, packageBlock, valueMap);

View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reandroid.arsc.array;
import com.reandroid.arsc.base.BlockArray;
import com.reandroid.arsc.value.AttributeType;
import com.reandroid.arsc.value.AttributeTypeFormat;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.json.JSONConvert;
import com.reandroid.json.JSONArray;
public abstract class CompoundItemArray<T extends ResValueMap> extends BlockArray<T> implements JSONConvert<JSONArray> {
public CompoundItemArray(){
super();
}
public AttributeTypeFormat[] getFormats(){
ResValueMap formatsMap = getByType(AttributeType.FORMATS);
if(formatsMap != null){
return AttributeTypeFormat.valuesOf(formatsMap.getData());
}
return null;
}
public boolean containsType(AttributeType attributeType){
for(T valueMap : getChildes()){
if(attributeType == valueMap.getAttributeType()){
return true;
}
}
return false;
}
public T getByType(AttributeType attributeType){
if(attributeType == null){
return null;
}
for(T valueMap : getChildes()){
if(attributeType == valueMap.getAttributeType()){
return valueMap;
}
}
return null;
}
public T getByName(int name){
for(T resValueMap : getChildes()){
if(resValueMap != null && name == resValueMap.getName()){
return resValueMap;
}
}
return null;
}
@Override
protected void onRefreshed() {
}
public void onRemoved(){
for(T resValueMap : getChildes()){
resValueMap.onRemoved();
}
}
@Override
public void clearChildes(){
this.onRemoved();
super.clearChildes();
}
@Override
public JSONArray toJson() {
JSONArray jsonArray=new JSONArray();
if(isNull()){
return jsonArray;
}
T[] childes = getChildes();
for(int i = 0; i < childes.length; i++){
jsonArray.put(i, childes[i].toJson());
}
return jsonArray;
}
@Override
public void fromJson(JSONArray json){
clearChildes();
if(json==null){
return;
}
int count=json.length();
ensureSize(count);
for(int i=0;i<count;i++){
get(i).fromJson(json.getJSONObject(i));
}
}
public void merge(CompoundItemArray<?> mapArray){
if(mapArray == null || mapArray == this){
return;
}
clearChildes();
int count = mapArray.childesCount();
ensureSize(count);
for(int i=0;i<count;i++){
ResValueMap coming = mapArray.get(i);
ResValueMap exist = get(i);
exist.merge(coming);
}
}
}

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -15,24 +15,12 @@
*/
package com.reandroid.arsc.array;
import com.reandroid.arsc.base.BlockArray;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.json.JSONConvert;
import com.reandroid.json.JSONArray;
public class ResValueMapArray extends BlockArray<ResValueMap> implements JSONConvert<JSONArray> {
public class ResValueMapArray extends CompoundItemArray<ResValueMap> {
public ResValueMapArray(){
super();
}
public ResValueMap getByName(int name){
for(ResValueMap resValueMap:listItems()){
if(resValueMap != null &&name == resValueMap.getName()){
return resValueMap;
}
}
return null;
}
@Override
public ResValueMap newInstance() {
return new ResValueMap();
@ -42,55 +30,4 @@ public class ResValueMapArray extends BlockArray<ResValueMap> implements JSONCon
public ResValueMap[] newInstance(int len) {
return new ResValueMap[len];
}
@Override
protected void onRefreshed() {
}
public void onRemoved(){
for(ResValueMap resValueMap:listItems()){
resValueMap.onRemoved();
}
}
@Override
public void clearChildes(){
this.onRemoved();
super.clearChildes();
}
@Override
public JSONArray toJson() {
JSONArray jsonArray=new JSONArray();
if(isNull()){
return jsonArray;
}
ResValueMap[] childes = getChildes();
for(int i=0;i<childes.length;i++){
jsonArray.put(i, childes[i].toJson());
}
return jsonArray;
}
@Override
public void fromJson(JSONArray json){
clearChildes();
if(json==null){
return;
}
int count=json.length();
ensureSize(count);
for(int i=0;i<count;i++){
get(i).fromJson(json.getJSONObject(i));
}
}
public void merge(ResValueMapArray bagItemArray){
if(bagItemArray==null||bagItemArray==this){
return;
}
clearChildes();
int count=bagItemArray.childesCount();
ensureSize(count);
for(int i=0;i<count;i++){
ResValueMap coming=bagItemArray.get(i);
ResValueMap exist=get(i);
exist.merge(coming);
}
}
}

View File

@ -429,11 +429,11 @@ public class ValueDecoder {
return null;
}
TableEntry<?, ?> tableEntry = entry.getTableEntry();
if(tableEntry == null || (tableEntry instanceof ResTableMapEntry)){
if(tableEntry == null || (tableEntry instanceof CompoundEntry)){
return null;
}
ResValue resValue =(ResValue) tableEntry.getValue();
int resourceId= resValue.getData();
ResValue resValue = (ResValue) tableEntry.getValue();
int resourceId = resValue.getData();
ValueType valueType= resValue.getValueType();
return buildReferenceValue(store, entry, valueType, resourceId);
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reandroid.arsc.value;
public enum AttributeType {
FORMATS(0x01000000),
MIN(0x01000001),
MAX(0x01000002),
L10N(0x01000003),
OTHER(0x01000004),
ZERO(0x01000005),
ONE(0x01000006),
TWO(0x01000007),
FEW(0x01000008),
MANY(0x01000009);
private final int id;
AttributeType(int id) {
this.id = id;
}
public int getId() {
return id;
}
public boolean isPlural(){
int i = id & 0xffff;
return i>=4 && i<=9;
}
public String getName(){
return name().toLowerCase();
}
@Override
public String toString(){
return getName();
}
public static AttributeType valueOf(int value){
for(AttributeType type:VALUES){
if(type.getId() == value){
return type;
}
}
return null;
}
public static AttributeType fromName(String name){
if(name == null){
return null;
}
name = name.toUpperCase();
if("FORMAT".equals(name)){
return FORMATS;
}
for(AttributeType type:VALUES){
if(name.equals(type.name())){
return type;
}
}
return null;
}
private static final AttributeType[] VALUES = values();
}

View File

@ -0,0 +1,251 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reandroid.arsc.value;
public enum AttributeTypeFormat {
REFERENCE(1<<0,
new ValueType[]{
ValueType.REFERENCE,
ValueType.ATTRIBUTE,
ValueType.DYNAMIC_REFERENCE,
ValueType.DYNAMIC_ATTRIBUTE,
ValueType.NULL,
}),
STRING(1<<1, new ValueType[]{
ValueType.STRING
}),
INTEGER(1<<2, new ValueType[]{
ValueType.INT_DEC,
ValueType.INT_HEX
}),
BOOL(1<<3, new ValueType[]{
ValueType.INT_BOOLEAN
}),
COLOR(1<<4, new ValueType[]{
ValueType.INT_COLOR_RGB4,
ValueType.INT_COLOR_ARGB4,
ValueType.INT_COLOR_RGB8,
ValueType.INT_COLOR_ARGB8
}),
FLOAT(1<<5, new ValueType[]{
ValueType.FLOAT
}),
DIMENSION(1<<6, new ValueType[]{
ValueType.DIMENSION
}),
FRACTION(1<<7, new ValueType[]{
ValueType.FRACTION
}),
ANY(0x0000FFFF, ValueType.values().clone()),
ENUM(1<<16, new ValueType[]{
ValueType.INT_DEC,
ValueType.INT_HEX
}),
FLAG(1<<17, new ValueType[]{
ValueType.INT_HEX,
ValueType.INT_DEC
});
private final int mask;
private final ValueType[] valueTypes;
AttributeTypeFormat(int mask, ValueType[] valueTypes) {
this.mask = mask;
this.valueTypes = valueTypes;
}
public int getMask() {
return mask;
}
public boolean matches(int value){
int mask = this.mask;
return (value & mask) == mask;
}
public ValueType[] getValueTypes() {
return valueTypes.clone();
}
public boolean contains(ValueType valueType){
ValueType[] valueTypes = this.valueTypes;
for(int i = 0; i < valueTypes.length; i++){
if(valueType == valueTypes[i]){
return true;
}
}
return false;
}
public String getName(){
return name().toLowerCase();
}
@Override
public String toString(){
StringBuilder builder = new StringBuilder();
builder.append(getName());
builder.append('{');
ValueType[] valueTypes = this.valueTypes;
for(int i = 0; i < valueTypes.length; i++){
if(i != 0){
builder.append(',');
}
builder.append(valueTypes[i]);
}
builder.append('}');
return builder.toString();
}
public static String toString(int typeValue){
return toString(valuesOf(typeValue));
}
public static String toString(AttributeTypeFormat[] typeValues){
if(typeValues == null || typeValues.length == 0){
return null;
}
StringBuilder builder = new StringBuilder();
boolean appendOnce = false;
int appendedTypes = 0;
for(AttributeTypeFormat typeValue : typeValues){
if(typeValue == ENUM || typeValue == FLAG){
continue;
}
if(typeValue == AttributeTypeFormat.ANY){
return AttributeTypeFormat.ANY.getName();
}
int mask = typeValue.getMask();
if((appendedTypes & mask) == mask){
continue;
}
if(appendOnce){
builder.append('|');
}
builder.append(typeValue.getName());
appendOnce = true;
appendedTypes = appendedTypes | mask;
}
return builder.toString();
}
public static int sum(AttributeTypeFormat[] typeValues){
if(typeValues == null){
return 0;
}
int result = 0;
for(AttributeTypeFormat typeValue:typeValues){
if(typeValue==null){
continue;
}
result |= typeValue.getMask();
}
return result;
}
public static AttributeTypeFormat[] valuesOf(int value){
AttributeTypeFormat[] tmp = new AttributeTypeFormat[VALUES.length];
int length = 0;
for(AttributeTypeFormat typeValue : VALUES){
int mask = typeValue.getMask();
if(mask == value){
return new AttributeTypeFormat[]{typeValue};
}
if(typeValue == ANY){
continue;
}
if((value & mask) == mask){
tmp[length] = typeValue;
length++;
}
}
if(length == 0){
return null;
}
AttributeTypeFormat[] results = new AttributeTypeFormat[length];
System.arraycopy(tmp, 0, results, 0, length);
return results;
}
public static AttributeTypeFormat[] valuesOf(String valuesString){
if(valuesString == null){
return null;
}
valuesString = valuesString.trim();
String[] valueNames = valuesString.split("\\s*\\|\\s*");
AttributeTypeFormat[] tmp = new AttributeTypeFormat[VALUES.length];
int length = 0;
for(String name:valueNames){
AttributeTypeFormat typeValue = fromName(name);
if(typeValue!=null){
tmp[length] = typeValue;
length++;
}
}
if(length == 0){
return null;
}
AttributeTypeFormat[] results = new AttributeTypeFormat[length];
System.arraycopy(tmp, 0, results, 0, length);
return results;
}
public static AttributeTypeFormat valueOf(int mask){
for(AttributeTypeFormat typeValue:VALUES){
if(typeValue.getMask() == mask){
return typeValue;
}
}
return null;
}
public static AttributeTypeFormat typeOf(int mask){
for(AttributeTypeFormat typeValue:TYPES){
if(typeValue.matches(mask)){
return typeValue;
}
}
return null;
}
public static AttributeTypeFormat fromName(String name){
if(name==null){
return null;
}
name = name.trim().toUpperCase();
for(AttributeTypeFormat typeValue:VALUES){
if(name.equals(typeValue.name())){
return typeValue;
}
}
for(AttributeTypeFormat typeValue:TYPES){
if(name.equals(typeValue.name())){
return typeValue;
}
}
return null;
}
private static final AttributeTypeFormat[] VALUES = new AttributeTypeFormat[]{
REFERENCE,
STRING,
INTEGER,
BOOL,
COLOR,
FLOAT,
DIMENSION,
FRACTION,
ANY
};
private static final AttributeTypeFormat[] TYPES = new AttributeTypeFormat[]{
ENUM,
FLAG
};
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reandroid.arsc.value;
import com.reandroid.arsc.array.CompoundItemArray;
import com.reandroid.arsc.pool.TableStringPool;
import com.reandroid.json.JSONObject;
public abstract class CompoundEntry<ITEM extends ResValueMap, ARRAY extends CompoundItemArray<ITEM>> extends TableEntry<EntryHeaderMap, ARRAY> {
public CompoundEntry(ARRAY mapArray){
super(new EntryHeaderMap(), mapArray);
}
// Valid for type attr
public AttributeTypeFormat[] getAttributeTypeFormats(){
ITEM item = getByType(AttributeType.FORMATS);
if(item != null){
return item.getAttributeTypeFormats();
}
return null;
}
public boolean containsType(AttributeType attributeType){
return getValue().containsType(attributeType);
}
public ITEM getByType(AttributeType attributeType){
return getValue().getByType(attributeType);
}
public void refresh(){
getHeader().setValuesCount(getValue().childesCount());
}
public ITEM[] listResValueMap(){
return getValue().getChildes();
}
public int getParentId(){
return getHeader().getParentId();
}
public void setParentId(int parentId){
getHeader().setParentId(parentId);
}
public int getValuesCount(){
return getHeader().getValuesCount();
}
public void setValuesCount(int valuesCount){
getHeader().setValuesCount(valuesCount);
getValue().setChildesCount(valuesCount);
}
@Override
void linkTableStringsInternal(TableStringPool tableStringPool){
for(ITEM item : listResValueMap()){
item.linkTableStrings(tableStringPool);
}
}
@Override
void onHeaderLoaded(ValueHeader valueHeader){
getValue().setChildesCount(getValuesCount());
}
@Override
void onRemoved(){
getHeader().onRemoved();
getValue().onRemoved();
}
@Override
public JSONObject toJson() {
JSONObject jsonObject = new JSONObject();
getHeader().toJson(jsonObject);
jsonObject.put(NAME_values, getValue().toJson());
return jsonObject;
}
@Override
public void fromJson(JSONObject json) {
getHeader().fromJson(json);
getValue().fromJson(json.optJSONArray(NAME_values));
refresh();
}
@Override
public String toString(){
StringBuilder builder = new StringBuilder();
builder.append(getHeader());
ITEM[] valueMaps = listResValueMap();
int len = valueMaps.length;
int max = len;
if(max>4){
max = 4;
}
for(int i=0;i<max;i++){
builder.append("\n ");
builder.append(valueMaps[i]);
}
if(len>0){
if(max!=len){
builder.append("\n ...");
}
builder.append("\n ");
}
return builder.toString();
}
public static final String NAME_values = "values";
}

View File

@ -302,7 +302,7 @@ public class Entry extends Block implements JSONConvert<JSONObject> {
}
public boolean isComplex(){
return getTableEntry() instanceof ResTableMapEntry;
return getTableEntry() instanceof CompoundEntry;
}
public void setTableEntry(TableEntry<?, ?> tableEntry){
if(tableEntry==this.mTableEntry){

View File

@ -16,47 +16,10 @@
package com.reandroid.arsc.value;
import com.reandroid.arsc.array.ResValueMapArray;
import com.reandroid.arsc.pool.TableStringPool;
import com.reandroid.json.JSONObject;
public class ResTableMapEntry extends TableEntry<EntryHeaderMap, ResValueMapArray> {
public class ResTableMapEntry extends CompoundEntry<ResValueMap, ResValueMapArray> {
public ResTableMapEntry(){
super(new EntryHeaderMap(), new ResValueMapArray());
}
public void refresh(){
getHeader().setValuesCount(getValue().childesCount());
}
public ResValueMap[] listResValueMap(){
return getValue().getChildes();
}
public int getParentId(){
return getHeader().getParentId();
}
public void setParentId(int parentId){
getHeader().setParentId(parentId);
}
public int getValuesCount(){
return getHeader().getValuesCount();
}
public void setValuesCount(int valuesCount){
getHeader().setValuesCount(valuesCount);
getValue().setChildesCount(valuesCount);
}
@Override
void linkTableStringsInternal(TableStringPool tableStringPool){
for(ResValueMap resValueMap : listResValueMap()){
resValueMap.linkTableStrings(tableStringPool);
}
}
@Override
void onHeaderLoaded(ValueHeader valueHeader){
getValue().setChildesCount(getValuesCount());
}
@Override
void onRemoved(){
getHeader().onRemoved();
getValue().onRemoved();
super(new ResValueMapArray());
}
@Override
boolean shouldMerge(TableEntry<?, ?> tableEntry){
@ -80,42 +43,4 @@ public class ResTableMapEntry extends TableEntry<EntryHeaderMap, ResValueMapArra
getValue().merge(coming.getValue());
refresh();
}
@Override
public JSONObject toJson() {
JSONObject jsonObject = new JSONObject();
getHeader().toJson(jsonObject);
jsonObject.put(NAME_values, getValue().toJson());
return jsonObject;
}
@Override
public void fromJson(JSONObject json) {
getHeader().fromJson(json);
getValue().fromJson(json.optJSONArray(NAME_values));
refresh();
}
@Override
public String toString(){
StringBuilder builder = new StringBuilder();
builder.append(getHeader());
ResValueMap[] valueMaps = listResValueMap();
int len = valueMaps.length;
int max = len;
if(max>4){
max = 4;
}
for(int i=0;i<max;i++){
builder.append("\n ");
builder.append(valueMaps[i]);
}
if(len>0){
if(max!=len){
builder.append("\n ...");
}
builder.append("\n ");
}
return builder.toString();
}
public static final String NAME_values = "values";
}

View File

@ -26,6 +26,22 @@ public class ResValueMap extends ValueItem implements AttributeValue{
super(12, OFFSET_SIZE);
}
public AttributeType getAttributeType(){
return AttributeType.valueOf(getNameResourceID());
}
public void setAttributeType(AttributeType attributeType){
setNameResourceID(attributeType.getId());
}
public AttributeTypeFormat[] getAttributeTypeFormats(){
AttributeType attributeType = getAttributeType();
if(attributeType != AttributeType.FORMATS){
return null;
}
return AttributeTypeFormat.valuesOf(getData());
}
public void setAttributeTypeFormats(AttributeTypeFormat[] formats){
setData(AttributeTypeFormat.sum(formats));
}
public Entry getEntry(){
return getParent(Entry.class);
}