001: /*
002: *
003: * Copyright (c) 2007, Sun Microsystems, Inc.
004: *
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * * Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * * Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * * Neither the name of Sun Microsystems nor the names of its contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032: package example.pim;
033:
034: import java.io.ByteArrayOutputStream;
035:
036: import java.util.Date;
037: import java.util.Enumeration;
038: import java.util.Hashtable;
039: import java.util.Vector;
040:
041: import javax.microedition.lcdui.Alert;
042: import javax.microedition.lcdui.AlertType;
043: import javax.microedition.lcdui.Command;
044: import javax.microedition.lcdui.CommandListener;
045: import javax.microedition.lcdui.DateField;
046: import javax.microedition.lcdui.Display;
047: import javax.microedition.lcdui.Displayable;
048: import javax.microedition.lcdui.Form;
049: import javax.microedition.lcdui.Item;
050: import javax.microedition.lcdui.ItemCommandListener;
051: import javax.microedition.lcdui.List;
052: import javax.microedition.lcdui.StringItem;
053: import javax.microedition.lcdui.TextField;
054: import javax.microedition.pim.Contact;
055: import javax.microedition.pim.Event;
056: import javax.microedition.pim.PIM;
057: import javax.microedition.pim.PIMException;
058: import javax.microedition.pim.PIMItem;
059: import javax.microedition.pim.ToDo;
060:
061: /**
062: * Demonstrate the use of JSR 75 PIM APIs
063: */
064: public class ItemDisplayScreen extends Form implements CommandListener,
065: ItemCommandListener {
066: private final Command editArrayCommand = new Command("Edit",
067: Command.OK, 1);
068: private final Command editBooleanCommand = new Command("Edit",
069: Command.OK, 1);
070: private final Command commitCommand = new Command("Commit",
071: Command.OK, 2);
072: private final Command backCommand = new Command("Back",
073: Command.BACK, 1);
074: private final Command showVCard = new Command("Show vCard",
075: Command.SCREEN, 5);
076: private final Command showVCalendar = new Command("Show vCalendar",
077: Command.SCREEN, 5);
078: private final Command addField = new Command("Add Field",
079: Command.SCREEN, 2);
080: private final Command removeField = new Command("Remove Field",
081: Command.SCREEN, 3);
082: private final PIMDemo midlet;
083: private final ItemSelectionScreen caller;
084: private final PIMItem item;
085: private final Hashtable fieldTable = new Hashtable(); // maps field indices to items
086:
087: public ItemDisplayScreen(PIMDemo midlet,
088: ItemSelectionScreen caller, PIMItem item)
089: throws PIMException {
090: super ("PIM Item");
091: this .midlet = midlet;
092: this .caller = caller;
093: this .item = item;
094:
095: populateForm();
096:
097: addCommand(backCommand);
098: addCommand(commitCommand);
099: setCommandListener(this );
100: }
101:
102: private boolean isClassField(int field) {
103: return (item instanceof Contact && (field == Contact.CLASS))
104: || (item instanceof Event && (field == Event.CLASS))
105: || (item instanceof ToDo && (field == ToDo.CLASS));
106: }
107:
108: private void populateForm() throws PIMException {
109: deleteAll();
110: fieldTable.clear();
111:
112: int[] fields = item.getPIMList().getSupportedFields();
113: boolean allFieldsUsed = true;
114:
115: for (int i = 0; i < fields.length; i++) {
116: int field = fields[i];
117:
118: // exclude CLASS field
119: if (isClassField(field)) {
120: continue;
121: }
122:
123: if (item.countValues(field) == 0) {
124: allFieldsUsed = false;
125:
126: continue;
127: }
128:
129: int dataType = item.getPIMList().getFieldDataType(field);
130: String label = item.getPIMList().getFieldLabel(field);
131: Item formItem = null;
132:
133: switch (dataType) {
134: case PIMItem.STRING: {
135: String sValue = item.getString(field, 0);
136:
137: if (sValue == null) {
138: sValue = "";
139: }
140:
141: int style = TextField.ANY;
142:
143: // cater for specific field styles
144: if (item instanceof Contact) {
145: switch (field) {
146: case Contact.EMAIL:
147: style = TextField.EMAILADDR;
148:
149: break;
150:
151: case Contact.TEL:
152: style = TextField.PHONENUMBER;
153:
154: break;
155:
156: case Contact.URL:
157: style = TextField.URL;
158:
159: break;
160: }
161: }
162:
163: try {
164: formItem = new TextField(label, sValue, 128, style);
165: } catch (IllegalArgumentException e) {
166: formItem = new TextField(label, sValue, 128,
167: TextField.ANY);
168: }
169:
170: break;
171: }
172:
173: case PIMItem.BOOLEAN: {
174: formItem = new StringItem(label, item.getBoolean(field,
175: 0) ? "yes" : "no");
176: formItem.setDefaultCommand(editBooleanCommand);
177:
178: break;
179: }
180:
181: case PIMItem.STRING_ARRAY: {
182: String[] a = item.getStringArray(field, 0);
183:
184: if (a != null) {
185: formItem = new StringItem(label, joinStringArray(a));
186: formItem.setDefaultCommand(editArrayCommand);
187: }
188:
189: break;
190: }
191:
192: case PIMItem.DATE: {
193: long time = item.getDate(field, 0);
194: int style = DateField.DATE_TIME;
195:
196: // some fields are date only, without a time.
197: // correct for these fields:
198: if (item instanceof Contact) {
199: switch (field) {
200: case Contact.BIRTHDAY:
201: style = DateField.DATE;
202:
203: break;
204: }
205: }
206:
207: formItem = new DateField(label, style);
208: ((DateField) formItem).setDate(new Date(time));
209:
210: break;
211: }
212:
213: case PIMItem.INT: {
214: formItem = new TextField(label, String.valueOf(item
215: .getInt(field, 0)), 64, TextField.DECIMAL);
216:
217: break;
218: }
219:
220: case PIMItem.BINARY: {
221: byte[] data = item.getBinary(field, 0);
222:
223: if (data != null) {
224: formItem = new StringItem(label, data.length
225: + " bytes");
226: }
227:
228: break;
229: }
230: }
231:
232: if (formItem != null) {
233: append(formItem);
234: fieldTable.put(formItem, new Integer(field));
235: formItem.addCommand(removeField);
236: formItem.setItemCommandListener(this );
237: }
238: }
239:
240: if (item instanceof Contact) {
241: addCommand(showVCard);
242: } else {
243: addCommand(showVCalendar);
244: }
245:
246: if (!allFieldsUsed) {
247: addCommand(addField);
248: } else {
249: removeCommand(addField);
250: }
251: }
252:
253: public void commandAction(final Command command,
254: Displayable displayable) {
255: if (command == backCommand) {
256: new Thread(new Runnable() {
257: public void run() {
258: try {
259: getUserData();
260: } catch (Exception e) {
261: // ignore; store what can be stored of the data
262: }
263:
264: try {
265: caller.populateList();
266: } catch (Exception e) {
267: // ignore again; show what can be shown of the list
268: }
269:
270: Display.getDisplay(midlet).setCurrent(caller);
271: }
272: }).start();
273: } else if (command == commitCommand) {
274: commit();
275: } else if (command == showVCard) {
276: showItem("VCARD/2.1");
277: } else if (command == showVCalendar) {
278: showItem("VCALENDAR/1.0");
279: } else if (command == addField) {
280: addField();
281: }
282: }
283:
284: public void commandAction(final Command command, final Item formItem) {
285: new Thread(new Runnable() {
286: public void run() {
287: final int field = ((Integer) fieldTable.get(formItem))
288: .intValue();
289:
290: if (command == editBooleanCommand) {
291: boolean newValue = !item.getBoolean(field, 0);
292: item.setBoolean(field, 0, PIMItem.ATTR_NONE,
293: newValue);
294: ((StringItem) formItem).setText(newValue ? "yes"
295: : "no");
296: } else if (command == editArrayCommand) {
297: String label = item.getPIMList().getFieldLabel(
298: field);
299: final String[] a = item.getStringArray(field, 0);
300: final TextField[] textFields = new TextField[a.length];
301:
302: for (int i = 0; i < a.length; i++) {
303: String elementLabel = item.getPIMList()
304: .getArrayElementLabel(field, i);
305: textFields[i] = new TextField(elementLabel,
306: a[i], 128, TextField.ANY);
307: }
308:
309: Form form = new Form(label, textFields);
310: final Command okCommand = new Command("OK",
311: Command.OK, 1);
312: final Command cancelCommand = new Command("Cancel",
313: Command.CANCEL, 1);
314: form.addCommand(okCommand);
315: form.addCommand(cancelCommand);
316: form.setCommandListener(new CommandListener() {
317: public void commandAction(Command command,
318: Displayable d) {
319: if (command == okCommand) {
320: for (int i = 0; i < textFields.length; i++) {
321: a[i] = textFields[i].getString();
322: }
323:
324: item.setStringArray(field, 0, item
325: .getAttributes(field, 0), a);
326: ((StringItem) formItem)
327: .setText(joinStringArray(a));
328: }
329:
330: Display.getDisplay(midlet).setCurrent(
331: ItemDisplayScreen.this );
332: }
333: });
334: Display.getDisplay(midlet).setCurrent(form);
335: } else if (command == removeField) {
336: try {
337: item.removeValue(field, 0);
338: } catch (IllegalArgumentException iae) {
339: System.out.println(iae.toString());
340: }
341:
342: try {
343: populateForm();
344: } catch (PIMException e) {
345: }
346:
347: /*
348: for (int i = size() - 1; i >=0; i--) {
349: if (get(i) == formItem) {
350: delete(i);
351: break;
352: }
353: }*/
354: }
355: }
356: }).start();
357: }
358:
359: private void commit() {
360: new Thread(new Runnable() {
361: public void run() {
362: try {
363: getUserData();
364: item.commit();
365: populateForm();
366: } catch (Exception e) {
367: midlet.reportException(e, ItemDisplayScreen.this );
368: }
369: }
370: }).start();
371: }
372:
373: private void getUserData() throws NumberFormatException {
374: int itemCount = size();
375:
376: for (int i = 0; i < itemCount; i++) {
377: Item formItem = get(i);
378: int field = ((Integer) fieldTable.get(formItem)).intValue();
379:
380: if (item.countValues(field) < 1) {
381: // No data in field. This can happen if, for example, a
382: // value is adding to PUBLIC_KEY, causing values of
383: // PUBLIC_KEY_STRING to be erased.
384: continue;
385: }
386:
387: int dataType = item.getPIMList().getFieldDataType(field);
388:
389: switch (dataType) {
390: case PIMItem.STRING: {
391: String s = ((TextField) formItem).getString();
392:
393: try {
394: item.setString(field, 0, PIMItem.ATTR_NONE, s);
395: } catch (IllegalArgumentException e) {
396: // this was a read-only field (UID)
397: }
398:
399: break;
400: }
401:
402: case PIMItem.DATE: {
403: long time = ((DateField) formItem).getDate().getTime();
404:
405: try {
406: item.setDate(field, 0, PIMItem.ATTR_NONE, time);
407: } catch (IllegalArgumentException e) {
408: // this was a read-only field (REVISION)
409: }
410:
411: break;
412: }
413:
414: case PIMItem.INT: {
415: String s = ((TextField) formItem).getString();
416: int j = Integer.parseInt(s);
417: item.setInt(field, 0, PIMItem.ATTR_NONE, j);
418:
419: break;
420: }
421: }
422: }
423: }
424:
425: private void addField() {
426: int[] allFields = item.getPIMList().getSupportedFields();
427: final Vector unusedFields = new Vector();
428:
429: for (int i = 0; i < allFields.length; i++) {
430: if ((item.countValues(allFields[i]) == 0)
431: && !isClassField(allFields[i])) {
432: unusedFields.addElement(new Integer(allFields[i]));
433: }
434: }
435:
436: final List fieldList = new List("Select a field to add",
437: List.IMPLICIT);
438:
439: for (Enumeration e = unusedFields.elements(); e
440: .hasMoreElements();) {
441: int field = ((Integer) e.nextElement()).intValue();
442: fieldList.append(item.getPIMList().getFieldLabel(field),
443: null);
444: }
445:
446: fieldList.addCommand(new Command("Cancel", Command.CANCEL, 1));
447: fieldList.setSelectCommand(new Command("Add", Command.OK, 1));
448: fieldList.setCommandListener(new CommandListener() {
449: public void commandAction(final Command c, Displayable d) {
450: new Thread(new Runnable() {
451: public void run() {
452: if (c.getCommandType() == Command.OK) {
453: try {
454: int index = fieldList
455: .getSelectedIndex();
456: int field = ((Integer) unusedFields
457: .elementAt(index)).intValue();
458: addField(field);
459: } catch (IllegalArgumentException iae) {
460: midlet.reportException(iae,
461: ItemDisplayScreen.this );
462: }
463:
464: try {
465: getUserData();
466: populateForm();
467: } catch (Exception e) {
468: midlet.reportException(e,
469: ItemDisplayScreen.this );
470: }
471: }
472:
473: Display.getDisplay(midlet).setCurrent(
474: ItemDisplayScreen.this );
475: }
476: }).start();
477: }
478: });
479: Display.getDisplay(midlet).setCurrent(fieldList);
480: }
481:
482: private void addField(int field) {
483: switch (item.getPIMList().getFieldDataType(field)) {
484: case PIMItem.STRING:
485: item.addString(field, PIMItem.ATTR_NONE, "");
486:
487: break;
488:
489: case PIMItem.STRING_ARRAY: {
490: int[] supportedElements = item.getPIMList()
491: .getSupportedArrayElements(field);
492: int arraySize = 0;
493:
494: for (int i = 0; i < supportedElements.length; i++) {
495: arraySize = Math.max(arraySize,
496: supportedElements[i] + 1);
497: }
498:
499: String[] a = new String[arraySize];
500:
501: for (int i = 0; i < a.length; i++) {
502: a[i] = "";
503: }
504:
505: item.addStringArray(field, PIMItem.ATTR_NONE, a);
506:
507: break;
508: }
509:
510: case PIMItem.BINARY:
511: item.addBinary(field, PIMItem.ATTR_NONE, new byte[16], 0,
512: 16);
513:
514: break;
515:
516: case PIMItem.BOOLEAN:
517: item.addBoolean(field, PIMItem.ATTR_NONE, false);
518:
519: break;
520:
521: case PIMItem.DATE:
522: item
523: .addDate(field, PIMItem.ATTR_NONE, new Date()
524: .getTime());
525:
526: break;
527:
528: case PIMItem.INT:
529: item.addInt(field, PIMItem.ATTR_NONE, 0);
530: }
531: }
532:
533: private void showItem(final String format) {
534: new Thread(new Runnable() {
535: public void run() {
536: try {
537: getUserData();
538: populateForm();
539:
540: ByteArrayOutputStream baos = new ByteArrayOutputStream();
541: PIM.getInstance().toSerialFormat(item, baos,
542: "UTF-8", format);
543:
544: String s = new String(baos.toByteArray(), "UTF-8");
545: Alert a = new Alert(format, s, null, AlertType.INFO);
546: a.setTimeout(Alert.FOREVER);
547: Display.getDisplay(midlet).setCurrent(a,
548: ItemDisplayScreen.this );
549: } catch (Exception e) {
550: midlet.reportException(e, ItemDisplayScreen.this );
551: }
552: }
553: }).start();
554: }
555:
556: private String joinStringArray(String[] a) {
557: StringBuffer sb = new StringBuffer();
558:
559: for (int i = 0; i < a.length; i++) {
560: if ((a[i] != null) && (a[i].length() > 0)) {
561: if (sb.length() > 0) {
562: sb.append(", ");
563: }
564:
565: sb.append(a[i]);
566: }
567: }
568:
569: return sb.toString();
570: }
571: }
|