org.loy.fesf.core.impl.BaseContext.java Source code

Java tutorial

Introduction

Here is the source code for org.loy.fesf.core.impl.BaseContext.java

Source

/*
 * COPYRIGHT. ALL RIGHTS RESERVED.
 * 
 * This software is only to be used for the purpose for which it has been
 * provided. No part of it is to be reproduced, disassembled, transmitted,
 * stored in a retrieval system nor translated in any human or computer
 * language in any way or for any other purposes whatsoever without the prior
 * written consent of loy org.
 */

/*
 * Copyright 1999-2004 The Apache Software Foundation
 * 
 * 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.
 */

/*
 * NOTICE: This source code originally belongs to the ContextBase class of
 * Apache Commons Chain API. It has been modified to meet specific
 * requirements. The following changes have been introduced: - The ContextBase
 * class has been renamed to BaseContext. - The package has been changed to
 * org.loy.fesf.core - The BaseContext class implements
 * org.loy.fesf.core.Context. - Methods checkKey and checkValue have been
 * introduced. - The get, put and remove methods have a call to the methods
 * checkKey and ChcekValue.
 */
package org.loy.fesf.core.impl;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.loy.fesf.core.Context;

/**
 * <p>
 * Convenience base class for {@link Context}implementations.
 * </p>
 *
 * <p>
 * In addition to the minimal functionality required by the {@link Context}
 * interface, this class implements the recommended support for
 * Attribute-Property Transparency
 * </p>
 * . This is implemented by analyzing the available JavaBeans properties of
 * this class (or its subclass), exposes them as key-value pairs in the
 * <code>Map</code>, with the key being the name of the property itself.
 *
 * <p>
 * <strong>IMPLEMENTATION NOTE</strong> - Because <code>empty</code> is a
 * read-only property defined by the <code>Map</code> interface, it may not be
 * utilized as an attribute key or property name.
 * </p>
 *
 * @author Craig R. McClanahan
 * @version $Revision: 1.4 $ $Date: 2008/02/11 17:19:02IST $
 *
 * <br>
 *          NOTICE:</br> This source code originally belongs to the ContextBase
 *          class of Apache Commons Chain API. It has been modified to meet
 *          specific requirements. <br>
 *          The following changes have been introduced:</br> <li>The
 *          ContextBase class has been renamed to BaseContext.</li> <li>The
 *          package has been changed to org.loy.fesf.core</li> <li>The
 *          BaseContext class implements org.loy.fesf.core.Context.</li> <li>
 *          Methods checkKey and checkValue have been introduced.</li> <li>The
 *          get, put and remove methods have a call to the methods checkKey and
 *          ChcekValue.</li>
 *
 */
public class BaseContext implements Context {
    // --------------------------------------------------------- Private
    // Classes

    /**
     * This HashMap stores all context information put in this class or in any
     * of its sub-classes.
     */
    private final HashMap<Object, Object> localMap;

    /**
     * <p>
     * Private implementation of <code>Set</code> that implements the semantics
     * required for the value returned by <code>entrySet()</code>.
     * </p>
     */
    private class EntrySetImpl extends AbstractSet<Object> {

        /**
         * Clears the entries in the inner class EntrySetImpl object.
         */
        @Override
        public void clear() {
            BaseContext.this.clear();
        }

        /**
         * Check for an entry in the inner class EntrySetImpl object.
         *
         * @param obj
         *            Object
         * @return boolean
         */
        @Override
        public boolean contains(final Object obj) {
            Map.Entry entry = null;
            Entry actual = null;

            if (!(obj instanceof Map.Entry)) {
                return (false);
            }

            entry = (Map.Entry) obj;
            actual = BaseContext.this.entry(entry.getKey());

            if (actual != null) {
                return (actual.equals(entry));
            }
            return (false);

        }

        /**
         * Check if there is no entry in the inner class EntrySetImpl object.
         *
         * @return boolean
         */
        @Override
        public boolean isEmpty() {
            return (BaseContext.this.isEmpty());
        }

        /**
         * Get an iteraor for the inner class EntrySetImpl object entries.
         *
         * @return Iterator
         */
        @Override
        public Iterator iterator() {
            return (BaseContext.this.entriesIterator());
        }

