ChoiceList.java

/**
 * Copyright (c) 2012 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation.
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners.
 * See LICENSE.TXT for license information.
 */

package com.nokia.example.contenthandler.texthandler;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Vector;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;

/**
 * Class provides basic methods to add/delete items from the list and give the
 * item URL.
 */
public class ChoiceList extends Form implements CommandListener,
        ItemCommandListener {

    // Message saying.. fail to load text invocation.
    private static final String MSG_FAILED_TO_LOAD_TEXT = "Failed to load text";
    // Message saying.. Invalid file
    private static final String MSG_INVALID_FILE = "Invalid file";
    // URL Choice from JAD
    private static final String JAD_NOKIA_CHOICE = "Nok-Choice-";
    // Resource file name from JAD
    private static final String JAD_NOKIA_RESOURCE_FILE = "Nok-Resource-File-Name";
    // New line separator
    private static final String NEW_LINE = "\n";
    // Key value separator for link.txt file.
    private static final String SEPARATOR = "~";
    // Display instance.
    private Display display = null;
    // List of choices
    private Vector choiceList = new Vector();
    // Alert to display choice details
    Alert alert = new Alert("Choice Details");
    // TextField to enter Title of the choice
    private TextField titleTextField;
    // TextField to enter choice URL.
    private TextField urlTextField;
    // Command to execute the choice
    private Command fireCommand = new Command("Execute", Command.OK, 1);
    // Command to add item to the list.
    private Command addCommand = new Command("Add", Command.ITEM, 2);
    // Command to Delete Choice from the list.
    private Command deleteCommand = new Command("Delete", Command.ITEM, 3);
    // Command to view details of the choice
    private Command detailCommand = new Command("Details", Command.ITEM, 4);
    // Command to save item to the list.
    private Command saveCommand = new Command("Save", Command.OK, 1);
    // Command to exit from the application
    private Command exitCommand = new Command("Exit", Command.EXIT, 5);
    // Command to exit from the application
    private Command backCommand = new Command("Back", Command.BACK, 6);
    // The ItemCommandListener that gets notified of select events.
    private TextHandler textHandler;
    // Commands for displayMessage method
    Command yes = new Command("Yes", Command.OK, 1);
    Command no = new Command("No", Command.BACK, 2);

    /**
     * Constructor to handle list of Choices
     *
     * @param title Choice list title.
     * @param _textHandler Instance of TextHandler class to handle UI part.
     */
    public ChoiceList(String title, TextHandler _textHandler) {
        super(title);

        textHandler = _textHandler;
        display = _textHandler.display;

        // Read favourites links form the resource file
        String strChoices = null;

        try {
            strChoices = readResourceFile();
        }
        catch (IOException ex) {
            choiceList.removeAllElements();
            choiceList.addElement(ChoiceList.MSG_INVALID_FILE);
        }

        try {
            generateChoiceList(strChoices);
        }
        catch (Exception e) {
            // Failed to load resources
            choiceList.removeAllElements();
            choiceList.addElement(ChoiceList.MSG_FAILED_TO_LOAD_TEXT);
        }

        displayChoices();

        configureTextFields();
        
    }

    /**
     * TextField configuration
     */
    private void configureTextFields() {
        titleTextField = new TextField("Add Title:", "", 30,
                TextField.INITIAL_CAPS_WORD);
        titleTextField.setLayout(Item.LAYOUT_DEFAULT
                | Item.LAYOUT_NEWLINE_AFTER);
        //titleTextField.addCommand(saveCommand);
        titleTextField.setItemCommandListener(this);
        urlTextField = new TextField("Add Link:", "http://", 128, TextField.URL);
        urlTextField.setLayout(Item.LAYOUT_DEFAULT | Item.LAYOUT_NEWLINE_AFTER);
        //urlTextField.addCommand(saveCommand);
        urlTextField.setItemCommandListener(this);

    }

    /**
     * Display favourite choice list
     */
    private void displayChoices() {

        for (int index = 0; index < choiceList.size(); index++) {

            ChoiceBean choiceBean = (ChoiceBean) choiceList.elementAt(index);
            this.append(choiceBean.getKeyTitle());
        }

        removeCommand(saveCommand);
        removeCommand(backCommand);
        addCommand(addCommand);
        addCommand(exitCommand);
        setCommandListener(this);
    }
    
    /**
     * Display add form for a custom link
     */
    private void displayAddForm() {
        // Reset strings
        titleTextField.setString("");
        urlTextField.setString("http://");

        // Add text fields to add new choice
        insert(0, titleTextField);
        insert(1, urlTextField);
        
        removeCommand(addCommand);
        removeCommand(exitCommand);
        addCommand(saveCommand);
        addCommand(backCommand);
        setCommandListener(this);
    }

    /**
     * Create choice list based resource string. Method reads choices from two
     * files.
     */
    private void generateChoiceList(String strChoices) {
        strChoices.replace('\r', '*');
        try {

            while ((strChoices != null)
                    && (strChoices.indexOf(ChoiceList.NEW_LINE) != -1)) {

                String item = strChoices.substring(0, strChoices.indexOf(ChoiceList.NEW_LINE) - 1);

                String key = item.substring(0, item.indexOf(ChoiceList.SEPARATOR));
                String value = item.substring(item.indexOf(ChoiceList.SEPARATOR) + 1);

                if (!"//".equals(key.substring(0, 2))) {
                    StringItem choice = new StringItem(null, key, Item.HYPERLINK);
                    choice.setLayout(Item.LAYOUT_2 | Item.LAYOUT_NEWLINE_AFTER);
                    choice.setDefaultCommand(fireCommand);
                    //choice.addCommand(backCommand);
                    //choice.addCommand(addCommand);
                    choice.addCommand(deleteCommand);
                    choice.addCommand(detailCommand);
                    choice.setItemCommandListener(this);

                    ChoiceBean choiceBean = new ChoiceBean(choice, value);
                    choiceList.addElement(choiceBean);
                }

                strChoices = strChoices.substring(strChoices.indexOf(ChoiceList.NEW_LINE) + 1);
            }
        }
        catch (Exception e) {
            //e.printStackTrace();
        }

        // Read from jad file, if entry exists
        int keyNum = 1;
        strChoices = null;
        do {
            strChoices = textHandler.getAppProperty(ChoiceList.JAD_NOKIA_CHOICE
                    + keyNum++);

            if (strChoices == null) {
                return;
            }

            String key;
            String value;
            if (strChoices.indexOf(ChoiceList.SEPARATOR) != -1) {
                key = strChoices.substring(0, strChoices.indexOf(ChoiceList.SEPARATOR));
                value = strChoices.substring(strChoices.indexOf(ChoiceList.SEPARATOR) + 1);

                if (value != null) {
                    StringItem choice = new StringItem(null, key,
                            Item.HYPERLINK);
                    choice.setLayout(Item.LAYOUT_2 | Item.LAYOUT_NEWLINE_AFTER);
                    choice.setDefaultCommand(fireCommand);
                    //choice.addCommand(addCommand);
                    choice.addCommand(deleteCommand);
                    choice.addCommand(detailCommand);
                    choice.setItemCommandListener(this);

                    ChoiceBean choiceBean = new ChoiceBean(choice, value);
                    choiceList.addElement(choiceBean);

                }

            }

        }
        while (strChoices != null);
    }

    /**
     * Read data from the resource file and generate String.
     *
     * @return string generated after reading the data from the resource file
     * @throws IOException
     */
    private String readResourceFile() throws IOException {
        InputStream is = getClass().getResourceAsStream(
                textHandler.getAppProperty(JAD_NOKIA_RESOURCE_FILE));

        InputStreamReader r = new InputStreamReader(is);

        char[] buffer = new char[32];
        StringBuffer sb = new StringBuffer();
        int count;

        while ((count = r.read(buffer, 0, buffer.length)) > -1) {
            sb.append(buffer, 0, count);
        }
        return sb.toString();
    }

    /**
     * Add Choice to the current list.
     *
     * @param keyTitle title of the new choice
     * @param choiceName URL of the given choice
     */
    public void addChoice(String keyTitle, String choiceName) {

        StringItem choice = new StringItem(null, keyTitle + "\n", Item.HYPERLINK);
        choice.setLayout(Item.LAYOUT_2 | Item.LAYOUT_NEWLINE_AFTER);
        choice.setDefaultCommand(fireCommand);
        //choice.addCommand(addCommand);
        //choice.addCommand(addCommand);
        choice.addCommand(deleteCommand);
        choice.addCommand(detailCommand);
        choice.setItemCommandListener(this);

        ChoiceBean choiceBean = new ChoiceBean(choice, choiceName);
        choiceList.addElement(choiceBean);

    }

    /**
     * Delete choice from the current list
     *
     * @param index delete choice based on the given index.
     */
    public void deleteChoice(int index) {
        choiceList.removeElementAt(index);
    }

    /**
     * Displays alarm message to the user
     * @param msg String to be displayed
     */
    void displayMessage(String msg) {
        Form form = new Form("Text Viewer");
        form.append(msg);
        form.addCommand(yes);
        form.addCommand(no);
        form.setCommandListener(this);
        display.setCurrent(form);
    }

    /**
     * Cleans everything away from the screen
     */
    private void removeItems() {
        while (this.size() > 0) {
            this.delete(0);
        }
    }

    /**
     * Handles form specific commands
     */
    public void commandAction(Command command, Displayable disp) {
        if (command == exitCommand) {
            textHandler.destroyApp(true);
            textHandler.notifyDestroyed();
        }
        else if (command == backCommand) {
            removeItems();
            displayChoices();
        }
        else if (command == addCommand) {
            removeItems();
            displayAddForm();
        }
        else if (command == saveCommand) {
            addChoice(titleTextField.getString().trim(), urlTextField.getString().trim());
            removeItems();
            displayChoices();
        }
    }
    
    /**
     * Handles item specific command
     */
    public void commandAction(Command command, Item item) {
        int itemIndex = getItemIndex(item);
        if (command == fireCommand) {

            if (textHandler != null) {

                String url = textHandler.choices.getURL(item);

                if (url == null) {
                    url = ((StringItem) item).getText();
                }
                System.out.println("URL|" + url + "|");
                textHandler.doInvoke(url);
            }
        }
        else if (command == deleteCommand) {

            this.delete(itemIndex);
            choiceList.removeElementAt(itemIndex);

        }
        else if (command == detailCommand) {

            alert.setString(((ChoiceBean) choiceList.elementAt(itemIndex)).getChoiceName());
            alert.setTimeout(Alert.FOREVER);
            alert.setType(AlertType.INFO);
            display.setCurrent(alert);

        }
    }

    /**
     * Find the index of the item in the form.
     *
     * @param item to find the index of
     * @return the index of the item or -1 if not found.
     */
    private int getItemIndex(Item item) {
        
        for (int itemIndex = 0; itemIndex < this.size(); itemIndex++) {
            if (this.get(itemIndex) == item) {
                return itemIndex;
            }
        }

        return -1;
    }

    /**
     * Get the url associated with the item.
     *
     * @param item for which to get the URL
     * @return the URL at index
     */
    public String getURL(Item item) {
        int index = getItemIndex(item);

        return (index < 0) ? null : ((ChoiceBean) choiceList.elementAt(index)).getChoiceName();
    }
}