com.google.api.gbase.client.ConversionUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.google.api.gbase.client.ConversionUtil.java

Source

/**
 * Mule Google Api Commons
 *
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 *
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */

package com.google.api.gbase.client;

import com.google.gdata.util.common.base.StringUtil;
import com.google.common.collect.Multimap;
import com.google.gdata.data.DateTime;

import java.util.ArrayList;
import java.util.Collection;

/**
 * Some methods for converting strings found in XML files
 * into other types.
 */
class ConversionUtil {

    private enum TaxField {
        Country("country"), Region("region"), Rate("rate"), TaxShip("tax_ship");

        private final String elemName;
        private final String attrName;

        TaxField(String elemName) {
            this.elemName = elemName;
            this.attrName = elemName.replace('_', ' ');
        }

        public String getElemName() {
            return elemName;
        }

        public String getAttrName() {
            return attrName;
        }
    }

    private enum ShippingField {
        Country("country"), Region("region"), Price("price"), Service("service");

        private final String elemName;
        private final String attrName;

        ShippingField(String elemName) {
            this.elemName = elemName;
            this.attrName = elemName.replace('_', ' ');
        }

        public String getElemName() {
            return elemName;
        }

        public String getAttrName() {
            return attrName;
        }
    }

    /**
     * Name of the element inside an attribute of type location
     * that contains the latitude.
     */
    private static final String LATITUDE_ELEMENT_NAME = "latitude";

    /**
     * Name of the element inside of an attribute of type location
     * that contains the longitude.
     */
    private static final String LONGITUDE_ELEMENT_NAME = "longitude";

    /** This class is not meant to be instantiated. */
    private ConversionUtil() {
    }

    /** Converts a string to a Float. */
    static Float toFloat(String text) {
        if (text == null) {
            return null;
        }
        return new Float(text);
    }

    /** Converts a string to an Integer. */
    static Integer toInteger(String text) {
        if (text == null) {
            return null;
        }
        return new Integer(text);
    }

    /** Converts a string to a Boolean. */
    static Boolean toBoolean(String text) {
        if (text == null) {
            return null;
        }
        return new Boolean(text);
    }

    /** Converts a string containing a date or a date and a time to a DateTime. */
    static DateTime toDateOrDateTime(String text) {
        if (text == null) {
            return null;
        }
        return DateTime.parseDateTimeChoice(text);
    }

    /**
     * Converts a integer followed by a unit name into an object.
     *
     * @param string a string of the form: <code>integer " " unit</code> or null
     * @return the corresponding object or null
     * @exception NumberFormatException if the conversion failed
     */
    public static NumberUnit<Integer> toIntUnit(String string) {
        if (string == null) {
            return null;
        }
        int firstSpace = findFirstSpace(string);
        String beforeSpace = beforeSpace(string, firstSpace);
        return new NumberUnit<Integer>(new Integer(beforeSpace), parseUnit(string, firstSpace));
    }

    /**
     * Converts a float followed by a unit name into an object.
     *
     * @param string a string of the form: <code>float " " unit</code> or null
     * @return the corresponding object or null
     * @exception NumberFormatException if the conversion failed
     */
    public static NumberUnit<Float> toFloatUnit(String string) {
        if (string == null) {
            return null;
        }
        int firstSpace = findFirstSpace(string);
        String beforeSpace = beforeSpace(string, firstSpace);
        return new NumberUnit<Float>(new Float(beforeSpace), parseUnit(string, firstSpace));
    }

    private static String beforeSpace(String string, int firstSpace) {
        return string.substring(0, firstSpace);
    }

    private static String parseUnit(String string, int firstSpace) {
        return string.substring(firstSpace + 1).trim();
    }

    private static int findFirstSpace(String string) {
        int firstSpace = string.indexOf(" ");
        if (firstSpace == -1 || firstSpace == string.length()) {
            throw new NumberFormatException("missing unit in '" + string + "'");
        }
        return firstSpace;
    }

    /**
     * Creates a {@link com.google.api.gbase.client.GoogleBaseAttribute} of type
     * {@link GoogleBaseAttributeType#DATE_TIME_RANGE}
     * and initializes it using the current state of the object.
     *
     * @param name attribute name
     * @param range attribute value
     * @return a new {@link com.google.api.gbase.client.GoogleBaseAttribute}
     */
    public static GoogleBaseAttribute createAttribute(String name, DateTimeRange range) {
        return new GoogleBaseAttribute(name, GoogleBaseAttributeType.DATE_TIME_RANGE, range.toString());
    }

