Source Code Cross Referenced for AbstractPIMItem.java in  » 6.0-JDK-Modules » j2me » com » sun » kvem » midp » pim » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.kvem.midp.pim 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *   
0003:         *
0004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006:         * 
0007:         * This program is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU General Public License version
0009:         * 2 only, as published by the Free Software Foundation.
0010:         * 
0011:         * This program is distributed in the hope that it will be useful, but
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014:         * General Public License version 2 for more details (a copy is
0015:         * included at /legal/license.txt).
0016:         * 
0017:         * You should have received a copy of the GNU General Public License
0018:         * version 2 along with this work; if not, write to the Free Software
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020:         * 02110-1301 USA
0021:         * 
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional
0024:         * information or have any questions.
0025:         */
0026:
0027:        package com.sun.kvem.midp.pim;
0028:
0029:        import java.io.ByteArrayOutputStream;
0030:        import java.io.IOException;
0031:        import javax.microedition.pim.Contact;
0032:        import javax.microedition.pim.FieldFullException;
0033:        import javax.microedition.pim.PIM;
0034:        import javax.microedition.pim.PIMException;
0035:        import javax.microedition.pim.PIMItem;
0036:        import javax.microedition.pim.PIMList;
0037:        import javax.microedition.pim.UnsupportedFieldException;
0038:
0039:        /**
0040:         * Partial implementation of PIMItem.
0041:         * Extended by ContactImpl, EventImpl and ToDoImpl.
0042:         *
0043:         */
0044:        public abstract class AbstractPIMItem implements  PIMItem {
0045:
0046:            /** Sorted list of defined field codes. */
0047:            private int[] fieldKeys = new int[0];
0048:
0049:            /** List of defined PIMFields. Indexed by fieldKeys. */
0050:
0051:            private PIMField[] fieldValues = new PIMField[0];
0052:
0053:            /** List of categories to which this item belongs */
0054:            private String[] categories = null;
0055:
0056:            /** Has this item been modified since it was last committed? */
0057:            private boolean modified = true;
0058:
0059:            /** List which this item belongs to. May be null for a deserialized item. */
0060:            private AbstractPIMList pimList;
0061:
0062:            /**
0063:             * Type of list this item belongs to (e.g. PIM.CONTACT_LIST).
0064:             * Note: valid even if pimList is null.
0065:             */
0066:            private final int listType;
0067:
0068:            /**
0069:             * Internal list used for item description getting. May not be null.
0070:             * For a deserialized item represents default dummy list
0071:             */
0072:            private Object pimListHandle;
0073:
0074:            /** Key for the use of commit() */
0075:            private Object key = null;
0076:
0077:            /** Instance of PIMHandler to simplify access to PIM storage */
0078:            private PIMHandler pimHandler;
0079:
0080:            /**
0081:             * Constructs a PIM list.
0082:             * @param pimList initial list
0083:             * @param type type of list
0084:             */
0085:            protected AbstractPIMItem(AbstractPIMList pimList, int type) {
0086:                this .pimList = pimList;
0087:                this .listType = type;
0088:                pimHandler = PIMHandler.getInstance();
0089:
0090:                try {
0091:                    pimListHandle = pimList != null ? pimList.getHandle()
0092:                            : pimHandler.openList(type, null, PIM.READ_ONLY);
0093:                } catch (PIMException e) {
0094:                    throw new RuntimeException(
0095:                            "Error while opening default list");
0096:                }
0097:            }
0098:
0099:            /**
0100:             * This constructor is used when importing an item.
0101:             * @param pimList initial list
0102:             * @param baseItem initial entry
0103:             */
0104:            protected AbstractPIMItem(AbstractPIMList pimList, PIMItem baseItem) {
0105:                this (pimList, pimList.getType());
0106:                // copy fields
0107:                int[] fields = baseItem.getFields();
0108:                for (int i = 0; i < fields.length; i++) {
0109:                    int field = fields[i];
0110:                    if (!pimList.isSupportedField(field)) {
0111:                        // skip field
0112:                        continue;
0113:                    }
0114:                    int dataType = pimList.getFieldDataType(field);
0115:                    int indices = baseItem.countValues(field);
0116:                    for (int index = 0; index < indices; index++) {
0117:                        int attributes = baseItem.getAttributes(field, index);
0118:                        Object value = null;
0119:                        switch (dataType) {
0120:                        case PIMItem.BINARY: {
0121:                            value = baseItem.getBinary(field, index);
0122:                            break;
0123:                        }
0124:                        case PIMItem.BOOLEAN: {
0125:                            value = new Boolean(baseItem.getBoolean(field,
0126:                                    index));
0127:                            break;
0128:                        }
0129:                        case PIMItem.DATE: {
0130:                            value = new Long(baseItem.getDate(field, index));
0131:                            break;
0132:                        }
0133:                        case PIMItem.INT: {
0134:                            value = new Integer(baseItem.getInt(field, index));
0135:                            break;
0136:                        }
0137:                        case PIMItem.STRING: {
0138:                            value = baseItem.getString(field, index);
0139:                            break;
0140:                        }
0141:                        case PIMItem.STRING_ARRAY: {
0142:                            value = baseItem.getStringArray(field, index);
0143:                            break;
0144:                        }
0145:                        default: {
0146:                            // cannot import this data. Not a problem, since
0147:                            // this method is called when importing a PIMItem
0148:                            // from another list. In this case, it is valid
0149:                            // to ignore data of an unknown type.
0150:                        }
0151:                        } // end switch (dataType)
0152:                        try {
0153:                            addValue(field, attributes, value, true);
0154:                        } catch (FieldFullException ffe) {
0155:                            // Too many values. It's OK to ignore values that
0156:                            // don't fit.
0157:                        } catch (IllegalArgumentException iae) {
0158:                            // illegal data in this field. It's OK not to import it.
0159:                        }
0160:                    } // finish iterating over indices
0161:                } // finish iterating over fields
0162:                updateRevision();
0163:            }
0164:
0165:            /**
0166:             * Gets the field entry.
0167:             * @param field identifier for the field
0168:             * @param create if <code>true</code> create the field
0169:             * if it doesn't already exist
0170:             * @param check if <code>true</code> check that the field is
0171:             * supported before attempting to get it
0172:             * @return the request field entry
0173:             */
0174:            PIMField getField(int field, boolean create, boolean check) {
0175:                PIMField f = getField(field);
0176:                if (f == null) {
0177:                    if (check
0178:                            && !pimHandler.isSupportedField(pimListHandle,
0179:                                    field)) {
0180:                        throw complaintAboutField(listType, field);
0181:                    }
0182:                    if (create) {
0183:                        f = new EmptyPIMField();
0184:                        putField(field, f);
0185:                    }
0186:                }
0187:                return f;
0188:            }
0189:
0190:            /**
0191:             * Sets the field value.
0192:             * @param field identifier of field
0193:             * @param index value offset
0194:             * @param attributes field properties
0195:             * @param value field to update
0196:             * @param force if <code>true</code> create the value
0197:             */
0198:            private void setValue(int field, int index, int attributes,
0199:                    Object value, boolean force) {
0200:                try {
0201:                    checkType(field, value);
0202:                    PIMField pimField = getField(field, false, true);
0203:                    if (pimField == null) {
0204:                        throw new IndexOutOfBoundsException("Empty field: "
0205:                                + field);
0206:                    }
0207:                    int currentValues = pimField.getValueCount();
0208:                    if (index < 0 || index >= currentValues) {
0209:                        throw new IndexOutOfBoundsException("0 <= index < "
0210:                                + currentValues + ", " + index
0211:                                + " not in range");
0212:                    }
0213:                    if (!force) {
0214:                        checkReadOnlyFields(field);
0215:                    }
0216:                    if (value instanceof  Integer) {
0217:                        checkIntValue(field, ((Integer) value).intValue());
0218:                    }
0219:                    attributes = filterAttributes(field, attributes);
0220:                    pimField.setValue(attributes, value, index);
0221:                    modified = true;
0222:                } catch (ClassCastException e) {
0223:                    throw new IllegalArgumentException("Wrong type for field");
0224:                }
0225:            }
0226:
0227:            /**
0228:             * Adds a value to a field.
0229:             *
0230:             * @param field identifier of field
0231:             * @param attributes field properties
0232:             * @param value field to update
0233:             * @param force if <code>true</code> create the value
0234:             * @throws FieldFullException if no more values can be added to the field
0235:             */
0236:            private void addValue(int field, int attributes, Object value,
0237:                    boolean force) {
0238:
0239:                checkType(field, value);
0240:                PIMField pimField = getField(field, true, true);
0241:                int maxValues = pimHandler.getMaximumValues(pimListHandle,
0242:                        field);
0243:                int currentValues = pimField.getValueCount();
0244:                if (maxValues != -1 && currentValues >= maxValues) {
0245:                    throw new FieldFullException("Can only store " + maxValues
0246:                            + " in field", field);
0247:                }
0248:                if (!force) {
0249:                    checkReadOnlyFields(field);
0250:                }
0251:                if (value instanceof  Integer) {
0252:                    checkIntValue(field, ((Integer) value).intValue());
0253:                }
0254:                if (pimField.isScalar()) {
0255:                    // upgrade PIM field
0256:                    if (currentValues == 0) {
0257:                        pimField = new ScalarPIMField();
0258:                        putField(field, pimField);
0259:                    } else {
0260:                        Object value0 = pimField.getValue(0);
0261:                        int attributes0 = pimField.getAttributes(0);
0262:                        pimField = new VectorPIMField();
0263:                        pimField.addValue(attributes0, value0);
0264:                        putField(field, pimField);
0265:                    }
0266:                }
0267:                attributes = filterAttributes(field, attributes);
0268:                pimField.addValue(attributes, value);
0269:                modified = true;
0270:            }
0271:
0272:            private void checkIntValue(int field, int value) {
0273:                if ((listType == PIM.CONTACT_LIST && field == Contact.CLASS)
0274:                        || (listType == PIM.EVENT_LIST && field == Event.CLASS)
0275:                        || (listType == PIM.TODO_LIST && field == ToDo.CLASS)) {
0276:                    validateClass(value);
0277:                }
0278:                if (listType == PIM.TODO_LIST && field == ToDo.PRIORITY) {
0279:                    validatePriority(value);
0280:                }
0281:            }
0282:
0283:            /**
0284:             * Filters attributes to include only the supported ones.
0285:             * @param field identifier of field
0286:             * @param attributes field properties
0287:             * @return filtered attributes
0288:             */
0289:            private int filterAttributes(int field, int attributes) {
0290:                if (attributes == 0) {
0291:                    return 0;
0292:                } else {
0293:                    return attributes
0294:                            & pimHandler.getSupportedAttributesMask(
0295:                                    pimListHandle, field);
0296:                }
0297:            }
0298:
0299:            /**
0300:             * Gets current value.
0301:             * @param field identifier of field
0302:             * @param index field identifier
0303:             * @return requested field
0304:             */
0305:            private Object getValue(int field, int index) {
0306:                PIMField pimField = getField(field, false, true);
0307:                if (pimField == null) {
0308:                    throw new IndexOutOfBoundsException("Empty field: " + field);
0309:                }
0310:                int currentValues = pimField.getValueCount();
0311:                if (index < 0 || index >= currentValues) {
0312:                    throw new IndexOutOfBoundsException("0 <= index < "
0313:                            + currentValues + ", " + index + " not in range");
0314:                }
0315:                return pimField.getValue(index);
0316:            }
0317:
0318:            // JAVADOC COMMENT ELIDED
0319:            public void addStringArray(int field, int attributes, String[] value) {
0320:                checkType(field, STRING_ARRAY);
0321:                validateStringArray(field, value);
0322:                addValue(field, attributes, value, false);
0323:            }
0324:
0325:            // JAVADOC COMMENT ELIDED
0326:            public void addBoolean(int field, int attributes, boolean value) {
0327:                addValue(field, attributes, new Boolean(value), false);
0328:            }
0329:
0330:            // JAVADOC COMMENT ELIDED
0331:            public void removeFromCategory(String category) {
0332:                if (category == null) {
0333:                    throw new NullPointerException("Null category");
0334:                }
0335:                if (categories != null) {
0336:                    for (int i = 0; i < categories.length; i++) {
0337:                        if (category.equals(categories[i])) {
0338:                            if (categories.length == 1) {
0339:                                this .categories = null;
0340:                            } else {
0341:                                String[] a = new String[categories.length - 1];
0342:                                System.arraycopy(categories, 0, a, 0, i);
0343:                                System.arraycopy(categories, i + 1, a, i,
0344:                                        a.length - i);
0345:                                this .categories = a;
0346:                            }
0347:                            this .modified = true;
0348:                            return;
0349:                        }
0350:                    }
0351:                }
0352:            }
0353:
0354:            // JAVADOC COMMENT ELIDED
0355:            public int[] getFields() {
0356:                int emptyFields = 0;
0357:                // make sure all these fields have defined values
0358:                for (int i = 0; i < fieldValues.length; i++) {
0359:                    if (fieldValues[i].getValueCount() == 0) {
0360:                        emptyFields++;
0361:                    }
0362:                }
0363:                int[] keys = new int[fieldKeys.length - emptyFields];
0364:                for (int i = 0, j = 0; i < keys.length; i++) {
0365:                    if (emptyFields == 0 || fieldValues[i].getValueCount() != 0) {
0366:                        keys[j++] = fieldKeys[i];
0367:                    } else {
0368:                        emptyFields--;
0369:                    }
0370:                }
0371:                return keys;
0372:            }
0373:
0374:            // JAVADOC COMMENT ELIDED
0375:            public boolean getBoolean(int field, int index) {
0376:                checkType(field, BOOLEAN);
0377:                return ((Boolean) getValue(field, index)).booleanValue();
0378:            }
0379:
0380:            // JAVADOC COMMENT ELIDED
0381:            public void addDate(int field, int attributes, long value) {
0382:                addValue(field, attributes, new Long(value), false);
0383:            }
0384:
0385:            // JAVADOC COMMENT ELIDED
0386:            public int maxCategories() {
0387:                return -1;
0388:            }
0389:
0390:            // JAVADOC COMMENT ELIDED
0391:            public void setDate(int field, int index, int attributes, long value) {
0392:                setValue(field, index, attributes, new Long(value), false);
0393:            }
0394:
0395:            // JAVADOC COMMENT ELIDED
0396:            public int getInt(int field, int index) {
0397:                checkType(field, INT);
0398:                try {
0399:                    return ((Integer) getValue(field, index)).intValue();
0400:                } catch (ClassCastException e) {
0401:                    String message = "Cannot convert to integer on field "
0402:                            + field + ": " + getValue(field, index).getClass();
0403:                    throw new ClassCastException(message);
0404:                }
0405:            }
0406:
0407:            // JAVADOC COMMENT ELIDED
0408:            public void setBinary(int field, int index, int attributes,
0409:                    byte[] value, int offset, int length) {
0410:                validateBinaryValue(value, offset, length);
0411:                length = Math.min(length, value.length - offset);
0412:                byte[] b = new byte[length];
0413:                System.arraycopy(value, offset, b, 0, length);
0414:                setValue(field, index, attributes, b, false);
0415:            }
0416:
0417:            // JAVADOC COMMENT ELIDED
0418:            public int getAttributes(int field, int index) {
0419:                return getField(field, true, true).getAttributes(index);
0420:            }
0421:
0422:            // JAVADOC COMMENT ELIDED
0423:            public int countValues(int field) {
0424:                PIMField pimField = getField(field, false, true);
0425:                return pimField == null ? 0 : pimField.getValueCount();
0426:            }
0427:
0428:            // JAVADOC COMMENT ELIDED
0429:            public void addString(int field, int attributes, String value) {
0430:                validateString(value);
0431:                addValue(field, attributes, value, false);
0432:            }
0433:
0434:            // JAVADOC COMMENT ELIDED
0435:            public String[] getCategories() {
0436:                if (categories == null) {
0437:                    return new String[0];
0438:                }
0439:                String[] cs = new String[categories.length];
0440:                System.arraycopy(categories, 0, cs, 0, categories.length);
0441:                return cs;
0442:            }
0443:
0444:            // JAVADOC COMMENT ELIDED
0445:            String[] getCategoriesRaw() {
0446:                return categories;
0447:            }
0448:
0449:            // JAVADOC COMMENT ELIDED
0450:            public void setInt(int field, int index, int attributes, int value) {
0451:                setValue(field, index, attributes, new Integer(value), false);
0452:            }
0453:
0454:            // JAVADOC COMMENT ELIDED
0455:            public void setStringArray(int field, int index, int attributes,
0456:                    String[] value) {
0457:                checkType(field, STRING_ARRAY);
0458:                validateStringArray(field, value);
0459:                setValue(field, index, attributes, value, false);
0460:            }
0461:
0462:            /**
0463:             * Makes sure that
0464:             * <ul>
0465:             * <li>The string array is not null
0466:             * <li>At least one string in the array is not null
0467:             * <li>The string array has the correct length
0468:             * </ul>
0469:             * @param field identifier for field
0470:             * @param a string array to be checked
0471:             */
0472:            private void validateStringArray(int field, String[] a) {
0473:                int requiredLength = pimHandler.getStringArraySize(
0474:                        pimListHandle, field);
0475:                if (a.length != requiredLength) {
0476:                    throw new IllegalArgumentException(
0477:                            "String array length incorrect: should be "
0478:                                    + requiredLength);
0479:                }
0480:                for (int i = 0; i < a.length; i++) {
0481:                    if (a[i] != null) {
0482:                        return;
0483:                    }
0484:                }
0485:                throw new IllegalArgumentException(
0486:                        "No non-null elements in array");
0487:            }
0488:
0489:            /**
0490:             * Makes sure that a string is not null.
0491:             * @param value string to be checked
0492:             */
0493:            private void validateString(String value) {
0494:                if (value == null) {
0495:                    throw new NullPointerException(
0496:                            "String field value should not be null");
0497:                }
0498:            }
0499:
0500:            // JAVADOC COMMENT ELIDED
0501:            public long getDate(int field, int index) {
0502:                checkType(field, DATE);
0503:                try {
0504:                    return ((Long) getValue(field, index)).longValue();
0505:                } catch (ClassCastException e) {
0506:                    throw e;
0507:                }
0508:            }
0509:
0510:            // JAVADOC COMMENT ELIDED
0511:            public void addToCategory(String category) throws PIMException {
0512:                if (category == null) {
0513:                    throw new NullPointerException("Null category");
0514:                }
0515:                if (categories == null) {
0516:                    this .categories = new String[] { category };
0517:                    this .modified = true;
0518:                } else {
0519:                    for (int i = 0; i < categories.length; i++) {
0520:                        if (categories[i].equals(category)) {
0521:                            return;
0522:                        }
0523:                    }
0524:                    String[] a = new String[categories.length + 1];
0525:                    System.arraycopy(categories, 0, a, 0, categories.length);
0526:                    a[categories.length] = category;
0527:                    this .categories = a;
0528:                    this .modified = true;
0529:                }
0530:            }
0531:
0532:            // JAVADOC COMMENT ELIDED
0533:            public void addInt(int field, int attributes, int value) {
0534:                addValue(field, attributes, new Integer(value), false);
0535:            }
0536:
0537:            // JAVADOC COMMENT ELIDED
0538:            public byte[] getBinary(int field, int index) {
0539:                checkType(field, BINARY);
0540:                return (byte[]) getValue(field, index);
0541:            }
0542:
0543:            // JAVADOC COMMENT ELIDED
0544:            public void addBinary(int field, int attributes, byte[] value,
0545:                    int offset, int length) {
0546:                validateBinaryValue(value, offset, length);
0547:                length = Math.min(length, value.length - offset);
0548:                byte[] b = new byte[length];
0549:                System.arraycopy(value, offset, b, 0, length);
0550:                addValue(field, attributes, b, false);
0551:            }
0552:
0553:            /**
0554:             * Ensures that binary parameters are in range.
0555:             * @param value binary data to be checked
0556:             * @param offset index into byte array
0557:             * @param length of data to be checked
0558:             * @throws NullPointerException if value is null
0559:             * @throws IllegalArgumentException if offset or length
0560:             * are not valid
0561:             */
0562:            private void validateBinaryValue(byte[] value, int offset,
0563:                    int length) {
0564:                if (value == null) {
0565:                    throw new NullPointerException("Binary field value"
0566:                            + " should not be null");
0567:                }
0568:                if (offset < 0) {
0569:                    throw new IllegalArgumentException("Negative offset");
0570:                }
0571:                if (offset + length > value.length) {
0572:                    throw new IllegalArgumentException("Offset out of range");
0573:                }
0574:                if (length <= 0) {
0575:                    throw new IllegalArgumentException(
0576:                            "Length must be at least 1");
0577:                }
0578:                if (value.length == 0) {
0579:                    throw new IllegalArgumentException("Binary array value "
0580:                            + "has zero length");
0581:                }
0582:            }
0583:
0584:            // JAVADOC COMMENT ELIDED
0585:            public String[] getStringArray(int field, int index) {
0586:                checkType(field, STRING_ARRAY);
0587:                return (String[]) getValue(field, index);
0588:            }
0589:
0590:            // JAVADOC COMMENT ELIDED
0591:            public void setBoolean(int field, int index, int attributes,
0592:                    boolean value) {
0593:                setValue(field, index, attributes, new Boolean(value), false);
0594:            }
0595:
0596:            // JAVADOC COMMENT ELIDED
0597:            public PIMList getPIMList() {
0598:                return pimList;
0599:            }
0600:
0601:            /**
0602:             * Returns the handle of the PIMList associated with this item.
0603:             *
0604:             * @return   the handle of the PIMList that this item belongs to.  If the
0605:             *           item does not belong to any list, handle of default dummy
0606:             *           list is returned.
0607:             */
0608:            public Object getPIMListHandle() {
0609:                return pimListHandle;
0610:            }
0611:
0612:            /**
0613:             * Set the PIMList of this item.
0614:             * @param list data to be saved
0615:             */
0616:            void setPIMList(AbstractPIMList list) {
0617:                this .pimList = list;
0618:                pimListHandle = list.getHandle();
0619:            }
0620:
0621:            // JAVADOC COMMENT ELIDED
0622:            public void removeValue(int field, int index) {
0623:                PIMField pimField = getField(field, false, true);
0624:                if (pimField == null) {
0625:                    throw new IndexOutOfBoundsException("Empty field: " + field);
0626:                }
0627:                int currentValues = pimField.getValueCount();
0628:                if (index < 0 || index >= currentValues) {
0629:                    throw new IndexOutOfBoundsException("0 <= index < "
0630:                            + currentValues + ", " + index + " not in range");
0631:                }
0632:                checkReadOnlyFields(field);
0633:                pimField.removeValue(index);
0634:                currentValues--;
0635:                if (currentValues == 0) {
0636:                    removeField(field);
0637:                } else if (currentValues == 1) {
0638:                    // downgrade field
0639:                    Object value = pimField.getValue(0);
0640:                    int attributes = pimField.getAttributes(0);
0641:                    pimField = new ScalarPIMField();
0642:                    pimField.addValue(attributes, value);
0643:                    putField(field, pimField);
0644:                }
0645:                modified = true;
0646:            }
0647:
0648:            // JAVADOC COMMENT ELIDED
0649:            public String getString(int field, int index) {
0650:                checkType(field, STRING);
0651:                return (String) getValue(field, index);
0652:            }
0653:
0654:            // JAVADOC COMMENT ELIDED
0655:            public void setString(int field, int index, int attributes,
0656:                    String value) {
0657:                validateString(value);
0658:                setValue(field, index, attributes, value, false);
0659:            }
0660:
0661:            // JAVADOC COMMENT ELIDED
0662:            public boolean isModified() {
0663:                return modified;
0664:            }
0665:
0666:            /**
0667:             * Sets the modified flag.
0668:             * @param modified flag to be saved
0669:             */
0670:            void setModified(boolean modified) {
0671:                this .modified = modified;
0672:            }
0673:
0674:            // JAVADOC COMMENT ELIDED
0675:            public void commit() throws PIMException {
0676:                if (pimList == null) {
0677:                    throw new PIMException("Item is not in a list");
0678:                }
0679:                pimList.checkWritePermission();
0680:                pimList.checkOpen();
0681:                updateRevision();
0682:                setDefaultValues();
0683:                try {
0684:                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
0685:                    PIMFormat format = getEncodingFormat();
0686:                    format.encode(baos, "UTF-8", this );
0687:                    Object newKey = pimList.commit(key, baos.toByteArray(),
0688:                            categories);
0689:                    if (key == null) {
0690:                        pimList.addItem(this );
0691:                    }
0692:                    setKey(newKey);
0693:                    updateUID();
0694:                    modified = false;
0695:                } catch (IOException e) {
0696:                    throw new PIMException("Error persisting PIMItem");
0697:                }
0698:            }
0699:
0700:            /**
0701:             * Gets the format codec used to encode and decode this object
0702:             * for storage.
0703:             * @return an instance of PIMFormat that can deal with this item
0704:             */
0705:            abstract PIMFormat getEncodingFormat();
0706:
0707:            /**
0708:             * Checks the category is valid.
0709:             * @param category name of category to check
0710:             * @return <code>true</code> if is int category
0711:             */
0712:            boolean isInCategory(String category) {
0713:                if (categories == null) {
0714:                    return false;
0715:                } else {
0716:                    for (int i = 0; i < categories.length; i++) {
0717:                        if (categories[i].equals(category)) {
0718:                            return true;
0719:                        }
0720:                    }
0721:                    return false;
0722:                }
0723:            }
0724:
0725:            /**
0726:             * Sets the key that identifies this item in the PIM database
0727:             * @param key an Object used to index this item
0728:             */
0729:            void setKey(Object key) {
0730:                this .key = key;
0731:                if (key != null) {
0732:                    updateUID();
0733:                }
0734:            }
0735:
0736:            /**
0737:             * Gets the key that identifies this item in the PIM database
0738:             * @return an Object used to index this item
0739:             */
0740:            Object getKey() {
0741:                return key;
0742:            }
0743:
0744:            /**
0745:             * Removed this PIMItem from its list
0746:             */
0747:            void remove() throws PIMException {
0748:                if (pimList == null) {
0749:                    throw new PIMException("Item is not in a list");
0750:                }
0751:                pimList.checkWritePermission();
0752:                pimList.commit(key, null, null);
0753:                setKey(null);
0754:                pimList = null;
0755:            }
0756:
0757:            /**
0758:             * Sets default values for this item.
0759:             */
0760:            protected void setDefaultValues() {
0761:                int[] supportedFields = pimList.getSupportedFields();
0762:                for (int i = 0; i < supportedFields.length; i++) {
0763:                    int field = supportedFields[i];
0764:                    PIMField pimField = getField(field, false, true);
0765:                    if ((pimField == null || pimField.getValueCount() == 0)
0766:                            && pimHandler.hasDefaultValue(pimListHandle, field)) {
0767:
0768:                        Object value = null;
0769:                        switch (pimList.getFieldDataType(field)) {
0770:                        case PIMItem.BOOLEAN:
0771:                            value = new Boolean(pimHandler
0772:                                    .getDefaultBooleanValue(pimListHandle,
0773:                                            field));
0774:                            break;
0775:                        case PIMItem.BINARY:
0776:                            value = pimHandler.getDefaultBinaryValue(
0777:                                    pimListHandle, field);
0778:                            break;
0779:                        case PIMItem.DATE:
0780:                            value = new Long(pimHandler.getDefaultDateValue(
0781:                                    pimListHandle, field));
0782:                            break;
0783:                        case PIMItem.INT:
0784:                            value = new Integer(pimHandler.getDefaultIntValue(
0785:                                    pimListHandle, field));
0786:                            break;
0787:                        case PIMItem.STRING:
0788:                            value = pimHandler.getDefaultStringValue(
0789:                                    pimListHandle, field);
0790:                            break;
0791:                        case PIMItem.STRING_ARRAY:
0792:                            value = pimHandler.getDefaultStringArrayValue(
0793:                                    pimListHandle, field);
0794:                            break;
0795:                        default:
0796:                            continue;
0797:                        }
0798:                        addValue(field, PIMItem.ATTR_NONE, value, false);
0799:                    }
0800:                }
0801:            }
0802:
0803:            /**
0804:             * Checks for valid PIM field.
0805:             * @param type list type
0806:             * @param field identifier for field
0807:             * @return <code>true</code> if field is valid
0808:             */
0809:            static boolean isValidPIMField(int type, int field) {
0810:                switch (type) {
0811:                case PIM.CONTACT_LIST:
0812:                    return ContactImpl.isValidPIMField(field);
0813:                case PIM.EVENT_LIST:
0814:                    return EventImpl.isValidPIMField(field);
0815:                case PIM.TODO_LIST:
0816:                    return ToDoImpl.isValidPIMField(field);
0817:                default:
0818:                    return false;
0819:                }
0820:            }
0821:
0822:            /**
0823:             * Checks the type of a field, throwing an IllegalArgumentException
0824:             * if given or if the field number is invalid.
0825:             * @param field identifier for field
0826:             * @param value data to be checked
0827:             * @throws IllegalArgumentException if data type is not known
0828:             */
0829:            private void checkType(int field, Object value) {
0830:                try {
0831:                    int dataType = pimHandler.getFieldDataType(pimListHandle,
0832:                            field);
0833:                    switch (dataType) {
0834:                    case PIMItem.BINARY: {
0835:                        byte[] b = (byte[]) value;
0836:                        break;
0837:                    }
0838:                    case PIMItem.BOOLEAN: {
0839:                        Boolean b = (Boolean) value;
0840:                        break;
0841:                    }
0842:                    case PIMItem.DATE: {
0843:                        Long l = (Long) value;
0844:                        break;
0845:                    }
0846:                    case PIMItem.INT: {
0847:                        Integer i = (Integer) value;
0848:                        break;
0849:                    }
0850:                    case PIMItem.STRING: {
0851:                        String s = (String) value;
0852:                        break;
0853:                    }
0854:                    case PIMItem.STRING_ARRAY: {
0855:                        String[] s = (String[]) value;
0856:                        break;
0857:                    }
0858:                    default:
0859:                        throw complaintAboutField(listType, field);
0860:                    }
0861:                } catch (ClassCastException cce) {
0862:                    throw new IllegalArgumentException(cce.getMessage());
0863:                }
0864:            }
0865:
0866:            /**
0867:             * Checks the type of a field, throwing an IllegalArgumentException
0868:             * if given or if the field number is invalid.
0869:             * @param field identifier of field
0870:             * @param dataType data type for field value
0871:             */
0872:            private void checkType(int field, int dataType) {
0873:                int correctDataType = pimHandler.getFieldDataType(
0874:                        pimListHandle, field);
0875:                if (dataType != correctDataType && correctDataType != -1) {
0876:                    throw new IllegalArgumentException("Wrong data type");
0877:                }
0878:                if (correctDataType == -1) {
0879:                    throw complaintAboutField(listType, field);
0880:                }
0881:            }
0882:
0883:            /**
0884:             * Throw an exception based on field failure type.
0885:             * @param type list type
0886:             * @param field identifier of field
0887:             * @return UnsupportedFieldException if the field value is not supported
0888:             * in the field or IllegalArgumentException, if the field is not valid
0889:             */
0890:            static RuntimeException complaintAboutField(int type, int field) {
0891:                if (isValidPIMField(type, field)) {
0892:                    return new UnsupportedFieldException(String.valueOf(field));
0893:                } else {
0894:                    return new IllegalArgumentException("Invalid field "
0895:                            + field);
0896:                }
0897:            }
0898:
0899:            /**
0900:             * Returns the index of the given key, if it is present in
0901:             * fieldKeys[]. If it is not present, returns the binary
0902:             *  complement of the index before which
0903:             * the key could be inserted. O(log fieldKeys.length) in time.
0904:             * @param key property key for requested field
0905:             * @return the index of the field key
0906:             */
0907:            private int findFieldKey(int key) {
0908:                int lowerBound = 0;
0909:                int upperBound = fieldKeys.length;
0910:                while (lowerBound != upperBound) {
0911:                    int index = lowerBound + (upperBound - lowerBound) / 2;
0912:                    int indexKey = fieldKeys[index];
0913:                    if (indexKey > key) {
0914:                        if (index == upperBound) {
0915:                            upperBound--;
0916:                        } else {
0917:                            upperBound = index;
0918:                        }
0919:                    } else if (indexKey == key) {
0920:                        return index;
0921:                    } else {
0922:                        if (index == lowerBound) {
0923:                            lowerBound++;
0924:                        } else {
0925:                            lowerBound = index;
0926:                        }
0927:                    }
0928:                }
0929:                return ~lowerBound;
0930:            }
0931:
0932:            /**
0933:             * Stores a PIMField. O(fieldKeys.length) in space and time.
0934:             * @param key property key for requested field
0935:             * @param field identifier of field
0936:             */
0937:            public void putField(int key, PIMField field) {
0938:                int index = findFieldKey(key);
0939:                if (index >= 0) {
0940:                    fieldValues[index] = field;
0941:                } else {
0942:                    index = ~index;
0943:                    int[] newKeys = new int[fieldKeys.length + 1];
0944:                    PIMField[] newFields = new PIMField[fieldValues.length + 1];
0945:                    System.arraycopy(fieldKeys, 0, newKeys, 0, index);
0946:                    System.arraycopy(fieldValues, 0, newFields, 0, index);
0947:                    newKeys[index] = key;
0948:                    newFields[index] = field;
0949:                    System.arraycopy(fieldKeys, index, newKeys, index + 1,
0950:                            fieldKeys.length - index);
0951:                    System.arraycopy(fieldValues, index, newFields, index + 1,
0952:                            fieldKeys.length - index);
0953:                    this .fieldKeys = newKeys;
0954:                    this .fieldValues = newFields;
0955:                }
0956:            }
0957:
0958:            /**
0959:             * Looks up a PIMField. O(log fieldKeys.length) in time.
0960:             * @param key property key for requested field
0961:             * @return PIM field requested
0962:             */
0963:            public PIMField getField(int key) {
0964:                int index = findFieldKey(key);
0965:                if (index >= 0) {
0966:                    return fieldValues[index];
0967:                } else {
0968:                    return null;
0969:                }
0970:            }
0971:
0972:            /**
0973:             * Removes a PIMField. O(fieldKeys.length) in space and time.
0974:             * @param key property key for requested field
0975:             */
0976:            public void removeField(int key) {
0977:                int index = findFieldKey(key);
0978:                if (index >= 0) {
0979:                    int[] newKeys = new int[fieldKeys.length - 1];
0980:                    PIMField[] newFields = new PIMField[fieldValues.length - 1];
0981:                    System.arraycopy(fieldKeys, 0, newKeys, 0, index);
0982:                    System.arraycopy(fieldValues, 0, newFields, 0, index);
0983:                    System.arraycopy(fieldKeys, index + 1, newKeys, index,
0984:                            newKeys.length - index);
0985:                    System.arraycopy(fieldValues, index + 1, newFields, index,
0986:                            newKeys.length - index);
0987:                    this .fieldKeys = newKeys;
0988:                    this .fieldValues = newFields;
0989:                }
0990:            }
0991:
0992:            /**
0993:             * Checks the read only fields.
0994:             * @param field identifier of the field
0995:             * @throws IllegalArgumentException if field is not read only
0996:             */
0997:            private void checkReadOnlyFields(int field) {
0998:                if (key != null) {
0999:                    if (field == getRevisionField()) {
1000:                        throw new IllegalArgumentException(
1001:                                "REVISION field is read only"
1002:                                        + " except on newly created PIMItems");
1003:                    } else if (field == getUIDField()) {
1004:                        throw new IllegalArgumentException(
1005:                                "UID field is read only except on newly created PIMItems");
1006:                    }
1007:                }
1008:            }
1009:
1010:            /**
1011:             * Update the revision time.
1012:             */
1013:            private void updateRevision() {
1014:                Long value = new Long(System.currentTimeMillis());
1015:                int field = getRevisionField();
1016:                if (countValues(field) == 0) {
1017:                    addValue(field, 0, value, true);
1018:                } else {
1019:                    setValue(field, 0, 0, value, true);
1020:                }
1021:            }
1022:
1023:            /**
1024:             * Update the UID field.
1025:             */
1026:            private void updateUID() {
1027:                String value = key.toString();
1028:                int field = getUIDField();
1029:                if (countValues(field) == 0) {
1030:                    addValue(field, 0, value, true);
1031:                } // don't change UID value, it can be set by user
1032:            }
1033:
1034:            /**
1035:             * Gets the field that corresponds to the REVISION of this PIMItem.
1036:             *
1037:             * REVISION fields have special handling; they are set automatically
1038:             * on commit and import, and are read only to the application once
1039:             * the item has been committed.
1040:             * @return revision field
1041:             */
1042:            protected abstract int getRevisionField();
1043:
1044:            /**
1045:             * Gets the field that corresponds to the UID of this PIMItem.
1046:             *
1047:             * UIDfields have special handling; they are set automatically
1048:             * on commit and import.
1049:             * @return UID field
1050:             */
1051:            protected abstract int getUIDField();
1052:
1053:            /**
1054:             * Format the data for output.
1055:             * @return formatted data
1056:             */
1057:            protected String formatData() {
1058:                StringBuffer sb = new StringBuffer();
1059:                for (int i = 0; i < fieldValues.length; i++) {
1060:                    if (fieldValues[i].getValueCount() != 0) {
1061:                        PIMField pimField = fieldValues[i];
1062:                        int field = fieldKeys[i];
1063:                        int valueCount = pimField.getValueCount();
1064:                        if (valueCount == 0) {
1065:                            continue;
1066:                        }
1067:                        if (i != 0) {
1068:                            sb.append(", ");
1069:                        }
1070:                        String label = pimHandler.getFieldLabel(pimListHandle,
1071:                                field);
1072:                        int dataType = pimHandler.getFieldDataType(
1073:                                pimListHandle, field);
1074:                        for (int j = 0; j < valueCount; j++) {
1075:                            sb.append(label);
1076:                            if (valueCount != 1) {
1077:                                sb.append("[");
1078:                                sb.append(j);
1079:                                sb.append("]");
1080:                            }
1081:                            sb.append("=");
1082:                            Object value = pimField.getValue(j);
1083:                            if (value == null) {
1084:                                sb.append("null");
1085:                                continue;
1086:                            }
1087:                            switch (dataType) {
1088:                            case STRING_ARRAY: {
1089:                                String[] aValue = (String[]) value;
1090:                                sb.append("[");
1091:                                for (int k = 0; k < aValue.length; k++) {
1092:                                    if (k != 0) {
1093:                                        sb.append(",");
1094:                                    }
1095:                                    sb.append(aValue[k]);
1096:                                }
1097:                                sb.append("]");
1098:                                break;
1099:                            }
1100:                            case BINARY: {
1101:                                byte[] bValue = (byte[]) value;
1102:                                sb.append("<" + bValue.length + " bytes>");
1103:                                break;
1104:                            }
1105:                            case DATE: {
1106:                                long dValue = ((Long) value).longValue();
1107:                                sb.append(pimHandler.composeDateTime(dValue));
1108:                                break;
1109:                            }
1110:                            default:
1111:                                sb.append(value);
1112:                            }
1113:                        }
1114:                    }
1115:                }
1116:                if (categories != null && categories.length != 0) {
1117:                    if (sb.length() > 0) {
1118:                        sb.append(", ");
1119:                    }
1120:                    sb.append("Categories=[");
1121:                    for (int i = 0; i < categories.length; i++) {
1122:                        if (i > 0) {
1123:                            sb.append(",");
1124:                        }
1125:                        sb.append(categories[i]);
1126:                    }
1127:                    sb.append("]");
1128:                }
1129:                return sb.toString();
1130:            }
1131:
1132:            /**
1133:             * Converts the record to a printable format.
1134:             * @return formatted record
1135:             */
1136:            protected abstract String toDisplayableString();
1137:
1138:            /**
1139:             * Convert the data to a String.
1140:             * @return formatted data
1141:             */
1142:            public String toString() {
1143:                return "true".equals(System.getProperty("pim.debug")) ? toDisplayableString()
1144:                        : super .toString();
1145:            }
1146:
1147:            /**
1148:             * Ensures valid class identifier.
1149:             * @param value class identifier to validate
1150:             * @throws IllegalArgumentException if value is not supported
1151:             */
1152:            private void validateClass(int value) {
1153:                switch (value) {
1154:                case javax.microedition.pim.Contact.CLASS_CONFIDENTIAL:
1155:                case Contact.CLASS_PRIVATE:
1156:                case Contact.CLASS_PUBLIC:
1157:                    return;
1158:                default:
1159:                    throw new IllegalArgumentException("Invalid CLASS value: "
1160:                            + value);
1161:                }
1162:            }
1163:
1164:            /**
1165:             * Ensures valid priority identifier.
1166:             * @param value priority identifier to validate
1167:             * @throws IllegalArgumentException if value is not supported
1168:             */
1169:            private void validatePriority(int value) {
1170:                if (value < 0 || value > 9) {
1171:                    throw new IllegalArgumentException(
1172:                            "Invalid PRIORITY value: " + value);
1173:                }
1174:            }
1175:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.