AbstractPIMItempublic abstract class AbstractPIMItem extends Object implements javax.microedition.pim.PIMItemPartial implementation of PIMItem.
Extended by ContactImpl, EventImpl and ToDoImpl. |
Fields Summary |
---|
private int[] | fieldKeysSorted list of defined field codes. | private PIMField[] | fieldValuesList of defined PIMFields. Indexed by fieldKeys. | private String[] | categoriesList of categories to which this item belongs | private boolean | modifiedHas this item been modified since it was last committed? | private AbstractPIMList | pimListList which this item belongs to. May be null for a deserialized item. | private final int | listTypeType of list this item belongs to (e.g. PIM.CONTACT_LIST).
Note: valid even if pimList is null. | private Object | pimListHandleInternal list used for item description getting. May not be null.
For a deserialized item represents default dummy list | private Object | keyKey for the use of commit() | private PIMHandler | pimHandlerInstance of PIMHandler to simplify access to PIM storage |
Constructors Summary |
---|
protected AbstractPIMItem(AbstractPIMList pimList, int type)Constructs a PIM list.
this.pimList = pimList;
this.listType = type;
pimHandler = PIMHandler.getInstance();
try {
pimListHandle = pimList != null ? pimList.getHandle() :
pimHandler.openList(type, null, PIM.READ_ONLY);
} catch (PIMException e) {
throw new RuntimeException("Error while opening default list");
}
| protected AbstractPIMItem(AbstractPIMList pimList, javax.microedition.pim.PIMItem baseItem)This constructor is used when importing an item.
this(pimList, pimList.getType());
// copy fields
int[] fields = baseItem.getFields();
for (int i = 0; i < fields.length; i++) {
int field = fields[i];
if (!pimList.isSupportedField(field)) {
// skip field
continue;
}
int dataType = pimList.getFieldDataType(field);
int indices = baseItem.countValues(field);
for (int index = 0; index < indices; index++) {
int attributes = baseItem.getAttributes(field, index);
Object value = null;
switch (dataType) {
case PIMItem.BINARY: {
value = baseItem.getBinary(field, index);
break;
}
case PIMItem.BOOLEAN: {
value = new Boolean(baseItem.getBoolean(field, index));
break;
}
case PIMItem.DATE: {
value = new Long(baseItem.getDate(field, index));
break;
}
case PIMItem.INT: {
value = new Integer(baseItem.getInt(field, index));
break;
}
case PIMItem.STRING: {
value = baseItem.getString(field, index);
break;
}
case PIMItem.STRING_ARRAY: {
value = baseItem.getStringArray(field, index);
break;
}
default: {
// cannot import this data. Not a problem, since
// this method is called when importing a PIMItem
// from another list. In this case, it is valid
// to ignore data of an unknown type.
}
} // end switch (dataType)
try {
addValue(field, attributes, value, true);
} catch (FieldFullException ffe) {
// Too many values. It's OK to ignore values that
// don't fit.
} catch (IllegalArgumentException iae) {
// illegal data in this field. It's OK not to import it.
}
} // finish iterating over indices
} // finish iterating over fields
updateRevision();
|
Methods Summary |
---|
public void | addBinary(int field, int attributes, byte[] value, int offset, int length)
validateBinaryValue(value, offset, length);
length = Math.min(length, value.length - offset);
byte[] b = new byte[length];
System.arraycopy(value, offset, b, 0, length);
addValue(field, attributes, b, false);
| public void | addBoolean(int field, int attributes, boolean value)
addValue(field, attributes, new Boolean(value), false);
| public void | addDate(int field, int attributes, long value)
addValue(field, attributes, new Long(value), false);
| public void | addInt(int field, int attributes, int value)
addValue(field, attributes, new Integer(value), false);
| public void | addString(int field, int attributes, java.lang.String value)
validateString(value);
addValue(field, attributes, value, false);
| public void | addStringArray(int field, int attributes, java.lang.String[] value)
checkType(field, STRING_ARRAY);
validateStringArray(field, value);
addValue(field, attributes, value, false);
| public void | addToCategory(java.lang.String category)
if (category == null) {
throw new NullPointerException("Null category");
}
if (categories == null) {
this.categories = new String[] { category };
this.modified = true;
} else {
for (int i = 0; i < categories.length; i++) {
if (categories[i].equals(category)) {
return;
}
}
String[] a = new String[categories.length + 1];
System.arraycopy(categories, 0, a, 0, categories.length);
a[categories.length] = category;
this.categories = a;
this.modified = true;
}
| private void | addValue(int field, int attributes, java.lang.Object value, boolean force)Adds a value to a field.
checkType(field, value);
PIMField pimField = getField(field, true, true);
int maxValues =
pimHandler.getMaximumValues(pimListHandle, field);
int currentValues = pimField.getValueCount();
if (maxValues != -1 && currentValues >= maxValues) {
throw new FieldFullException("Can only store "
+ maxValues + " in field", field);
}
if (!force) {
checkReadOnlyFields(field);
}
if (value instanceof Integer) {
checkIntValue(field, ((Integer)value).intValue());
}
if (pimField.isScalar()) {
// upgrade PIM field
if (currentValues == 0) {
pimField = new ScalarPIMField();
putField(field, pimField);
} else {
Object value0 = pimField.getValue(0);
int attributes0 = pimField.getAttributes(0);
pimField = new VectorPIMField();
pimField.addValue(attributes0, value0);
putField(field, pimField);
}
}
attributes = filterAttributes(field, attributes);
pimField.addValue(attributes, value);
modified = true;
| private void | checkIntValue(int field, int value)
if ((listType == PIM.CONTACT_LIST && field == Contact.CLASS) ||
(listType == PIM.EVENT_LIST && field == Event.CLASS) ||
(listType == PIM.TODO_LIST && field == ToDo.CLASS)) {
validateClass(value);
}
if (listType == PIM.TODO_LIST && field == ToDo.PRIORITY) {
validatePriority(value);
}
| private void | checkReadOnlyFields(int field)Checks the read only fields.
if (key != null) {
if (field == getRevisionField()) {
throw new IllegalArgumentException(
"REVISION field is read only"
+ " except on newly created PIMItems");
} else if (field == getUIDField()) {
throw new IllegalArgumentException(
"UID field is read only except on newly created PIMItems");
}
}
| private void | checkType(int field, java.lang.Object value)Checks the type of a field, throwing an IllegalArgumentException
if given or if the field number is invalid.
try {
int dataType =
pimHandler.getFieldDataType(pimListHandle, field);
switch (dataType) {
case PIMItem.BINARY: {
byte[] b = (byte[]) value;
break;
}
case PIMItem.BOOLEAN: {
Boolean b = (Boolean) value;
break;
}
case PIMItem.DATE: {
Long l = (Long) value;
break;
}
case PIMItem.INT: {
Integer i = (Integer) value;
break;
}
case PIMItem.STRING: {
String s = (String) value;
break;
}
case PIMItem.STRING_ARRAY: {
String[] s = (String[]) value;
break;
}
default:
throw complaintAboutField(listType, field);
}
} catch (ClassCastException cce) {
throw new IllegalArgumentException(cce.getMessage());
}
| private void | checkType(int field, int dataType)Checks the type of a field, throwing an IllegalArgumentException
if given or if the field number is invalid.
int correctDataType =
pimHandler.getFieldDataType(pimListHandle, field);
if (dataType != correctDataType && correctDataType != -1) {
throw new IllegalArgumentException("Wrong data type");
}
if (correctDataType == -1) {
throw complaintAboutField(listType, field);
}
| public void | commit()
if (pimList == null) {
throw new PIMException("Item is not in a list");
}
pimList.checkWritePermission();
pimList.checkOpen();
updateRevision();
setDefaultValues();
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PIMFormat format = getEncodingFormat();
format.encode(baos, "UTF-8", this);
Object newKey = pimList.commit(key, baos.toByteArray(), categories);
if (key == null) {
pimList.addItem(this);
}
setKey(newKey);
updateUID();
modified = false;
} catch (IOException e) {
throw new PIMException("Error persisting PIMItem");
}
| static java.lang.RuntimeException | complaintAboutField(int type, int field)Throw an exception based on field failure type.
if (isValidPIMField(type, field)) {
return new UnsupportedFieldException(String.valueOf(field));
} else {
return new IllegalArgumentException("Invalid field " + field);
}
| public int | countValues(int field)
PIMField pimField = getField(field, false, true);
return pimField == null ? 0 : pimField.getValueCount();
| private int | filterAttributes(int field, int attributes)Filters attributes to include only the supported ones.
if (attributes == 0) {
return 0;
} else {
return attributes
& pimHandler
.getSupportedAttributesMask(pimListHandle, field);
}
| private int | findFieldKey(int key)Returns the index of the given key, if it is present in
fieldKeys[]. If it is not present, returns the binary
complement of the index before which
the key could be inserted. O(log fieldKeys.length) in time.
int lowerBound = 0;
int upperBound = fieldKeys.length;
while (lowerBound != upperBound) {
int index = lowerBound + (upperBound - lowerBound) / 2;
int indexKey = fieldKeys[index];
if (indexKey > key) {
if (index == upperBound) {
upperBound --;
} else {
upperBound = index;
}
} else if (indexKey == key) {
return index;
} else {
if (index == lowerBound) {
lowerBound ++;
} else {
lowerBound = index;
}
}
}
return ~lowerBound;
| protected java.lang.String | formatData()Format the data for output.
StringBuffer sb = new StringBuffer();
for (int i = 0; i < fieldValues.length; i++) {
if (fieldValues[i].getValueCount() != 0) {
PIMField pimField = fieldValues[i];
int field = fieldKeys[i];
int valueCount = pimField.getValueCount();
if (valueCount == 0) {
continue;
}
if (i != 0) {
sb.append(", ");
}
String label =
pimHandler.getFieldLabel(pimListHandle, field);
int dataType =
pimHandler.getFieldDataType(pimListHandle, field);
for (int j = 0; j < valueCount; j++) {
sb.append(label);
if (valueCount != 1) {
sb.append("[");
sb.append(j);
sb.append("]");
}
sb.append("=");
Object value = pimField.getValue(j);
if (value == null) {
sb.append("null");
continue;
}
switch (dataType) {
case STRING_ARRAY: {
String[] aValue = (String[]) value;
sb.append("[");
for (int k = 0; k < aValue.length; k++) {
if (k != 0) {
sb.append(",");
}
sb.append(aValue[k]);
}
sb.append("]");
break;
}
case BINARY: {
byte[] bValue = (byte[]) value;
sb.append("<" + bValue.length + " bytes>");
break;
}
case DATE: {
long dValue = ((Long) value).longValue();
sb.append(pimHandler.composeDateTime(dValue));
break;
}
default:
sb.append(value);
}
}
}
}
if (categories != null && categories.length != 0) {
if (sb.length() > 0) {
sb.append(", ");
}
sb.append("Categories=[");
for (int i = 0; i < categories.length; i++) {
if (i > 0) {
sb.append(",");
}
sb.append(categories[i]);
}
sb.append("]");
}
return sb.toString();
| public int | getAttributes(int field, int index)
return getField(field, true, true).getAttributes(index);
| public byte[] | getBinary(int field, int index)
checkType(field, BINARY);
return (byte[]) getValue(field, index);
| public boolean | getBoolean(int field, int index)
checkType(field, BOOLEAN);
return ((Boolean) getValue(field, index)).booleanValue();
| public java.lang.String[] | getCategories()
if (categories == null) {
return new String[0];
}
String[] cs = new String[categories.length];
System.arraycopy(categories, 0, cs, 0, categories.length);
return cs;
| java.lang.String[] | getCategoriesRaw()
return categories;
| public long | getDate(int field, int index)
checkType(field, DATE);
try {
return ((Long) getValue(field, index)).longValue();
} catch (ClassCastException e) {
throw e;
}
| abstract PIMFormat | getEncodingFormat()Gets the format codec used to encode and decode this object
for storage.
| PIMField | getField(int field, boolean create, boolean check)Gets the field entry.
PIMField f = getField(field);
if (f == null) {
if (check && !pimHandler.isSupportedField(pimListHandle, field)) {
throw complaintAboutField(listType, field);
}
if (create) {
f = new EmptyPIMField();
putField(field, f);
}
}
return f;
| public PIMField | getField(int key)Looks up a PIMField. O(log fieldKeys.length) in time.
int index = findFieldKey(key);
if (index >= 0) {
return fieldValues[index];
} else {
return null;
}
| public int[] | getFields()
int emptyFields = 0;
// make sure all these fields have defined values
for (int i = 0; i < fieldValues.length; i++) {
if (fieldValues[i].getValueCount() == 0) {
emptyFields ++;
}
}
int[] keys = new int[fieldKeys.length - emptyFields];
for (int i = 0, j = 0; i < keys.length; i++) {
if (emptyFields == 0 || fieldValues[i].getValueCount() != 0) {
keys[j++] = fieldKeys[i];
} else {
emptyFields --;
}
}
return keys;
| public int | getInt(int field, int index)
checkType(field, INT);
try {
return ((Integer) getValue(field, index)).intValue();
} catch (ClassCastException e) {
String message = "Cannot convert to integer on field "
+ field + ": "
+ getValue(field, index).getClass();
throw new ClassCastException(message);
}
| java.lang.Object | getKey()Gets the key that identifies this item in the PIM database
return key;
| public javax.microedition.pim.PIMList | getPIMList()
return pimList;
| public java.lang.Object | getPIMListHandle()Returns the handle of the PIMList associated with this item.
return pimListHandle;
| protected abstract int | getRevisionField()Gets the field that corresponds to the REVISION of this PIMItem.
REVISION fields have special handling; they are set automatically
on commit and import, and are read only to the application once
the item has been committed.
| public java.lang.String | getString(int field, int index)
checkType(field, STRING);
return (String) getValue(field, index);
| public java.lang.String[] | getStringArray(int field, int index)
checkType(field, STRING_ARRAY);
return (String[]) getValue(field, index);
| protected abstract int | getUIDField()Gets the field that corresponds to the UID of this PIMItem.
UIDfields have special handling; they are set automatically
on commit and import.
| private java.lang.Object | getValue(int field, int index)Gets current value.
PIMField pimField = getField(field, false, true);
if (pimField == null) {
throw new IndexOutOfBoundsException("Empty field: " + field);
}
int currentValues = pimField.getValueCount();
if (index < 0 || index >= currentValues) {
throw new IndexOutOfBoundsException("0 <= index < "
+ currentValues + ", " + index + " not in range");
}
return pimField.getValue(index);
| boolean | isInCategory(java.lang.String category)Checks the category is valid.
if (categories == null) {
return false;
} else {
for (int i = 0; i < categories.length; i++) {
if (categories[i].equals(category)) {
return true;
}
}
return false;
}
| public boolean | isModified()
return modified;
| static boolean | isValidPIMField(int type, int field)Checks for valid PIM field.
switch (type) {
case PIM.CONTACT_LIST:
return ContactImpl.isValidPIMField(field);
case PIM.EVENT_LIST:
return EventImpl.isValidPIMField(field);
case PIM.TODO_LIST:
return ToDoImpl.isValidPIMField(field);
default:
return false;
}
| public int | maxCategories()
return -1;
| public void | putField(int key, PIMField field)Stores a PIMField. O(fieldKeys.length) in space and time.
int index = findFieldKey(key);
if (index >= 0) {
fieldValues[index] = field;
} else {
index = ~index;
int[] newKeys = new int[fieldKeys.length + 1];
PIMField[] newFields = new PIMField[fieldValues.length + 1];
System.arraycopy(fieldKeys, 0, newKeys, 0, index);
System.arraycopy(fieldValues, 0, newFields, 0, index);
newKeys[index] = key;
newFields[index] = field;
System.arraycopy(fieldKeys, index, newKeys, index + 1,
fieldKeys.length - index);
System.arraycopy(fieldValues, index, newFields, index + 1,
fieldKeys.length - index);
this.fieldKeys = newKeys;
this.fieldValues = newFields;
}
| void | remove()Removed this PIMItem from its list
if (pimList == null) {
throw new PIMException("Item is not in a list");
}
pimList.checkWritePermission();
pimList.commit(key, null, null);
setKey(null);
pimList = null;
| public void | removeField(int key)Removes a PIMField. O(fieldKeys.length) in space and time.
int index = findFieldKey(key);
if (index >= 0) {
int[] newKeys = new int[fieldKeys.length - 1];
PIMField[] newFields = new PIMField[fieldValues.length - 1];
System.arraycopy(fieldKeys, 0, newKeys, 0, index);
System.arraycopy(fieldValues, 0, newFields, 0, index);
System.arraycopy(fieldKeys, index + 1, newKeys, index,
newKeys.length - index);
System.arraycopy(fieldValues, index + 1, newFields, index,
newKeys.length - index);
this.fieldKeys = newKeys;
this.fieldValues = newFields;
}
| public void | removeFromCategory(java.lang.String category)
if (category == null) {
throw new NullPointerException("Null category");
}
if (categories != null) {
for (int i = 0; i < categories.length; i++) {
if (category.equals(categories[i])) {
if (categories.length == 1) {
this.categories = null;
} else {
String[] a = new String[categories.length - 1];
System.arraycopy(categories, 0, a, 0, i);
System.arraycopy(categories, i + 1, a, i,
a.length - i);
this.categories = a;
}
this.modified = true;
return;
}
}
}
| public void | removeValue(int field, int index)
PIMField pimField = getField(field, false, true);
if (pimField == null) {
throw new IndexOutOfBoundsException("Empty field: " + field);
}
int currentValues = pimField.getValueCount();
if (index < 0 || index >= currentValues) {
throw new IndexOutOfBoundsException("0 <= index < "
+ currentValues + ", " + index + " not in range");
}
checkReadOnlyFields(field);
pimField.removeValue(index);
currentValues --;
if (currentValues == 0) {
removeField(field);
} else if (currentValues == 1) {
// downgrade field
Object value = pimField.getValue(0);
int attributes = pimField.getAttributes(0);
pimField = new ScalarPIMField();
pimField.addValue(attributes, value);
putField(field, pimField);
}
modified = true;
| public void | setBinary(int field, int index, int attributes, byte[] value, int offset, int length)
validateBinaryValue(value, offset, length);
length = Math.min(length, value.length - offset);
byte[] b = new byte[length];
System.arraycopy(value, offset, b, 0, length);
setValue(field, index, attributes, b, false);
| public void | setBoolean(int field, int index, int attributes, boolean value)
setValue(field, index, attributes, new Boolean(value), false);
| public void | setDate(int field, int index, int attributes, long value)
setValue(field, index, attributes, new Long(value), false);
| protected void | setDefaultValues()Sets default values for this item.
int[] supportedFields = pimList.getSupportedFields();
for (int i = 0; i < supportedFields.length; i++) {
int field = supportedFields[i];
PIMField pimField = getField(field, false, true);
if ((pimField == null || pimField.getValueCount() == 0)
&& pimHandler.hasDefaultValue(pimListHandle, field)) {
Object value = null;
switch (pimList.getFieldDataType(field)) {
case PIMItem.BOOLEAN:
value = new Boolean(pimHandler
.getDefaultBooleanValue(pimListHandle, field));
break;
case PIMItem.BINARY:
value = pimHandler
.getDefaultBinaryValue(pimListHandle, field);
break;
case PIMItem.DATE:
value = new Long(pimHandler
.getDefaultDateValue(pimListHandle, field));
break;
case PIMItem.INT:
value = new Integer(pimHandler
.getDefaultIntValue(pimListHandle, field));
break;
case PIMItem.STRING:
value = pimHandler
.getDefaultStringValue(pimListHandle, field);
break;
case PIMItem.STRING_ARRAY:
value = pimHandler
.getDefaultStringArrayValue(pimListHandle, field);
break;
default: continue;
}
addValue(field, PIMItem.ATTR_NONE, value, false);
}
}
| public void | setInt(int field, int index, int attributes, int value)
setValue(field, index, attributes, new Integer(value), false);
| void | setKey(java.lang.Object key)Sets the key that identifies this item in the PIM database
this.key = key;
if (key != null) {
updateUID();
}
| void | setModified(boolean modified)Sets the modified flag.
this.modified = modified;
| void | setPIMList(AbstractPIMList list)Set the PIMList of this item.
this.pimList = list;
pimListHandle = list.getHandle();
| public void | setString(int field, int index, int attributes, java.lang.String value)
validateString(value);
setValue(field, index, attributes, value, false);
| public void | setStringArray(int field, int index, int attributes, java.lang.String[] value)
checkType(field, STRING_ARRAY);
validateStringArray(field, value);
setValue(field, index, attributes, value, false);
| private void | setValue(int field, int index, int attributes, java.lang.Object value, boolean force)Sets the field value.
try {
checkType(field, value);
PIMField pimField = getField(field, false, true);
if (pimField == null) {
throw new IndexOutOfBoundsException("Empty field: " + field);
}
int currentValues = pimField.getValueCount();
if (index < 0 || index >= currentValues) {
throw new IndexOutOfBoundsException("0 <= index < "
+ currentValues + ", " + index + " not in range");
}
if (!force) {
checkReadOnlyFields(field);
}
if (value instanceof Integer) {
checkIntValue(field, ((Integer)value).intValue());
}
attributes = filterAttributes(field, attributes);
pimField.setValue(attributes, value, index);
modified = true;
} catch (ClassCastException e) {
throw new IllegalArgumentException("Wrong type for field");
}
| protected abstract java.lang.String | toDisplayableString()Converts the record to a printable format.
| public java.lang.String | toString()Convert the data to a String.
return "true".equals(System.getProperty("pim.debug"))
? toDisplayableString()
: super.toString();
| private void | updateRevision()Update the revision time.
Long value = new Long(System.currentTimeMillis());
int field = getRevisionField();
if (countValues(field) == 0) {
addValue(field, 0, value, true);
} else {
setValue(field, 0, 0, value, true);
}
| private void | updateUID()Update the UID field.
String value = key.toString();
int field = getUIDField();
if (countValues(field) == 0) {
addValue(field, 0, value, true);
} // don't change UID value, it can be set by user
| private void | validateBinaryValue(byte[] value, int offset, int length)Ensures that binary parameters are in range.
if (value == null) {
throw new NullPointerException("Binary field value"
+" should not be null");
}
if (offset < 0) {
throw new IllegalArgumentException("Negative offset");
}
if (offset + length > value.length) {
throw new IllegalArgumentException("Offset out of range");
}
if (length <= 0) {
throw new IllegalArgumentException("Length must be at least 1");
}
if (value.length == 0) {
throw new IllegalArgumentException("Binary array value "
+ "has zero length");
}
| private void | validateClass(int value)Ensures valid class identifier.
switch (value) {
case javax.microedition.pim.Contact.CLASS_CONFIDENTIAL:
case Contact.CLASS_PRIVATE:
case Contact.CLASS_PUBLIC:
return;
default:
throw new IllegalArgumentException(
"Invalid CLASS value: " + value);
}
| private void | validatePriority(int value)Ensures valid priority identifier.
if (value < 0 || value > 9) {
throw new IllegalArgumentException(
"Invalid PRIORITY value: " + value);
}
| private void | validateString(java.lang.String value)Makes sure that a string is not null.
if (value == null) {
throw new NullPointerException(
"String field value should not be null");
}
| private void | validateStringArray(int field, java.lang.String[] a)Makes sure that
- The string array is not null
- At least one string in the array is not null
- The string array has the correct length
int requiredLength =
pimHandler.getStringArraySize(pimListHandle, field);
if (a.length != requiredLength) {
throw new IllegalArgumentException(
"String array length incorrect: should be " + requiredLength);
}
for (int i = 0; i < a.length; i++) {
if (a[i] != null) {
return;
}
}
throw new IllegalArgumentException("No non-null elements in array");
|
|