FileDocCategorySizeDatePackage
PIMBridge.javaAPI DocphoneME MR2 API (J2ME)23744Wed May 02 18:00:28 BST 2007com.sun.kvem.midp.pim

PIMBridge.java

/*
 *   
 *
 * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 only, as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License version 2 for more details (a copy is
 * included at /legal/license.txt).
 * 
 * You should have received a copy of the GNU General Public License
 * version 2 along with this work; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 or visit www.sun.com if you need additional
 * information or have any questions.
 */

package com.sun.kvem.midp.pim;

import javax.microedition.pim.PIMException;
import javax.microedition.pim.PIM;
import java.io.*;
import java.util.Hashtable;
import java.util.Enumeration;
import com.sun.midp.log.*;
import com.sun.midp.main.Configuration;
import com.sun.kvem.midp.pim.formats.FormatSupport;


/**
 * Implementations of shared PIM code.
 */
public class PIMBridge extends PIMHandler {

    /**
     * Contact table.
     */
    private static Hashtable contactListFields = new Hashtable();

    /**
     * Event table.
     */
    private static Hashtable eventListFields   = new Hashtable();

    /**
     * Todo table.
     */
    private static Hashtable todoListFields    = new Hashtable();

    /**
     * PIMItem data storage.
     */
    private static PIMDatabase database;

    /**
     * Constant representing a Contact List.
     */
    public static final int CONTACT_LIST = 1;

    /**
     * Constant representing an Event List.
     */
    public static final int EVENT_LIST = 2;

    /**
     * Constant representing a ToDo List.
     */
    public static final int TODO_LIST = 3;

    /**
     * Initialization flag.
     */
    private static boolean initialized = false;


    /**
     * This class holds information about a single list.
     */
    private class List {
        /** Type of the list: CONTACT_LIST, EVENT_LIST or TODO_LIST */
        int type;

        /** Name of the list */
        String name;

        /**
         * The only constructor for this list descriptor.
         *
         * @param listType CONTACT_LIST, EVENT_LIST or TODO_LIST
         * @param listName name of the list
         */
        List(int listType, String listName) {
            type = listType;
            name = listName;
        }
    }

    /**
     * Set up data structures.
     */
    public synchronized void initialize() {
        if (!initialized) {
            initializeMap(contactListFields,
            SupportedPIMFields.CONTACT_LIST_FIELDS);
            initializeMap(eventListFields,
            SupportedPIMFields.EVENT_LIST_FIELDS);
            initializeMap(todoListFields,
            SupportedPIMFields.TODO_LIST_FIELDS);
        try {
                database = new PIMDatabase(
            Configuration.getProperty("PIMRootDir") + "pim");
                initialized = true;
        } catch (IOException e) {
            if (Logging.TRACE_ENABLED) {
                    Logging.trace(e, "Unable to create PIMDatabase");
        }
            }
    }
    }

    /**
     *  Initialization one structure.
     *
     * @param map          Hashtable for initialization
     * @param descriptors  array of the field descriptors
     */
    private void initializeMap(Hashtable map,
        PIMFieldDescriptor[] descriptors) {
        for (int i = 0; i < descriptors.length; i++) {
            map.put(new Integer(descriptors[i].getField()), descriptors[i]);
        }
    }

    /**
     *  Gets the table of fields for given list type.
     *
     * @param listType    CONTACT_LIST, EVENT_LIST or  TODO_LIST
     *
     * @return hashtable of fields
     */
    private Hashtable getFields(int listType) {
        Hashtable map;
        switch (listType) {
            case CONTACT_LIST:
                map = contactListFields;
                break;
            case EVENT_LIST:
                map = eventListFields;
                break;
            case TODO_LIST:
                map = todoListFields;
                break;
            default:
                throw new IllegalArgumentException("List type " + listType
                    + " is not valid");
        }
        return map;
    }

    /**
     *  Gets the descriptor for given field.
     *
     * @param listType    CONTACT_LIST, EVENT_LIST or  TODO_LIST
     * @param field the field ID
     *
     * @return field descriptor
     */
    private PIMFieldDescriptor getFieldDescriptor(int listType, int field) {
        return (PIMFieldDescriptor)getFields(listType).get(new Integer(field));
    }

    /**
     * Gets all fields that are supported in this list.  All fields supported by
     * this list, including both standard and extended, are returned in this
     * array.
     *
     * @param listHandle handle of list
     * @return  an int array containing all fields supported by this list.  The
     *          order of the fields returned is unspecified.  If there are no
     *          supported fields, a zero-length array is returned.
     */
    public int[] getSupportedFields(Object listHandle) {
        initialize();

        Hashtable map = getFields(((List)listHandle).type);
        Enumeration fieldNumbers = map.keys();
        int len = map.size();
        int[] result = new int[len];

        for (int i = 0; i < len; i++) {
            result[i] = (fieldNumbers.nextElement()).hashCode();
        }

        return result;
    }