    /**
     * Extracts a {@link DateTimeRange} from the value of a
     * {@link com.google.api.gbase.client.GoogleBaseAttribute}.
     *
     * @param attribute
     * @exception NumberFormatException if the conversion failed, either
     *   because on of the date/time was invalid or if the expected start
     *   and end tags were missing
     */
    public static DateTimeRange extractDateTimeRange(GoogleBaseAttribute attribute) {
        String range = attribute.getValueAsString();
        int space = range.indexOf(' ');
        if (space == -1) {
            /* Not really a range, but since date and dateTime are subtypes
             * of DateTimeRange, try and convert them into a DateTimeRange.
             */
            return new DateTimeRange(toDateOrDateTime(range));
        } else {
            String startStr = range.substring(0, space);
            String endStr = range.substring(space + 1);
            return new DateTimeRange(toDateOrDateTime(startStr), toDateOrDateTime(endStr));
        }
    }

    /**
     * Extracts a {@link Group} object from the value of a
     * {@link com.google.api.gbase.client.GoogleBaseAttribute}.
     *
     * @param attribute
     */
    public static Group extractGroup(GoogleBaseAttribute attribute) {
        return new Group(attribute.getSubAttributes());
    }

    /**
     * Creates a {@link GoogleBaseAttribute} of type
     * {@link GoogleBaseAttributeType#GROUP} and initializes it using the
     * current state of the object. Sub-attributes of group with type
     * GROUP or GROUP's derived types are ignored.
     * 
     * @param name attribute name
     * @param group attribute value
     * @return a new {@link com.google.api.gbase.client.GoogleBaseAttribute}
     */
    public static GoogleBaseAttribute createAttribute(String name, Group group) {
        GoogleBaseAttribute attribute = new GoogleBaseAttribute(name, GoogleBaseAttributeType.GROUP);
        Multimap<String, GoogleBaseAttribute> subAttributes = group.getAllSubAttributes();
        for (GoogleBaseAttribute attr : subAttributes.values()) {
            GoogleBaseAttributeType type = attr.getType();
            if (!GoogleBaseAttributeType.GROUP.equals(type)
                    && !GoogleBaseAttributeType.GROUP.equals(type.getSupertype())
                    && (attr.hasValue() || attr.hasSubElements())) {
                attribute.addSubAttribute(attr);
            }
        }
        return attribute;
    }

    /**
     * Extracts a {@link Shipping} object from the value of a
     * {@link com.google.api.gbase.client.GoogleBaseAttribute}.
     *
     * @param attribute
     * @exception NumberFormatException if the conversion failed 
     *    because the price is missing or not a number.
     */
    public static Shipping extractShipping(GoogleBaseAttribute attribute) {
        if (attribute.hasSubAttributes()) {
            return extractShippingFromAttributes(attribute);
        } else {
            return extractShippingFromElements(attribute);
        }
    }

    private static Shipping extractShippingFromAttributes(GoogleBaseAttribute attribute) {
        NumberUnit<Float> priceUnit = null;
        String country = null;
        Collection<String> regions = new ArrayList<String>();
        ;
        String service = null;
        for (GoogleBaseAttribute attr : attribute.getSubAttributes()) {
            String name = attr.getName();
            if (ShippingField.Country.getAttrName().equals(name)) {
                country = attr.getValueAsString();
            } else if (ShippingField.Region.getAttrName().equals(name)) {
                regions.add(attr.getValueAsString());
            } else if (ShippingField.Price.getAttrName().equals(name)) {
                String price = attr.getValueAsString();
                try {
                    priceUnit = toFloatUnit(price);
                } catch (NumberFormatException e) {
                    priceUnit = new NumberUnit<Float>(Float.parseFloat(price), null);
                }
            } else if (ShippingField.Service.getAttrName().equals(name)) {
                service = attr.getValueAsString();
            } else {
                throw new IllegalArgumentException("Sub-attribute " + name + " is not supported in Shipping.");
            }
        }
        if (priceUnit == null) {
            throw new NumberFormatException("missing 'price' element in shipping attribute: " + attribute);
        }
        return new Shipping(country, regions, service, priceUnit.getValue(), priceUnit.getUnit());
    }

