com.surevine.ldap2alfresco.ProfileFieldTelephoneConverter.java Source code

Java tutorial

Introduction

Here is the source code for com.surevine.ldap2alfresco.ProfileFieldTelephoneConverter.java

Source

/*
 * Copyright (C) 2008-2010 Surevine Limited.
 *   
 * Although intended for deployment and use alongside Alfresco this module should
 * be considered 'Not a Contribution' as defined in Alfresco'sstandard contribution agreement, see
 * http://www.alfresco.org/resource/AlfrescoContributionAgreementv2.pdf
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package com.surevine.ldap2alfresco;

import java.io.PrintWriter;
import java.io.StringWriter;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * Class which can convert a telephone number profile field between different formats.
 */
public class ProfileFieldTelephoneConverter implements ProfileFieldConverter {

    /**
     * Label for the attribute version.
     */
    private String attributeLabel;

    /**
     * Label for the JSON version.
     */
    private String jsonLabel;

    /**
     * Can there be multiple copies of the attribute?
     */
    private boolean allowMultiples;

    /**
     * Logging instance.
     */
    private static final Logger LOGGER = Logger.getLogger(ProfileFieldTelephoneConverter.class);

    /**
     * Label for JSON encoding of network field.
     */
    private static final String JSON_LABEL_NETWORK = "network";

    /**
     * Label for JSON encoding of number field.
     */
    private static final String JSON_LABEL_NUMBER = "number";

    /**
     * Label for JSON encoding of extension field.
     */
    private static final String JSON_LABEL_EXTENSION = "extension";

    /**
     * Constructor.
     * @param attributeName Name of attribute
     * @param jsonName Name of JSON encoded attribute
     * @param multiples Can there be multiple attributes with this name?
     */
    ProfileFieldTelephoneConverter(final String attributeName, final String jsonName, final boolean multiples) {
        attributeLabel = attributeName;
        jsonLabel = jsonName;
        allowMultiples = multiples;
    }

    /**
     * Encode some attributes as Attributes.
     * @param json The JSON object to convert
     * @param attributes Collection of attributes to insert into
     */
    public void toAttributes(final Attributes attributes, final JSONObject json) {

        BasicAttribute attr = new BasicAttribute(attributeLabel);

        try {
            if (allowMultiples) {
                JSONArray jsonNumbers = json.getJSONArray(jsonLabel);

                for (int x = 0; x < jsonNumbers.length(); x++) {
                    JSONObject jsonNumber = jsonNumbers.getJSONObject(x);
                    String number = encodePhoneNumber(jsonNumber);

                    if (number != null && number.length() > 0) {
                        attr.add(number);
                    }
                }
            } else {
                JSONObject jsonNumber = json.getJSONObject(jsonLabel);
                String number = encodePhoneNumber(jsonNumber);

                if (number != null && number.length() > 0) {
                    attr.add(number);
                }
            }
        } catch (JSONException e) {
            logException(Level.ERROR, e);
            return;
        }

        attributes.put(attr);
    }

    /**
     * Encode some attributes as JSON.
     * @param json The JSON object to insert into
     * @param attributes Collection of attributes
     */
    public void toJson(final JSONObject json, final Attributes attributes) {

        Attribute attribute = attributes.get(attributeLabel);

        if (attribute == null) {
            LOGGER.debug("Missing attribute: " + attributeLabel);

            // just put an empty entry into the JSON
            try {
                if (allowMultiples) {
                    json.put(jsonLabel, new JSONArray());
                } else {
                    JSONObject blank = new JSONObject();
                    blank.put(JSON_LABEL_NETWORK, "");
                    blank.put(JSON_LABEL_NUMBER, "");
                    blank.put(JSON_LABEL_EXTENSION, "");
                    json.put(jsonLabel, blank);
                }
            } catch (JSONException e) {
                logException(Level.ERROR, e);
            }

            return;
        }

        int numValues = attribute.size();

        if (numValues == 0) {
            LOGGER.error("Attribute " + attributeLabel + " contains no values");
            return;
        }

        try {
            if (allowMultiples) {

                JSONArray values = new JSONArray();

                NamingEnumeration<?> valueEnum = attribute.getAll();

                while (valueEnum.hasMore()) {
                    String value = valueEnum.next().toString();
                    JSONObject entry = decodePhoneNumber(value);

                    if (entry == null) {
                        LOGGER.error("Failed to parse telephone number from :" + value);
                    } else {
                        values.put(entry);
                    }
                }

                json.put(jsonLabel, values);
            } else {
                // expecting only one value
                if (numValues != 1) {
                    LOGGER.error("Expected single value in attribute " + attributeLabel + ", found " + numValues);
                    return;
                }

                String value = attribute.get().toString();
                JSONObject entry = decodePhoneNumber(value);

                if (entry == null) {
                    LOGGER.error("Failed to parse telephone fields from :" + value);
                } else {
                    json.put(jsonLabel, entry);
                }
            }
        } catch (NamingException e) {
            logException(Level.ERROR, e);
            return;
        } catch (JSONException e) {
            logException(Level.ERROR, e);
            return;
        }
    }