    /**
     * Checks if field is supported in list.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return <code>true</code> if field supported
     */
    public boolean isSupportedField(Object listHandle, int field) {
        initialize();
        return getFieldDescriptor(((List)listHandle).type, field) != null;
    }

    /**
     * Checks if field has default value.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return <code>true</code> if field supported
     */
    public boolean hasDefaultValue(Object listHandle, int field) {
        initialize();
        return getFieldDescriptor(((List)listHandle).type, field)
                .hasDefaultValue();
    }

    /**
     * Gets the data type of the field.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return data type identifier
     */
    public int getFieldDataType(Object listHandle, int field) {
        initialize();
        try {
            return getFieldDescriptor(((List)listHandle).type, field)
                    .getDataType();
        } catch (NullPointerException npe) {
            return -1;
        }
    }

    /**
     * Gets the label of the field.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return label of the field
     */
    public String getFieldLabel(Object listHandle, int field) {
        initialize();
        try {
            return getFieldDescriptor(((List)listHandle).type, field)
                    .getLabel();
        } catch (NullPointerException npe) {
            return null;
        }
    }

    /**
     * Gets the default integer value for the given field. This will
     *  only
     * return a valid value if hasDefaultValue(listType, field) returns true.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return default value of the field
     */
    public int getDefaultIntValue(Object listHandle, int field) {
        initialize();
        PIMFieldDescriptor descriptor =
            getFieldDescriptor(((List)listHandle).type, field);
        return ((Integer) descriptor.getDefaultValue()).intValue();
    }

    /**
     * Gets the default string value for the given field. This will
     * only
     * return a valid value if hasDefaultValue(listType, field) returns true.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return default value of the field
     */
    public String getDefaultStringValue(Object listHandle, int field) {
        return null;
    }

    /**
     * Gets the default String[] value for the given field. This will
     * only
     * return a valid value if hasDefaultValue(listType, field) returns true.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return default value of the field
     */
    public String[] getDefaultStringArrayValue(Object listHandle, int field) {
        int length = getStringArraySize(listHandle, field);
        return new String[length];
    }

    /**
     * Gets the default date value for the given field. This will only
     * return a valid value if hasDefaultValue(listType, field) returns true.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return default value of the field
     */
    public long getDefaultDateValue(Object listHandle, int field) {
        return 0;
    }

    /**
     * Gets the default byte[] value for the given field. This will
     * only
     * return a valid value if hasDefaultValue(listType, field) returns true.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return default value of the field
     */
    public byte[] getDefaultBinaryValue(Object listHandle, int field) {
        return null;
    }

    /**
     * Gets the default boolean value for the given field. This will
     * only
     * return a valid value if hasDefaultValue(listType, field) returns true.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return default value of the field
     */
    public boolean getDefaultBooleanValue(Object listHandle, int field) {
        return false;
    }

    /**
     * Gets the supported attributes for the given field.
     * @param listHandle handle of the list
     * @param field identifier of field
     * @return array of supported attributes of the field
     */
    public int[] getSupportedAttributes(Object listHandle, int field) {
        initialize();
        int listType = ((List)listHandle).type;
        long attributes = getFieldDescriptor(listType, field)
            .getSupportedAttributes();
        int elementCount = listType == PIM.CONTACT_LIST ? 1 : 0;
        for (long a = attributes; a > 0; a >>= 1) {
            if ((a & 1) == 1) {
                elementCount++;
            }
        }
        int[] result = new int[elementCount];
        if (elementCount > 0) {
            int a = 1;
            int i;
            if (listType == PIM.CONTACT_LIST) {
                result[0] = PIMItem.ATTR_NONE;
                i = 1;
            } else {
                i = 0;
            }
            for (; i < elementCount; i++) {
                while ((attributes & a) == 0) a <<= 1;
                result[i] = a;
                a <<= 1;
            }
        }
        return result;
    }

    /**
     * Gets a mask containing all possible attributes for the given field.
     *
     * @param listHandle handle of the list
     * @param field the field number
     * @return supported attribute mask
     */
    public int getSupportedAttributesMask(Object listHandle, int field) {
        initialize();
        return (int)getFieldDescriptor(((List)listHandle).type, field)
                .getSupportedAttributes();
    }