        /**
         * Remove an entry from the inner class EntrySetImpl object.
         *
         * @param obj
         *            Object
         * @return boolean
         */
        @Override
        public boolean remove(final Object obj) {
            if (obj instanceof Map.Entry) {
                return (BaseContext.this.remove((Map.Entry) obj));
            }
            return (false);

        }

        /**
         * Get no of entries in the inner class EntrySetImpl object.
         *
         * @return int
         */
        @Override
        public int size() {
            return (BaseContext.this.size());
        }

    }

    /**
     * <p>
     * Private implementation of <code>Iterator</code> for the <code>Set</code>
     * returned by <code>entrySet()</code>.
     * </p>
     */
    private class EntrySetIterator implements Iterator {

        /**
         * Map.Entry type identifier.
         */
        private Map.Entry entry = null;

        /**
         * Iterator type identifier.
         */
        private final Iterator keys = BaseContext.this.keySet().iterator();

        /**
         * Check if there are any more entries.
         *
         * @return boolean
         */
        @Override
        public boolean hasNext() {
            return (this.keys.hasNext());
        }

        /**
         * Get the next entry.
         *
         * @return Object
         */
        @Override
        public Object next() {
            this.entry = BaseContext.this.entry(this.keys.next());

            return (entry);
        }

        /**
         * Remove entry from Context.
         */
        @Override
        public void remove() {
            BaseContext.this.remove(entry);
        }

    }

    /**
     * <p>
     * Private implementation of <code>Map.Entry</code> for each item in
     * <code>EntrySetImpl</code>.
     * </p>
     */
    private class MapEntryImpl implements Map.Entry {

        /**
         * Object type identifier.
         */
        private final Object key;

        /**
         * Object type identifier.
         */
        private Object value;

        /**
         * Constructor for MapEntryImpl.
         *
         * @param tempKey
         *            Object
         * @param tempValue
         *            Object
         */
        MapEntryImpl(final Object tempKey, final Object tempValue) {
            this.key = tempKey;
            this.value = tempValue;
        }

        /**
         * Overrides equals method of Object. Check if the passed object is the
         * same as on which the method is being called.
         *
         * @param obj
         *            Object
         * @return boolean
         */
        @Override
        public boolean equals(final Object obj) {
            Map.Entry entry = null;

            if (obj == null) {
                return (false);
            } else if (!(obj instanceof Map.Entry)) {
                return (false);
            }

            entry = (Map.Entry) obj;

            if (key == null) {
                return (entry.getKey() == null);
            }

            if (this.key.equals(entry.getKey())) {
                if (value == null) {
                    return (entry.getValue() == null);
                }
                return (this.value.equals(entry.getValue()));

            }
            return (false);
        }

        /**
         * Return key.
         *
         * @return Object
         */
        @Override
        public Object getKey() {
            return (this.key);
        }

        /**
         * Return value.
         *
         * @return Object
         */
        @Override
        public Object getValue() {
            return (this.value);
        }

        /**
         * Get the appropriate hashcode.
         *
         * @return int
         */
        @Override
        public int hashCode() {

            int keyHashCode = 0;
            if (key == null) {
                keyHashCode = 0;
            } else {
                keyHashCode = this.key.hashCode();
            }

            int valueHashCode = 0;
            if (value == null) {
                valueHashCode = 0;
            } else {
                valueHashCode = this.value.hashCode();
            }

            return keyHashCode ^ valueHashCode;

        }

        /**
         * Sets the value.
         *
         * @param tempValue
         *            Object
         * @return object
         */
        @Override
        public Object setValue(final Object tempValue) {
            Object previous = this.value;

            BaseContext.this.put(this.key, tempValue);
            this.value = tempValue;

            return (previous);
        }

        /**
         * Overrides toString method of Object.
         *
         * @return String
         */
        @Override
        public String toString() {
            return getKey() + "=" + getValue();
        }
    }

    /**
     * <p>
     * Private implementation of <code>Collection</code> that implements the
     * semantics required for the value returned by <code>values()</code>.
     * </p>
     */
    private class ValuesImpl extends AbstractCollection {

        /**
         * Clears the entries in the inner class ValuesImpl object.
         */
        @Override
        public void clear() {
            BaseContext.this.clear();
        }