    private static Shipping extractShippingFromElements(GoogleBaseAttribute attribute) {
        String country = attribute.getSubElementValue(ShippingField.Country.getElemName());
        Collection<String> regions = attribute.getSubElementValues(ShippingField.Region.getElemName());
        String price = attribute.getSubElementValue(ShippingField.Price.getElemName());
        String service = attribute.getSubElementValue(ShippingField.Service.getElemName());
        if (price == null) {
            throw new NumberFormatException("missing 'price' element in shipping attribute: " + attribute);
        }
        NumberUnit<Float> priceUnit;
        try {
            priceUnit = toFloatUnit(price);
        } catch (NumberFormatException e) {
            priceUnit = new NumberUnit<Float>(Float.parseFloat(price), null);
        }
        return new Shipping(country, regions, service, priceUnit.getValue(), priceUnit.getUnit());
    }

    /**
     * Creates a {@link GoogleBaseAttribute} of type
     * {@link GoogleBaseAttributeType#SHIPPING} and initializes it using the
     * current state of the object.
     * @param name attribute name
     * @param shipping attribute value
     * @return a new {@link com.google.api.gbase.client.GoogleBaseAttribute}
     */
    public static GoogleBaseAttribute createAttribute(String name, Shipping shipping) {
        GoogleBaseAttribute attribute = new GoogleBaseAttribute(name, GoogleBaseAttributeType.SHIPPING);

        if (shipping.getCountry() != null) {
            GoogleBaseAttribute countryAttr = new GoogleBaseAttribute(ShippingField.Country.getAttrName(), null,
                    shipping.getCountry());
            attribute.addSubAttribute(countryAttr);
        }
        for (String region : shipping.getRegions()) {
            GoogleBaseAttribute regionAttr = new GoogleBaseAttribute(ShippingField.Region.getAttrName(), null,
                    region);
            attribute.addSubAttribute(regionAttr);
        }
        if (shipping.getService() != null) {
            GoogleBaseAttribute serviceAttr = new GoogleBaseAttribute(ShippingField.Service.getAttrName(), null,
                    shipping.getService());
            attribute.addSubAttribute(serviceAttr);
        }

        String priceWithUnit = Float.toString(shipping.getPrice());
        if (shipping.getCurrency() != null) {
            priceWithUnit += " " + shipping.getCurrency();
        }
        GoogleBaseAttribute priceAttr = new GoogleBaseAttribute(ShippingField.Price.getAttrName(), null,
                priceWithUnit);
        attribute.addSubAttribute(priceAttr);
        return attribute;
    }

    /**
     * Extracts a {@link Tax} object from the value of a
     * {@link com.google.api.gbase.client.GoogleBaseAttribute}.
     *
     * @param attribute
     * @exception NumberFormatException if the conversion failed, usually
     *   because the rate is missing or not a number.
     */
    public static Tax extractTax(GoogleBaseAttribute attribute) {
        if (attribute.hasSubAttributes()) {
            return extractTaxFromAttributes(attribute);
        } else {
            return extractTaxFromElements(attribute);
        }
    }

    private static Tax extractTaxFromAttributes(GoogleBaseAttribute attribute) {
        String rateString = null;
        String country = null;
        Collection<String> regions = new ArrayList<String>();
        Boolean taxShip = null;
        for (GoogleBaseAttribute attr : attribute.getSubAttributes()) {
            String name = attr.getName();
            if (TaxField.Country.getAttrName().equals(name)) {
                country = attr.getValueAsString();
            } else if (TaxField.Region.getAttrName().equals(name)) {
                regions.add(attr.getValueAsString());
            } else if (TaxField.Rate.getAttrName().equals(name)) {
                rateString = attr.getValueAsString();
            } else if (TaxField.TaxShip.getAttrName().equals(name)) {
                String taxShipString = attr.getValueAsString();
                if (taxShipString != null) {
                    taxShip = Boolean.valueOf(taxShipString);
                }
            } else {
                throw new IllegalArgumentException("Sub-attribute " + name + " is not supported in Tax.");
            }
        }
        if (StringUtil.isEmpty(rateString)) {
            throw new NumberFormatException("missing 'rate' element in tax attribute: " + attribute);
        }
        float rate = Float.valueOf(rateString.trim()).floatValue();
        return new Tax(country, regions, rate, taxShip);
    }

    private static Tax extractTaxFromElements(GoogleBaseAttribute attribute) {
        String country = attribute.getSubElementValue(TaxField.Country.getElemName());
        Collection<String> regions = attribute.getSubElementValues(TaxField.Region.getElemName());
        String rateString = attribute.getSubElementValue(TaxField.Rate.getElemName());
        if (rateString == null) {
            throw new NumberFormatException("missing 'rate' element in tax attribute: " + attribute);
        }
        float rate = Float.valueOf(rateString.trim()).floatValue();
        String taxShipString = attribute.getSubElementValue(TaxField.TaxShip.getElemName());
        Boolean taxShip = null;
        if (taxShipString != null) {
            taxShip = Boolean.valueOf(taxShipString);
        }
        return new Tax(country, regions, rate, taxShip);
    }