    /**
     * Gets attribute label for the given field attribute.
     *
     * @param listHandle handle of the list
     * @param attribute identifier of attribute
     * @return attribute label
     */
    public String getAttributeLabel(Object listHandle, int attribute) {
        initialize();
        StringBuffer tag = new StringBuffer("PIM.Attributes.");
        if (attribute == 0) {
            tag.append("None");
        } else {
            switch (((List)listHandle).type) {
                case CONTACT_LIST: tag.append("ContactList."); break;
                case EVENT_LIST: tag.append("EventList."); break;
                case TODO_LIST: tag.append("ToDoList."); break;
                default: return null;
            }
            int index = 0;
            while (attribute > 1) {
                index++;
                attribute = attribute >> 1;
            }
            tag.append(index);
        }
        String tagString = tag.toString();
        String returnValue = Configuration.getPropertyDefault(tagString,
            "Label_" + tagString);
        return returnValue;
    }

    /**
     * Checks if attribute is supported.
     *
     * @param listHandle handle of the list
     * @param field the field number
     * @param attribute identifier of attribute
     * @return <code>true</code> if attribute is supported
     */
    public boolean isSupportedAttribute(Object listHandle, int field,
        int attribute) {
        initialize();
        if (attribute == PIMItem.ATTR_NONE) {
            return true;
        } else {
            long attributes = getFieldDescriptor(((List)listHandle).type, field)
                .getSupportedAttributes();
            return (attributes & attribute) != 0;
        }
    }

    /**
     * Checks if size of the string array.
     *
     * @param listHandle handle of the list
     * @param field the field number
     * @return size of the string array
     */
    public int getStringArraySize(Object listHandle, int field) {
        initialize();
        try {
            return getFieldDescriptor(((List)listHandle).type, field)
                .getStringArraySize();
        } catch (NullPointerException npe) {
            // debug.exception(Debug.LIGHT, npe);
            return 0;
        }
    }

    /**
     * Gets the array of supported elements.
     *
     * @param listHandle handle of the list
     * @param field the field number
     * @return array of supported elements
     */
    public int[] getSupportedArrayElements(Object listHandle, int field) {
        int size = getStringArraySize(listHandle, field);
        int[] result = new int[size];
        for (int i = 0; i < size; i++) {
            result[i] = i;
        }
        return result;
    }

    /**
     * Gets the array element label.
     *
     * @param listHandle handle of the list
     * @param field the field number
     * @param arrayElement the element identifier
     * @return label fro the array element
     */
    public String getArrayElementLabel(Object listHandle, int field,
        int arrayElement) {
        initialize();
        return getFieldDescriptor(((List)listHandle).type, field)
            .getElementlabel(arrayElement);
    }

    /**
     * Checks if the array element is supported.
     *
     * @param listHandle handle of the list
     * @param field the field number
     * @param arrayElement the element identifier
     * @return <code>true</code> if attribute element is supported
     */
    public boolean isSupportedArrayElement(Object listHandle, int field,
            int arrayElement) {
        return arrayElement >= 0 &&
            arrayElement < getStringArraySize(listHandle, field);
    }

    /**
     * Get the maximum number of values that can be stored in the given field.
     *
     * @param listHandle handle of the list
     * @param field the field type
     * @return the maximum value
     */
    public int getMaximumValues(Object listHandle, int field) {
        initialize();
        return getFieldDescriptor(((List)listHandle).type, field)
            .getMaximumValues();
    }

    /**
     * Get the supported list names for the given list type. All list elements
     * must be unique within the list.
     *
     * @param listType the type of the list
     * @return a non-null array of supported list names. A copy of this array is
     * returned by PIM.listPIMLists()
     */
    synchronized public String[] getListNames(int listType) {
        initialize();
        int length = database.getListNames(listType).length;
        String[] names = new String[length];
        for (int i = 0; i < length; i++) {
            names[i] = database.getListNames(listType)[i];
        }
        return names;
    }

    /**
     * Get the name of the default list for the given type.
     *
     * @param listType the type of the list
     * @return the name of the default list, or null if no list of this type
     * is supported.
     */
    public String getDefaultListName(int listType) {
        initialize();
        return database.getDefaultListName(listType);
    }

    /**
     * Opens list.
     *
     * @param listType the type of the list
     * @param listName the name of the list
     * @param openMode open mode
     * @return list handle that will be used to access this list
     * @throws PIMException  in case of I/O error.
     */
    public Object openList(int listType, String listName, int openMode)
        throws PIMException {
        return new List(listType, listName);
    }

    /**
     * Closes list.
     *
     * @param listHandle handle of list
     * @throws PIMException  in case of I/O error.
     */
    public void closeList(Object listHandle)
        throws PIMException {
    }

    /**
     * Get list element keys.
     *
     * @param listHandle handle of the list
     * @return an array of objects representing PIM element keys. These keys
     * are to be passed to getListElement() and commitListElement().
     * @throws PIMException  in case of I/O error.
     */
    synchronized public Object[] getListKeys(Object listHandle)
            throws PIMException {
        initialize();

        Hashtable hash_keys =
            database.getKeys(((List)listHandle).type, ((List)listHandle).name);
        int len = hash_keys.size();
        Object[] keys = new Object[len];
        Enumeration en_keys = hash_keys.keys();

        for (int i = 0; i < len; i++) {
            keys[i] = en_keys.nextElement().toString();
        }

        return keys;
    }