        /**
         * Check for an entry in the inner class ValuesImpl object.
         *
         * @param obj
         *            Object
         * @return boolean
         */
        @Override
        public boolean contains(final Object obj) {
            Map.Entry entry = null;

            if (!(obj instanceof Map.Entry)) {
                return (false);
            }

            entry = (Map.Entry) obj;

            return (BaseContext.this.containsValue(entry.getValue()));
        }

        /**
         * Check whether there are any entries in the inner class ValuesImpl
         * object.
         *
         * @return boolean
         */
        @Override
        public boolean isEmpty() {
            return (BaseContext.this.isEmpty());
        }

        /**
         * Get the iterator for ValuesImpl object entries.
         *
         * @return Iterator
         */
        @Override
        public Iterator iterator() {
            return (BaseContext.this.valuesIterator());
        }

        /**
         * Remove an entry from the inner class ValuesImpl object.
         *
         * @param obj
         *            Object
         * @return boolean
         */
        @Override
        public boolean remove(final Object obj) {
            if (obj instanceof Map.Entry) {
                return (BaseContext.this.remove((Map.Entry) obj));
            }
            return (false);
        }

        /**
         * Return the no of entries in the ValuesImpl object.
         *
         * @return int
         */
        @Override
        public int size() {
            return (BaseContext.this.size());
        }

    }

    /**
     * <p>
     * Private implementation of <code>Iterator</code> for the
     * <code>Collection</code> returned by <code>values()</code>.
     * </p>
     */
    private class ValuesIterator implements Iterator {

        /**
         * Map.Entry type identifier.
         */
        private Map.Entry entry = null;

        /**
         * Iterator type identifier.
         */
        private final Iterator keys = BaseContext.this.keySet().iterator();

        /**
         * Returns whether there are more entries to iterate or not.
         * 
         * @return boolean
         */
        @Override
        public boolean hasNext() {
            return (this.keys.hasNext());
        }

        /**
         * Iterate to the next object.
         * 
         * @return Object
         */
        @Override
        public Object next() {
            this.entry = BaseContext.this.entry(this.keys.next());

            return (this.entry.getValue());
        }

        /**
         * Removes entry from the Context object.
         */
        @Override
        public void remove() {
            BaseContext.this.remove(entry);
        }

    }

    /**
     * <p>
     * Distinguished SINGLETON value that is stored in the map for each key
     * that is actually a property. This value is used to ensure that
     * <code>equals()</code> comparisons will always fail.
     * </p>
     */
    private static final Map SINGLETON = new HashMap() {

        /**
         * Overrides equals method of AbstractMap. Check if the passed object
         * is the same as on which the method is being called.
         *
         * @param object
         *            Object
         * @return boolean
         */
        @Override
        public boolean equals(final Object object) {
            return (false);
        }
    };

    /**
     * <p>
     * Zero-length array of parameter values for calling property getters.
     * </p>
     */
    private static final Object[] ZERO_PARAMS = new Object[0];

    // NOTE - PropertyDescriptor instances are not Serializable, so the
    // following variables must be declared as transient. When a BaseContext
    // instance is deserialized, the no-arguments constructor is called,
    // and the initialize() method called there will repoopulate them.
    // Therefore, no special restoration activity is required.

    /**
     * <p>
     * The <code>PropertyDescriptor</code> s for all JavaBeans properties of
     * this {@link Context}implementation class, keyed by property name. This
     * collection is allocated only if there are any JavaBeans properties.
     * </p>
     */
    private transient Map descriptors = null;

    /**
     * <p>
     * The same <code>PropertyDescriptor</code> s as an array.
     * </p>
     */
    private transient PropertyDescriptor[] pd = null;

