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