    /**
     * Creates a {@link GoogleBaseAttribute} of type
     * {@link GoogleBaseAttributeType#TAX} and initializes it using the
     * current state of the object.
     * @param name attribute name
     * @param tax attribute value
     * @return a new {@link com.google.api.gbase.client.GoogleBaseAttribute}
     */
    public static GoogleBaseAttribute createAttribute(String name, Tax tax) {
        GoogleBaseAttribute attribute = new GoogleBaseAttribute(name, GoogleBaseAttributeType.TAX);
        GoogleBaseAttribute attr = null;
        if (tax.getCountry() != null) {
            attr = new GoogleBaseAttribute(TaxField.Country.getAttrName(), null, tax.getCountry());
            attribute.addSubAttribute(attr);
        }
        for (String region : tax.getRegions()) {
            attr = new GoogleBaseAttribute(TaxField.Region.getAttrName(), null, region);
            attribute.addSubAttribute(attr);
        }
        attr = new GoogleBaseAttribute(TaxField.Rate.getAttrName(), null, Float.toString(tax.getRate()));
        attribute.addSubAttribute(attr);
        if (tax.getTaxShip() != null) {
            attr = new GoogleBaseAttribute(TaxField.TaxShip.getAttrName(), null,
                    tax.getTaxShip() ? "true" : "false");
            attribute.addSubAttribute(attr);
        }
        return attribute;
    }

    /**
     * Extracts a {@link Location} object from the value of a
     * {@link GoogleBaseAttribute}.
     *
     * @param attribute
     * @return NumberFormatException if the conversion failed, usually
     *   because the latitude or longitude information are invalid numbers
     */
    public static Location extractLocation(GoogleBaseAttribute attribute) {
        String address = attribute.getValueAsString();
        Location retval = new Location(address);

        String latString = attribute.getSubElementValue(LATITUDE_ELEMENT_NAME);
        String longString = attribute.getSubElementValue(LONGITUDE_ELEMENT_NAME);
        if (latString != null && longString != null) {
            retval.setLatitude(Float.parseFloat(latString));
            retval.setLongitude(Float.parseFloat(longString));
        }
        return retval;
    }

    public static GoogleBaseAttribute createAttribute(String name, Location location) {
        GoogleBaseAttribute attribute = new GoogleBaseAttribute(name, GoogleBaseAttributeType.LOCATION);
        attribute.setValue(location.getAddress());
        if (location.hasCoordinates()) {
            attribute.setSubElement(LATITUDE_ELEMENT_NAME, Float.toString(location.getLatitude()));
            attribute.setSubElement(LONGITUDE_ELEMENT_NAME, Float.toString(location.getLongitude()));
        }
        return attribute;
    }

    /**
     * Extracts a {@link Number} from a {@link GoogleBaseAttribute}.
     *
     * @param attr an attribute of type NUMBER, FLOAT or INT, may be null
     * @return a Number, which might be an Integer or a Float depending
     *   on the type of the attribute, or null if {@code attr} was null
     */
    public static Number extractNumber(GoogleBaseAttribute attr) {
        if (attr == null) {
            return null;
        }

        /* If the attribute has been declared as being an int,
         * treat it as such, otherwise create  a Float.
         */
        if (GoogleBaseAttributeType.FLOAT.equals(attr.getAttributeId().getType())) {
            return toFloat(attr.getValueAsString());
        } else {
            return toInteger(attr.getValueAsString());
        }
    }

    /**
     * Extracts a <code>NumberUnit<Number></code> from a
     * {@link GoogleBaseAttribute}.
     *
     * @param attr an attribute of type NUMBER_UNIT, FLOAT_UNIT or INT_UNIT,
     *   may be null
     * @return a NumberUnit object whose number might be an Integer
     *   or a Float, depending on the type of the attribute, or null
     *   if {@code attr} was null
     */
    public static NumberUnit<? extends Number> extractNumberUnit(GoogleBaseAttribute attr) {
        if (attr == null) {
            return null;
        }

        if (GoogleBaseAttributeType.INT_UNIT.equals(attr.getAttributeId().getType())) {
            return toIntUnit(attr.getValueAsString());
        }
        return toFloatUnit(attr.getValueAsString());
    }
}