Package widgetpackage

Source Code of widgetpackage.NdefMessageParser

/*
* Copyright 2011-2012 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package widgetpackage;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;

import net.rim.device.api.io.Base64OutputStream;
import net.rim.device.api.io.nfc.ndef.NDEFMessage;
import net.rim.device.api.io.nfc.ndef.NDEFRecord;

import org.json.me.JSONArray;
import org.json.me.JSONException;
import org.json.me.JSONObject;

public class NdefMessageParser implements Runnable {

    private static NdefMessageParser _parser = new NdefMessageParser();
    private static NdefJavaScriptBridge _js_bridge = NdefJavaScriptBridge
            .getInstance();
    private Vector _messages;

    private NdefMessageParser() {
        _messages = new Vector();
    }

    public static NdefMessageParser getInstance(NDEFMessage message) {
        return _parser;
    }

    public void parseAndDeliver(NDEFMessage message) {
        log("parseAndDeliver(NDEFMessage)");
        synchronized (_messages) {
            _messages.addElement(message);
        }
        Thread parser_thread = new Thread(this);
        parser_thread.start();
    }

    protected JSONObject parseMessage(NDEFMessage _message)
            throws JSONException, IOException {
        log("parseMessage(NDEFMessage)");
        String record_type = "?";
        int typeNameFormat = NDEFRecord.TNF_WELL_KNOWN;

        JSONObject result = new JSONObject();
        /*
         * The NDEF Message may consist of a number of NDEF records
         */

        NDEFRecord[] records = _message.getRecords();
        /*
         * This is the number of NDEF records in the NDEF message
         */
        int numRecords = records.length;

        log("Parsing #records=" + numRecords);

        /*
         * Only unpick the message if it contains a non-zero number of records
         */
        JSONArray recordsArray = new JSONArray();
        result.put(Constants.NDEF_RECORDS, recordsArray);

        if (numRecords > 0) {
            /*
             * Work our way through each record in the message in turn
             */
            for (int j = 0; j < numRecords; ++j) {
                log("parseMessage record #" + j);

                NDEFRecord currentRecord = records[j];
                JSONObject jsonRecord = new JSONObject();
                recordsArray.put(jsonRecord);

                log("Processing NDEF record#=" + j);

                typeNameFormat = currentRecord.getTypeNameFormat();
                record_type = records[j].getType();

                if (typeNameFormat == NDEFRecord.TNF_WELL_KNOWN) {
                    if (Constants.NDEF_SMART_POSTER_TYPE.equals(records[j]
                            .getType())) {
                        mergeInto(jsonRecord, parseSmartPoster(records[j]));
                    } else if (Constants.NDEF_TEXT_TYPE.equals(records[j]
                            .getType())) {
                        mergeInto(jsonRecord, parseText(records[j]));
                    } else if (Constants.NDEF_URI_TYPE.equals(records[j]
                            .getType())) {
                        mergeInto(jsonRecord, parseURI(records[j]));
                    } else {
                        // Gc, Hr, Hs, Hc, Sig are not currently parsed by this
                        // implementation...
                    }
                } else if (typeNameFormat == NDEFRecord.TNF_MEDIA) {
                    mergeInto(jsonRecord, parseMediaRecord(records[j]));
                } else if (typeNameFormat == NDEFRecord.TNF_EXTERNAL) {
                    NDEFMessage message = new NDEFMessage(
                            records[j].getPayload());
                    mergeInto(jsonRecord, parseMessage(message));
                }

                if (!jsonRecord.has(Constants.NDEF_PAYLOAD64)) {
                    mergeInto(jsonRecord, parseGenericRecord(records[j]));
                }

                // Put the first record at the top level - to simplify
                // accessing.
                if (j == 0) {
                    mergeInto(result, jsonRecord);
                }
            }
        } else {
            log("No records in message");
            return null;
        }
        return result;
    }

    public void run() {
        NDEFMessage message = null;
        synchronized (_messages) {
            message = (NDEFMessage) _messages.elementAt(_messages.size() - 1);
            _messages.removeElementAt(_messages.size() - 1);
        }

        JSONObject toUse;
        try {
            toUse = parseMessage(message);
            try {
                _js_bridge.useNDEFMessage(
                        toUse.getInt(Constants.NDEF_TYPE_NAME_FORMAT),
                        toUse.getString(Constants.NDEF_TYPE), toUse.toString());
            } catch (JSONException j) {
                log("Could not send object back to event handler", j);
            }
        } catch (Exception e) {
            String record_type = "?";
            int typeNameFormat = NDEFRecord.TNF_WELL_KNOWN;
            try {
                NDEFRecord[] records = message.getRecords();
                if (records.length > 0) {
                    record_type = records[0].getType();
                    typeNameFormat = records[0].getTypeNameFormat();
                }
            } catch (Exception toIgnore) {
                // consume
            }
            _js_bridge.reportError(typeNameFormat, record_type, e.getClass()
                    .getName() + ": " + e.getMessage());
            log("Problem inside run", e);
        }
    }

    private void log(String message) {
        Utilities.log(NdefMessageParser.class.getName() + ": " + message);
    }

    private void log(String message, Throwable t) {
        Utilities.log(NdefMessageParser.class.getName() + ": " + message, t);
    }

    private void mergeInto(JSONObject target, JSONObject source)
            throws JSONException {
        log("mergeInto(JSONObject,JSONObject)");
        Enumeration e = source.keys();
        while (e.hasMoreElements()) {
            String key = String.valueOf(e.nextElement());
            if (!target.has(key)) {
                target.put(key, source.get(key));
            }
        }
    }

    protected JSONObject parseURI(NDEFRecord record) throws JSONException,
            IOException {
        log("parseURL(NDEFRecord)");
        JSONObject toReturn = parseGenericRecord(record);
        byte[] payload = record.getPayload();
        StringBuffer uriBuffer = new StringBuffer();
        uriBuffer.append(URLPrefixes.getPrefix(payload[0] & 0xff));
        uriBuffer.append(new String(payload, 1, payload.length - 1, "UTF-8"));
        toReturn.put(Constants.NDEF_URI, uriBuffer.toString());
        return toReturn;
    }

    protected JSONObject parseGenericRecord(NDEFRecord record)
            throws JSONException, IOException {
        log("parseGenericRecord(NDEFRecord)");
        JSONObject toReturn = new JSONObject();
        toReturn.putOpt(Constants.NDEF_ID, record.getId());
        toReturn.putOpt(Constants.NDEF_TYPE, record.getType());
        toReturn.put(Constants.NDEF_TYPE_NAME_FORMAT,
                record.getTypeNameFormat());

        byte[] payloadBytes = record.getPayload();
        JSONArray bytePayload = new JSONArray();

        for (int i = 0; i < payloadBytes.length; i++) {
            byte b = payloadBytes[i];
            bytePayload.put(b & 0xff);
        }

        toReturn.put("payload", bytePayload);
        return toReturn;
    }

    protected JSONObject parseText(NDEFRecord record) throws JSONException,
            IOException {
        log("parseText(NDEFRecord)");
        byte[] payload = record.getPayload();
        if (payload.length == 0) {
            log("Text record too short to read");
            return null;
        }
        int statusByte = payload[0] & 0xff;

        boolean isUTF16 = Utilities.isUtf16Encoded(statusByte);
        int languageCodeLength = Utilities
                .getIanaLanguageCodeLength(statusByte);

        int textLength = payload.length - 1 - languageCodeLength;

        String languageCode = "";
        if (languageCodeLength > 0) {
            languageCode = new String(payload, 1, languageCodeLength,
                    "US-ASCII");
        }

        String text = "";
        if (textLength > 0) {
            text = new String(payload, 1 + languageCodeLength, textLength,
                    isUTF16 ? "UTF-16" : "UTF-8");
        }

        JSONObject toReturn = parseGenericRecord(record);
        toReturn.putOpt(Constants.NDEF_TEXT_LANGUAGE_CODE, languageCode);
        toReturn.putOpt(Constants.NDEF_TEXT_VALUE, text);
        return toReturn;
    }

    protected JSONObject parseSmartPoster(NDEFRecord record)
            throws JSONException, IOException {
        log("parseSmartPoster(NDEFRecord)");
        JSONObject toReturn = new JSONObject();
        JSONArray recordsArray = new JSONArray();
        toReturn.put("records", recordsArray);
        // testing

        // if (true)
        // throw new JSONException("Fictitious JSON problem");

        // if(true)
        // throw new
        // UnsupportedEncodingException("Fictitious encoding problem");

        // if(true)
        // throw new BadFormatException("Fictitious format problem");

        // if(true)
        // throw new NFCException("Fictitious NFC problem");

        log("Recognised a Smart Poster Message");
        // try {
        NDEFMessage smartPosterMessage = new NDEFMessage(record.getPayload());
        NDEFRecord[] spRecords = smartPosterMessage.getRecords();
        int numSpRecords = spRecords.length;
        log("Parsing smartposter #records=" + numSpRecords);

        if (numSpRecords > 0) {
            log("Parsing Smart Poster Message");
            for (int k = 0; k < numSpRecords; ++k) {
                log("parseSmartPoster record #" + k);
                JSONObject currentRecordJSON = parseGenericRecord(spRecords[k]);
                recordsArray.put(currentRecordJSON);
                log("Parsing SP record#=" + k);
                byte[] spPayloadBytes = spRecords[k].getPayload();

                int tnf = spRecords[k].getTypeNameFormat();
                String type = spRecords[k].getType();

                log("entering parseSmartPoster if");

                if (tnf == NDEFRecord.TNF_WELL_KNOWN) {
                    if (Constants.NDEF_TEXT_TYPE.equals(type)) {
                        log(Constants.NDEF_TEXT_TYPE);
                        JSONObject text = parseText(spRecords[k]);
                        mergeInto(currentRecordJSON, text);
                        if (text != null) {
                            toReturn.putOpt(Constants.NDEF_TEXT,
                                    text.get(Constants.NDEF_TEXT_VALUE));
                            getOrCreateArray(toReturn,
                                    Constants.NDEF_TEXT_VALUES).put(text);
                        }
                    } else if (Constants.NDEF_URI_TYPE.equals(type)) {
                        log(Constants.NDEF_URI_TYPE);
                        JSONObject uri = parseURI(spRecords[k]);
                        mergeInto(currentRecordJSON, uri);
                        toReturn.put(Constants.NDEF_URI,
                                uri.get(Constants.NDEF_URI));
                        toReturn.put(Constants.NDEF_URI_LEGACY,
                                uri.get(Constants.NDEF_URI));
                    } else if (Constants.NDEF_SMART_POSTER_RECOMMENDED_ACTION_TYPE
                            .equals(type)) {
                        log("Reading an action");
                        if (spPayloadBytes.length != 1) {
                            log("Incorrect length noted for 'action' record: "
                                    + spPayloadBytes.length);
                        }
                        if (spPayloadBytes.length > 0) {
                            toReturn.put(
                                    Constants.NDEF_SMART_POSTER_RECOMMENDED_ACTION,
                                    spPayloadBytes[0] & 0xff);
                        }
                    } else if (Constants.NDEF_SMART_POSTER_URI_SIZE_TYPE
                            .equals(type)) {
                        log("Reading size");
                        if (spPayloadBytes.length != 4) {
                            log("Incorrect length noted for 'size' record: "
                                    + spPayloadBytes.length);
                        }
                        if (spPayloadBytes.length >= 4) {
                            long size = 0;
                            for (int i = 0; i < 4; ++i) {
                                size <<= 8;
                                size |= spPayloadBytes[i] & 0xff;
                            }
                            toReturn.put(Constants.NDEF_SMART_POSTER_URI_SIZE,
                                    size);
                        }
                    } else if (Constants.NDEF_SMART_POSTER_URI_TYPE_TYPE
                            .equals(type)) {
                        log("Reading URI Type");
                        if (spPayloadBytes.length == 0) {
                            toReturn.put(Constants.NDEF_SMART_POSTER_URI_TYPE,
                                    "");
                        } else {
                            toReturn.put(Constants.NDEF_SMART_POSTER_URI_TYPE,
                                    new String(spPayloadBytes, "UTF-8"));
                        }
                    } else {
                        // Unexpected TNF_WELL_KNOWN for a smart poster...
                        log("Unexpected type for TNF_WELL_KNOWN for smart poster: "
                                + type);
                    }
                } else if (tnf == NDEFRecord.TNF_MEDIA) {
                    log("Reading " + NDEFRecord.TNF_MEDIA);
                    try {
                        getOrCreateArray(toReturn,
                                Constants.NDEF_SMART_POSTER_ICONS).put(
                                parseMediaRecord(spRecords[k]));
                    } catch (IOException ioe) {
                        log("Could not build media record: " + ioe.getMessage());
                    }
                } else {
                    log("Unexpected type name format for smart poster: " + tnf);
                }

                log("finished if");
            }
        } else {
            log("Empty Smart Poster Message");
            toReturn.putOpt(Constants.NDEF_ERROR,
                    "NdefMessageParser empty Smart Poster Message");
        }
        return toReturn;
    }

    protected JSONObject parseMediaRecord(NDEFRecord ndefRecord)
            throws JSONException, IOException {
        log("parseMediaRecord(NDEFRecord)");
        JSONObject toReturn = parseGenericRecord(ndefRecord);
        byte[] payLoad = ndefRecord.getPayload();
        String base64 = Base64OutputStream.encodeAsString(payLoad, 0,
                payLoad.length, false, false);
        toReturn.put(Constants.NDEF_MEDIA_MIME_TYPE, ndefRecord.getType());
        toReturn.put(Constants.NDEF_MEDIA_MIME_BODY, base64);
        toReturn.put(Constants.NDEF_MEDIA_DATA_URI,
                "data:" + ndefRecord.getType() + ";base64," + base64);
        return toReturn;
    }

    private JSONArray getOrCreateArray(JSONObject object, String name)
            throws JSONException {
        log("getOrCreateArray(JSONObject,String)");
        JSONArray toReturn = null;
        if (object.has(name)) {
            toReturn = object.getJSONArray(name);
        } else {
            toReturn = new JSONArray();
            object.put(name, toReturn);
        }
        return toReturn;
    }
}
TOP

Related Classes of widgetpackage.NdefMessageParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.