coherence/lang/Immutable.hpp

00001 /*
00002 * Immutable.hpp
00003 *
00004 * Copyright 2001-2008 by Oracle. All rights reserved.
00005 *
00006 * Oracle is a registered trademarks of Oracle Corporation and/or its
00007 * affiliates.
00008 *
00009 * This software is the confidential and proprietary information of Oracle
00010 * Corporation. You shall not disclose such confidential and proprietary
00011 * information and shall use it only in accordance with the terms of the
00012 * license agreement you entered into with Oracle.
00013 *
00014 * This notice may not be removed or altered.
00015 */
00016 #ifndef COH_IMMUTABLE_HPP
00017 #define COH_IMMUTABLE_HPP
00018 
00019 #include "coherence/lang/compatibility.hpp"
00020 
00021 #include "coherence/lang/IllegalArgumentException.hpp"
00022 #include "coherence/lang/Object.hpp"
00023 #include "coherence/lang/TypedHandle.hpp"
00024 
00025 #include <sstream>
00026 
00027 COH_OPEN_NAMESPACE2(coherence,lang)
00028 
00029 
00030 /**
00031 * A Handle implementation which upon assignment ensures that it will
00032 * reference an immutable Object. If the passed Object is immutable
00033 * (as defined by Object::isImmutable()) then the handle simply holds a const
00034 * pointer to the Object. If the passed Object is not immutable, then a clone
00035 * attempt is made, and held via a const pointer.  If the supplied Object is
00036 * not immutable and not cloneable then assignment will fail with a
00037 * CloneNotSupport exception.
00038 *
00039 * @author mf  2007.07.05
00040 */
00041 template<class T>
00042 class Immutable
00043     : public TypedHandle<const T>
00044     {
00045     // ----- constructors ---------------------------------------------------
00046 
00047     public:
00048         /**
00049         * Construct a @c NULL handle.
00050         */
00051         Immutable()
00052                 : TypedHandle<const T>()
00053             {
00054             }
00055 
00056         /**
00057         * Construct an Immutable handle to the given Object.
00058         *
00059         * @param po the pointer to the Object to reference
00060         */
00061         Immutable(const T* po)
00062                 : TypedHandle<const T>()
00063             {
00064             set(po);
00065             }
00066 
00067         /**
00068         * Construct an Immutable handle from another Handle
00069         *
00070         * @param h another handle
00071         */
00072         template<class O> Immutable<T>(const TypedHandle<O>& h)
00073                 : TypedHandle<const T>()
00074             {
00075             set(get_pointer(h));
00076             }
00077 
00078         /**
00079         * Construct an Immutable handle from another Handle
00080         *
00081         * @param h another handle
00082         */
00083         Immutable<T>(const Immutable<T>& h)
00084                 : TypedHandle<const T>()
00085             {
00086             set(h.get());
00087             }
00088 
00089         /**
00090         * Destruct the handle
00091         */
00092         ~Immutable()
00093             {
00094             }
00095 
00096 
00097     // ----- helper methods -------------------------------------------------
00098 
00099     protected:
00100 
00101         /**
00102         * Set this handle to point to immutable version of the given object,
00103         * or unset the handle.
00104         *
00105         * If the given pointer points to the immutable object, then this
00106         * handle will point it. If the given pointer points to the mutable
00107         * object, then this handle will point to the clone of that object.
00108         * If the given pointer is NULL, then this handle will point to no
00109         * object.
00110         */
00111         Immutable<T>& set(const T* cpo)
00112             {
00113             if (cpo == NULL || cpo->isImmutable())
00114                 {
00115                 TypedHandle<const T>::set(cpo);
00116                 }
00117             else
00118                 {
00119                 Object::View vClone;
00120                     {
00121                     // With the Sun compiler the temporary handle created
00122                     // here will live for the duration of the surrounding
00123                     // scope, we must pop the scope to ensure that the
00124                     // temporary handle is destroyed/detached, so the
00125                     // immutability check can pass
00126                     vClone = cpo->clone();
00127                     }
00128                 if (NULL == vClone || !vClone->isImmutable())
00129                     {
00130                     COH_THROW_STREAM(IllegalArgumentException,
00131                         "Object of type '" << typeid(*cpo).name() <<
00132                         "' cannot be made immutable through cloneing.");
00133                     }
00134                 TypedHandle<const T>::set(get_pointer(
00135                         cast<typename T::View>(vClone)));
00136                 }
00137             return *this;
00138             }
00139     };
00140 
00141 /**
00142 * Return an immutable version of the supplied Object. If the supplied view
00143 * does not refer to an immutable Object, then a clone of the orginal Object
00144 * is returned.
00145 *
00146 * @param v  view to the Object to return an immutable copy of
00147 *
00148 * @return a view to an immutable version of the supplied Object, or the
00149 *         supplied Object if it was already immutable
00150 */
00151 template<class T> typename T::View immutable_view(const typename T::View& v)
00152     {
00153     return Immutable<T>(v);
00154     }
00155 
00156 COH_CLOSE_NAMESPACE2
00157 
00158 #endif // COH_IMMUTABLE_HPP
Copyright (c) 2000-2008 Oracle. All rights reserved.