    /**
     * Default Contructor for BaseContext.
     *
     */
    public BaseContext() {
        localMap = new HashMap(); // super();
        init();
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to return size of the
     * underlying <code>Map</code>.
     * </p>
     *
     * @return <code>0</code> if this Context is empty
     */
    @Override
    public int size() {
        // Even for properties a key is inserted in the underlying map
        // (See initialize() method). Hence the below statement will work.
        return (this.localMap.size());
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to return
     * <code>true</code> if the underlying <code>Map</code> only contains
     * key-value pairs for local properties (if any).
     * </p>
     *
     * @return <code>true</code> if this Context is empty, otherwise
     *         <code>false</code>.
     */
    @Override
    public boolean isEmpty() {
        // Case 1 -- no local properties
        if (descriptors == null) {
            return (this.localMap.isEmpty());
        }

        // Case 2 -- compare key count to property count
        return (this.localMap.size() <= this.descriptors.size());
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to return
     * <code>true</code> if the specified key is present in the underlying
     * <code>Map</code>.
     * </p>
     *
     * @param key
     *            the key look for in the context.
     * @return <code>true</code> if found in this context otherwise
     *         <code>false</code>.
     */
    @Override
    public boolean containsKey(final Object key) {
        // Even for properties a key is inserted in the underlying map
        // (See initialize() method). Hence the below statement will work.
        return (this.localMap.containsKey(key));
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to return
     * <code>true</code> if the specified value is present in either the
     * underlying <code>Map</code> or one of the local property values.
     * </p>
     *
     * @param value
     *            the value look for in the context.
     * @return <code>true</code> if found in this context otherwise
     *         <code>false</code>.
     *
     */
    @Override
    public boolean containsValue(final Object value) {

        // Case 1 -- no local properties
        if (descriptors == null) {
            return (this.localMap.containsValue(value));
        } else if (this.localMap.containsValue(value)) {
            // Case 2 -- value found in the underlying Map
            return (true);
        }

        // Case 3 -- check the values of our readable properties
        for (int i = 0; i < this.pd.length; i++) {
            if (pd[i].getReadMethod() != null) {
                Object prop = readProperty(pd[i]);

                if (value == null) {
                    if (prop == null) {
                        return (true);
                    }
                } else if (value.equals(prop)) {
                    return (true);
                }
            }
        }

        return (false);
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to return the value of a
     * local property if the specified key matches a local property name.
     * </p>
     *
     * <p>
     * <strong>IMPLEMENTATION NOTE </strong>- If the specified <code>key</code>
     * identifies a write-only property, <code>null</code> will arbitrarily be
     * returned, in order to avoid difficulties implementing the contracts of
     * the <code>Map</code> interface.
     * </p>
     *
     * @param key
     *            Key of the value to be returned
     * @return The value for the specified key.
     *
     */
    @Override
    public Object get(final Object key) {
        checkKey(key);

        // Case 1 -- no local properties
        if (descriptors == null) {
            return (this.localMap.get(key));
        }

        // Case 2 -- this is a local property
        if (key != null) {
            PropertyDescriptor descriptor = (PropertyDescriptor) this.descriptors.get(key);

            if (descriptor != null) {
                if (descriptor.getReadMethod() != null) {
                    return (readProperty(descriptor));
                }
                return (null);
            }
        }

        // Case 3 -- retrieve value from our underlying Map
        return (this.localMap.get(key));
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to set the value of a
     * local property if the specified key matches a local property name.
     * </p>
     *
     * @param key
     *            Key of the value to be stored or replaced
     * @param value
     *            New value to be stored
     * @return The value added to the Context.
     *
     */
    @Override
    public Object put(final Object key, final Object value) {
        checkKey(key);
        checkValue(value);

        // Case 1 -- no local properties
        if (descriptors == null) {
            return (this.localMap.put(key, value));
        }

        // Case 2 -- this is a local property
        if (key != null) {
            PropertyDescriptor descriptor = (PropertyDescriptor) this.descriptors.get(key);

            if (descriptor != null) {
                Object previous = null;

                if (descriptor.getReadMethod() != null) {
                    previous = readProperty(descriptor);
                }

                writeProperty(descriptor, value);

                return (previous);
            }
        }

        // Case 3 -- store or replace value in our underlying map
        return (this.localMap.put(key, value));
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to throw
     * <code>UnsupportedOperationException</code> on any attempt to remove a
     * key that is the name of a local property.
     * </p>
     *
     * @param key
     *            Key to be removed
     * @return The value removed from the Context.
     *
     */
    @Override
    public Object remove(final Object key) {
        checkKey(key);

        // Case 1 -- no local properties
        if (descriptors == null) {
            return (this.localMap.remove(key));
        }

        // Case 2 -- this is a local property
        if (key != null) {
            PropertyDescriptor descriptor = (PropertyDescriptor) this.descriptors.get(key);

            if (descriptor != null) {
                throw new UnsupportedOperationException("Local property '" + key + "' cannot be removed");
            }
        }

        // Case 3 -- remove from underlying Map
        return (this.localMap.remove(key));
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to call the
     * <code>put()</code> method individually for each key-value pair in the
     * specified <code>Map</code>.
     * </p>
     *
     * @param map
     *            <code>Map</code> containing key-value pairs to store (or
     *            replace)
     *
     */
    @Override
    public void putAll(final Map map) {
        Iterator pairs = map.entrySet().iterator();

        while (pairs.hasNext()) {
            Map.Entry pair = (Map.Entry) pairs.next();

            put(pair.getKey(), pair.getValue());
        }
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to clear all keys and
     * values except those corresponding to JavaBeans properties.
     * </p>
     */
    @Override
    public void clear() {
        if (descriptors == null) {
            this.localMap.clear();
        } else {
            Iterator keys = keySet().iterator();

            while (keys.hasNext()) {
                Object key = keys.next();

                if (!this.descriptors.containsKey(key)) {
                    keys.remove();
                }
            }
        }
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to return a
     * <code>Set</code> that meets the specified default behavior except for
     * attempts to remove the key for a property of the {@link Context}
     * implementation class, which will throw
     * <code>UnsupportedOperationException</code>.
     * </p>
     *
     * @return The set of keys for objects in this Context.
     */
    @Override
    public Set keySet() {
        return (this.localMap.keySet());
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to return a
     * <code>Collection</code> that meets the specified default behavior except
     * for attempts to remove the key for a property of the {@link Context}
     * implementation class, which will throw
     * <code>UnsupportedOperationException</code>.
     * </p>
     *
     * @return The collection of values in this Context.
     */
    @Override
    public Collection values() {
        return (new ValuesImpl());
    }

    /**
     * <p>
     * Override the default <code>Map</code> behavior to return a
     * <code>Set</code> that meets the specified default behavior except for
     * attempts to remove the key for a property of the {@link Context}
     * implementation class, which will throw
     * <code>UnsupportedOperationException</code>.
     * </p>
     *
     * @return Set of entries in the Context.
     */
    @Override
    public Set entrySet() {
        return (new EntrySetImpl());
    }

    // --------------------------------------------------------- Private
    // Methods

    /**
     * <p>
     * Eliminate the specified property descriptor from the list of property
     * descriptors in <code>pd</code>.
     * </p>
     *
     * @param name
     *            Name of the property to eliminate
     *
     */
    private void removePropertyDescriptor(final String name) {
        PropertyDescriptor[] results = null;
        int j = -1;
        boolean exit = false;
        for (int i = 0; (i < this.pd.length) && !exit; i++) {
            if (name.equals(pd[i].getName())) {
                j = i;
                exit = true;
            }
        }

        if (j < 0) {
            throw new IllegalArgumentException("Property '" + name + "' is not present");
        }

        results = new PropertyDescriptor[this.pd.length - 1];
        System.arraycopy(pd, 0, results, 0, j);
        System.arraycopy(pd, j + 1, results, j, this.pd.length - (j + 1));
        this.pd = results;
    }

    /**
     * <p>
     * Return an <code>Iterator</code> over the set of <code>Map.Entry</code>
     * objects representing our key-value pairs.
     * </p>
     *
     * @return Iterator
     *
     */
    private Iterator entriesIterator() {
        return (new EntrySetIterator());
    }

    /**
     * <p>
     * Return a <code>Map.Entry</code> for the specified key value, if it is
     * present; otherwise, return <code>null</code>.
     * </p>
     *
     * @param key
     *            Attribute key or property name
     * @return Map.Entry
     *
     */
    private Map.Entry entry(final Object key) {
        if (containsKey(key)) {
            return (new MapEntryImpl(key, get(key)));
        }
        return (null);
    }

    /**
     * <p>
     * Customize the contents of our underlying <code>Map</code> so that it
     * contains keys corresponding to all of the JavaBeans properties of the
     * {@link Context}implementation class.
     * </p>
     *
     */
    private void init() {
        // Retrieve the set of property descriptors for this Context class
        try {
            this.pd = Introspector.getBeanInfo(getClass()).getPropertyDescriptors();
        } catch (IntrospectionException e) {
            this.pd = new PropertyDescriptor[0]; // Should never happen
        }

        removePropertyDescriptor("class"); // Because of "getClass()"
        removePropertyDescriptor("empty"); // Because of "isEmpty()"

        // Initialize the underlying Map contents
        if (this.pd.length > 0) {
            this.descriptors = new HashMap();

            for (int i = 0; i < this.pd.length; i++) {
                this.descriptors.put(pd[i].getName(), pd[i]);
                this.localMap.put(pd[i].getName(), BaseContext.SINGLETON);
            }
        }
    }

    /**
     * <p>
     * Get and return the value for the specified property.
     * </p>
     *
     * @param descriptor
     *            <code>PropertyDescriptor</code> for the specified property
     * @return Object
     *
     */
    private Object readProperty(final PropertyDescriptor descriptor) {
        try {
            Method method = descriptor.getReadMethod();

            if (method == null) {
                throw new UnsupportedOperationException("Property '" + descriptor.getName() + "' is not readable");
            }

            return (method.invoke(this, BaseContext.ZERO_PARAMS));
        } catch (Exception e) {
            throw new UnsupportedOperationException(
                    "Exception reading property '" + descriptor.getName() + "': " + e.getMessage());
        }
    }

    /**
     * <p>
     * Remove the specified key-value pair, if it exists, and return
     * <code>true</code>. If this pair does not exist, return
     * <code>false</code>.
     * </p>
     *
     * @param entry
     *            Key-value pair to be removed
     * @return boolean
     *
     */
    private boolean remove(final Map.Entry entry) {
        Map.Entry actual = entry(entry.getKey());

        if (actual == null) {
            return (false);
        } else if (!entry.equals(actual)) {
            return (false);
        } else {
            remove(entry.getKey());

            return (true);
        }
    }

    /**
     * <p>
     * This method checks for following contrainsts on a key key is not null,
     * key is a String, key is not a blank string.
     * </p>
     *
     * @param key
     *            Object
     */
    private void checkKey(final Object key) {
        if (key != null) {
            if (key instanceof String) {
                if (StringUtils.isBlank((String) key)) {
                    throw new IllegalArgumentException(
                            "The input key is not valid. " + "Key should be an instance of class "
                                    + "java.lang.String and should not be blank " + "The key entered is blank");
                }
            } else {
                throw new IllegalArgumentException(
                        "The input key is not valid. " + "Key should be an instance of class "
                                + "java.lang.String and should not be blank " + "The key entered is not a String");
            }
        } else {
            throw new IllegalArgumentException(
                    "Invalid input parameter! The input key is not valid. " + "Key should be an instance of class "
                            + "java.lang.String and should not be blank " + "The key entered is null");
        }
    }

    /**
     * <p>
     * This method checks for following contrainsts on a value is not null
     * </p>
     * .
     *
     * @param value
     *            Object
     */
    private void checkValue(final Object value) {
        if (value == null) {
            throw new IllegalArgumentException("The input value is not valid. Value cannot be null. ");
        }
    }

    /**
     * <p>
     * Return an <code>Iterator</code> over the set of values in this
     * <code>Map</code>.
     * </p>
     *
     * @return Iterator
     */
    private Iterator valuesIterator() {
        return (new ValuesIterator());
    }

    /**
     * <p>
     * Set the value for the specified property.
     * </p>
     *
     * @param descriptor
     *            <code>PropertyDescriptor</code> for the specified property
     * @param value
     *            The new value for this property (must be of the correct type)
     *
     */
    private void writeProperty(final PropertyDescriptor descriptor, final Object value) {
        try {
            Method method = descriptor.getWriteMethod();

            if (method == null) {
                throw new UnsupportedOperationException("Property '" + descriptor.getName() + "' is not writeable");
            }

            method.invoke(this, new Object[] { value });
        } catch (Exception e) {
            throw new UnsupportedOperationException(
                    "Exception writing property '" + descriptor.getName() + "': " + e.getMessage());
        }
    }

    /**
     * Returns the values that are stored in the localMap.
     * 
     * @return String
     */
    @Override
    public String toString() {
        return localMap.toString();

    }

}