    /**
     * Get the data for a list element.
     * @param listHandle handle of the list
     * @param elementKey the key of the requested element
     * @return a byte array containing the element data in a supported format
     * @throws PIMException  in case of I/O error.
     */
    public byte[] getListElement(Object listHandle,
        Object elementKey) throws PIMException {
        initialize();
        return database.getElement(((List)listHandle).type,
            ((List)listHandle).name, (String)elementKey);

    }

    /**
     * Get categories for the specified list element.
     * @param listHandle handle of list
     * @param elementKey the key of the requested element
     * @return an array of categories names
     * @throws PIMException  in case of I/O error.
     */
    public String[] getListElementCategories(Object listHandle,
        Object elementKey) throws PIMException {

        return new String[0];
    }

    /**
     * Commit a list element.
     *
     * @param listHandle handle of the list
     * @param elementKey the key of the element to be stored, or null if this
     * is a new element.
     * @param element element data in a form that can be interpreted
     * by getListElement()
     * @param categories list of categories which the list element belongs to
     * @return a non-null key for this element, to be used in future calls
     * to commitListElement() and getListElement()
     * @throws PIMException  in case of I/O error.
     */
    synchronized public Object commitListElement(Object listHandle,
        Object elementKey, byte[] element, String[] categories)
        throws PIMException {
        initialize();
        elementKey = database.commitElement(((List)listHandle).type,
            ((List)listHandle).name, (String)elementKey, element);
        return elementKey;
    }

    /**
     * Gets the set of categories defined for a list.
     *
     * @param listHandle handle of the list
     * @return the set of defined categories
     * @throws PIMException  If an error occurs or
     * the list is no longer accessible or closed.
     */
    public String[] getCategories(Object listHandle)
        throws PIMException {
        initialize();
        String result = database.getCategories(((List)listHandle).type,
            ((List)listHandle).name);
        return FormatSupport.split(result, '\n', 0);
    }

    /**
     * Adds a category to the categories defined for a list.
     *
     * @param listHandle handle of list
     * @param category category name
     * @throws PIMException  If an error occurs or
     * the list is no longer accessible or closed.
     * @see #getCategories
     */
    public void addCategory(Object listHandle,
        String category) throws PIMException {
        initialize();
        String cats = database.getCategories(((List)listHandle).type,
            ((List)listHandle).name);
        // the implementation expects that '\n' is never escaped in categories
        String cat_add = "\n" + category;
        if (cats.indexOf(cat_add + '\n') != -1 ||
            cats.startsWith(category + '\n') ||
            cats.endsWith(cat_add) ||
            ((cats.length() > 0) && cats.equals(category))) {
            return;
        }
        if (cats.length() == 0 && category.length() > 0) {
            cats = category;
        } else {
            cats += cat_add;
        }
        database.setCategories(((List)listHandle).type,
            ((List)listHandle).name, cats);
    }

    /**
     * Deletes a category from the categories defined for a list.
     *
     * @param listHandle handle of list
     * @param category category name
     * @throws PIMException  If an error occurs or
     * the list is no longer accessible or closed.
     * @see #getCategories
     */
    public void deleteCategory(Object listHandle,
        String category) throws PIMException {
        initialize();
        String cats = database.getCategories(((List)listHandle).type,
            ((List)listHandle).name);
        // the implementation expects that '\n' is never escaped in categories
        String cat_add = "\n" + category;
        int pos;
        if ((pos = cats.indexOf(cat_add + '\n')) != -1) {
            cats = cats.substring(0, pos)
                + cats.substring(pos + cat_add.length());
        } else if (cats.startsWith(category + '\n')) {
            cats = cats.substring(cat_add.length());
        } else if (cats.endsWith(cat_add)) {
            cats = cats.substring(0, cats.length() - cat_add.length());
        } else if (cats.equals(category)) {
            cats = "";
        } else {
            return;
        }
        database.setCategories(((List)listHandle).type,
            ((List)listHandle).name, cats);
    }

    /**
     * Rename a category.
     *
     * @param listHandle handle of list
     * @param currentCategory current category name
     * @param newCategory new category name
     * @throws PIMException  If an error occurs or
     * the list is no longer accessible or closed.
     * @see #getCategories
     */
    public void renameCategory(Object listHandle,
        String currentCategory, String newCategory) throws PIMException {
        deleteCategory(listHandle, currentCategory);
        addCategory(listHandle, newCategory);
    }
}