All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.servicerocket.confluence.randombits.storage.StringBasedStorage Maven / Gradle / Ivy

There is a newer version: 2.5.12
Show newest version
/*
 * Copyright (c) 2006, David Peterson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of "randombits.org" nor the names of its contributors
 *       may be used to endorse or promote products derived from this software
 *       without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package com.servicerocket.confluence.randombits.storage;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.BaseException;
import org.apache.log4j.Logger;

import java.util.Date;
import java.util.List;

/**
 * This is an abstract base-class for storage locations which only provide
 * String storage.
 * 
 * @author David Peterson
 */
public abstract class StringBasedStorage extends BasedStorage implements Aliasable {
    private static final Logger LOG = Logger.getLogger( StringBasedStorage.class );

    private XStream xStream;

    /**
     * @param type
     *            The type of the storage object.
     */
    public StringBasedStorage( BoxType type ) {
        super( type );
    }

    /**
     * @param alias
     *            The alias for the class
     * @param clazz
     *            The class to alias.
     */
    public void addAlias( String alias, Class clazz ) {
        getXStream().alias( alias, clazz );
    }

    /**
     * @return the XStream instance.
     */
    private XStream getXStream() {
        if ( xStream == null ) {
            xStream = new XStream();
            xStream.setClassLoader( getClass().getClassLoader() );
        }
        return xStream;
    }

    /**
     * Sets the classloader which will be used for serialization.
     * 
     * @param classLoader
     *            The serialization classloader.
     */
    public void setClassLoader( ClassLoader classLoader ) {
        getXStream().setClassLoader( classLoader );
    }

    /**
     * Converts the object to XML.
     * 
     * @param value
     *            The object to convert.
     * @return The XML version of the object.
     */
    protected String objectToXML( Object value ) {
        if ( value != null )
            return getXStream().toXML( value );
        return null;
    }

    /**
     * Converts the XML into an object.
     * 
     * @param xml
     *            The XML to convert.
     * @return the object version of the XML
     */
    protected Object xmlToObject( String xml ) {
        if ( xml != null ) {
            try {
                return getXStream().fromXML( xml );
            } catch ( BaseException e ) {
                LOG.debug( "Conversion error occurred while retrieving object.", e );
            }

        }
        return null;
    }

    @Override protected Boolean getBaseBoolean( String name ) {
        String value = getBaseString( name );
        if ( value != null )
            return Boolean.valueOf( value );
        return null;
    }

    @Override protected Date getBaseDate( String name ) {
        Long time = getBaseLong( name );
        if ( time != null )
            return new Date( time.longValue() );
        return null;
    }

    @Override protected Double getBaseDouble( String name ) {
        String value = getBaseString( name );
        try {
            if ( notEmpty( value ) )
                return new Double( value );
        } catch ( NumberFormatException e ) {
            throw new StorageException( "Value for '" + name + "' is not a valid double: " + value, e );
        }
        return null;
    }

    @Override protected Integer getBaseInteger( String name ) {
        Number n = getBaseNumber( name );
        return null == n ? null : new Integer( n.intValue() );
    }

    private boolean notEmpty( String value ) {
        return value != null && value.trim().length() > 0;
    }

    @Override protected Long getBaseLong( String name ) {
        Number n = getBaseNumber( name );
        return null == n ? null : new Long( n.longValue() );
    }

    /**
     * Returns the named value as a Number. Useful if the specific type of
     * number in the field is unknown.
     * 
     * @param name
     *            The name of the value.
     * @return The value as a Number.
     */
    @Override protected Number getBaseNumber( String name ) {
        return getBaseDouble( name );
    }
    
    /**
     * Gets the base object, checking if it is an instance of the supplied class.
     * If not, null is returned.
     *
     * @param  The type specify by clazz.
     * @param name The field name.
     * @param clazz The class to check against.
     * @return The field value, or null if the field does not match the class.
     */
    protected  T getBaseObject( String name, Class clazz ) {
        Object value = getBaseObject( name );
        return toType( value, null, clazz );
    }

    @Override protected Object getBaseObject( String name ) {
        String value = getBaseString( name );
        if ( value != null ) {
            Object obj = xmlToObject( value );
            return ( obj == null ) ? value : obj;
        }
        return null;
    }

    @Override protected List getBaseObjectList( String name ) {
        String[] values = getBaseStringArray( name );
        if ( values != null && values.length >= 0 ) {
            List list = new java.util.ArrayList( values.length );
            for (String value : values) {
                if (value == null || value.trim().length() == 0) {
                    list.add(null);
                } else {
                    list.add(xmlToObject(value));
                }
            }
            return list;
        }

        return null;
    }

    @Override protected String[] getBaseStringArray( String name ) {
        String fieldSizeName = name + ".length";
        Integer fieldSize = getBaseInteger( fieldSizeName );
        if ( fieldSize != null && fieldSize.intValue() >= 0 ) {
            String[] value = new String[fieldSize.intValue()];

            for ( int i = 0; i < value.length; i++ ) {
                value[i] = getBaseString( name + "." + i );
            }
            return value;
        }
        return null;
    }

    @Override protected void setBaseBoolean( String name, Boolean value ) {
        if ( value != null )
            setBaseString( name, value.toString() );
        else
            setBaseString( name, null );
    }

    @Override protected void setBaseDate( String name, Date value ) {
        if ( value != null )
            setBaseLong( name, new Long( value.getTime() ) );
        else
            setBaseString( name, null );
    }

    @Override protected void setBaseDouble( String name, Double value ) {
        if ( value != null )
            setBaseString( name, value.toString() );
        else
            setBaseString( name, null );
    }

    @Override protected void setBaseInteger( String name, Integer value ) {
        if ( value != null )
            setBaseString( name, value.toString() );
        else
            setBaseString( name, null );
    }

    @Override protected void setBaseLong( String name, Long value ) {
        if ( value != null )
            setBaseString( name, value.toString() );
        else
            setBaseString( name, null );
    }

    @Override protected void setBaseObject( String name, Object value ) {
        if ( value != null )
            setBaseString( name, objectToXML( value ) );
        else
            setBaseString( name, null );
    }

    @Override protected void setBaseObjectList( String name, List value ) {
        String fieldLengthName = name + ".length";

        // Clear any existing data
        Integer oldLength = getBaseInteger( fieldLengthName );
        if ( oldLength != null ) {
            for ( int i = 0; i < oldLength.intValue(); i++ )
                setBaseObject( name + "." + i, null );
        }

        if ( value == null )
            setBaseInteger( fieldLengthName, null );
        else {
            setBaseInteger( fieldLengthName, new Integer( value.size() ) );
            for ( int i = 0; i < value.size(); i++ ) {
                setBaseObject( name + "." + i, value.get( i ) );
            }
        }
    }

    @Override protected void setBaseStringArray( String name, String[] value ) {
        String fieldLengthName = name + ".length";

        // Clear any existing data
        Integer oldLength = getBaseInteger( fieldLengthName );
        if ( oldLength != null ) {
            int oli = oldLength.intValue();
            for ( int i = 0; i < oli; i++ )
                setBaseString( name + "." + i, null );
        }

        // Save the new data.
        if ( value == null )
            setBaseInteger( fieldLengthName, null );
        else {
            setBaseInteger( fieldLengthName, new Integer( value.length ) );
            for ( int i = 0; i < value.length; i++ )
                setBaseString( name + "." + i, value[i] );
        }
    }
}