    /**
     * Generate comma separated fields in a string representation.
     * @param json JSON encoded phone number
     * @return String encoded version
     */
    private String encodePhoneNumber(final JSONObject json) {
        String network;
        String number;
        String extension;

        try {
            network = json.getString(JSON_LABEL_NETWORK);
            number = json.getString(JSON_LABEL_NUMBER);
            extension = json.getString(JSON_LABEL_EXTENSION);
        } catch (JSONException e) {
            logException(Level.ERROR, e);
            return null;
        }

        if (!isNetworkValid(network)) {
            LOGGER.error("Telephone network is not valid: " + network);
            return null;
        }

        if (!isNumberValid(number)) {
            LOGGER.error("Telephone number is not valid: " + number);
            return null;
        }

        if (!isExtensionValid(extension)) {
            LOGGER.error("Telephone extension is not valid: " + extension);
            return null;
        }

        return network + "," + number + "," + extension;
    }

    /**
     * Separate out comma separated fields in a string representation.
     * @param phone The phone number
     * @return JSON encoded version
     */
    private JSONObject decodePhoneNumber(final String phone) {
        // limit argument of -1 to allow empty strings
        // to be parsed out (otherwise any trailing empty
        // string is removed
        String[] fields = phone.split(",", -1);

        if (fields.length != 3) {
            LOGGER.error("Expected 3 fields for telephone number, found " + fields.length + "fields: " + phone);
            return null;
        }

        String network = fields[0];
        String number = fields[1];
        String extension = fields[2];

        if (!isNetworkValid(network)) {
            LOGGER.error("Telephone network is not valid: " + network);
            return null;
        }

        if (!isNumberValid(number)) {
            LOGGER.error("Telephone number is not valid: " + number);
            return null;
        }

        if (!isExtensionValid(extension)) {
            LOGGER.error("Telephone extension is not valid: " + extension);
            return null;
        }

        JSONObject json = new JSONObject();

        try {
            json.put(JSON_LABEL_NETWORK, network);
            json.put(JSON_LABEL_NUMBER, number);
            json.put(JSON_LABEL_EXTENSION, extension);
        } catch (JSONException e) {
            logException(Level.ERROR, e);
            return null;
        }

        return json;
    }

    /**
     * Is a string representation of a telephone network valid?
     * @param network Network to check
     * @return if the representation is valid
     */
    private boolean isNetworkValid(final String network) {
        return network.matches("^[A-Z0-9\\- ]+$");
    }

    /**
     * Is a string representation of a telephone number valid?
     * @param number Number to check
     * @return if the representation is valid
     */
    private boolean isNumberValid(final String number) {
        return number.matches("^[0-9 *()+#]+$");
    }

    /**
     * Is a string representation of a telephone extension valid?
     * @param extension Extension to check
     * @return if the representation is valid
     */
    private boolean isExtensionValid(final String extension) {
        return extension.matches("^[0-9 *()+#]*$");
    }

    /**
     * Output an exception's stack trace to the log file.
     * @param level The log level
     * @param e The exception
     */
    private void logException(final Level level, final Exception e) {
        try {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            LOGGER.log(level, sw.toString());
        } catch (Exception e2) {
            LOGGER.log(level, "stack trace unavailable");
        }
    }
}