Class ClassCopierBase

  • All Implemented Interfaces:
    ClassCopier
    Direct Known Subclasses:
    ClassCopierOrdinaryImpl

    public abstract class ClassCopierBase
    extends java.lang.Object
    implements ClassCopier
    A convenient base class for making ClassCopier types. This takes care of checking oldToNew and updating oldToNew when an actual copy is made. All subclasses must override createCopy, which allocates a new result. In some simple cases, this is all that is needed. In the more complex cases, doCopy must also be overridden to make the actual copy.
    • Field Summary

      Fields 
      Modifier and Type Field Description
      private boolean isReflective  
      private java.lang.String name  
    • Constructor Summary

      Constructors 
      Modifier Constructor Description
      protected ClassCopierBase​(java.lang.String name)
      Pass a name here that can be used for toString, hashCode, and equals.
      protected ClassCopierBase​(java.lang.String name, boolean isReflective)  
    • Method Summary

      All Methods Instance Methods Abstract Methods Concrete Methods 
      Modifier and Type Method Description
      private java.util.HashMap cloneEmptyHashMap()  
      java.lang.Object copy​(java.util.Map<java.lang.Object,​java.lang.Object> oldToNew, java.lang.Object source)
      Make the actual copy of source, using oldToNew to preserve aliasing.
      protected abstract java.lang.Object createCopy​(java.lang.Object source)
      Create a copy of source.
      private java.lang.Object doByFieldCopy​(java.util.Map<java.lang.Object,​java.lang.Object> oldToNew, java.lang.Object source)  
      protected java.lang.Object doCopy​(java.util.Map<java.lang.Object,​java.lang.Object> oldToNew, java.lang.Object source, java.lang.Object result)
      Do the copying of data from source to result.
      private java.lang.Object doSpecialCaseCopy​(java.util.Map<java.lang.Object,​java.lang.Object> oldToNew, java.lang.Object source)
      Sometimes the internal representation of an object will be violated by our field-by-field copy.
      boolean equals​(java.lang.Object obj)  
      int hashCode()  
      private boolean isEmptyHashMap​(java.lang.Object source)
      As of JDK 1.7-40, the JDK relies on the HashMap#table field being identical to a constant.
      boolean isReflectiveClassCopier()
      We need to know whether this class copier operates via reflection or not, as the reflective class copier must be able to tell when a super class is copied by an incompatible copier.
      java.lang.String toString()  
      • Methods inherited from class java.lang.Object

        clone, finalize, getClass, notify, notifyAll, wait, wait, wait
    • Field Detail

      • name

        private java.lang.String name
      • isReflective

        private boolean isReflective
    • Constructor Detail

      • ClassCopierBase

        protected ClassCopierBase​(java.lang.String name)
        Pass a name here that can be used for toString, hashCode, and equals. All different ClassCopier classes derived from this base should have unique names.
      • ClassCopierBase

        protected ClassCopierBase​(java.lang.String name,
                                  boolean isReflective)
    • Method Detail

      • toString

        public final java.lang.String toString()
        Overrides:
        toString in class java.lang.Object
      • hashCode

        public final int hashCode()
        Overrides:
        hashCode in class java.lang.Object
      • equals

        public final boolean equals​(java.lang.Object obj)
        Overrides:
        equals in class java.lang.Object
      • copy

        public final java.lang.Object copy​(java.util.Map<java.lang.Object,​java.lang.Object> oldToNew,
                                           java.lang.Object source)
                                    throws ReflectiveCopyException
        Make the actual copy of source, using oldToNew to preserve aliasing. This first checks to see whether source has been previously copied. If so, the value obtained from oldToNew is returned. Otherwise,
        1. createCopy( source ) is called to create a new copy of source.
        2. The new copy is placed in oldToNew with source as its key.
        3. doCopy is called to complete the copy.
        This split into two phases isolates all subclasses from the need to update oldToNew. It accommodates simple cases (arrays of primitives for example) that only need to define createCopy, as well as more complex case (general objects) that must first create the copy, update oldToNew, and then do the copy, as otherwise self-references would cause infinite recursion.
        Specified by:
        copy in interface ClassCopier
        Throws:
        ReflectiveCopyException
      • doSpecialCaseCopy

        private java.lang.Object doSpecialCaseCopy​(java.util.Map<java.lang.Object,​java.lang.Object> oldToNew,
                                                   java.lang.Object source)
        Sometimes the internal representation of an object will be violated by our field-by-field copy. This method handles those special cases. It suggests that there may be a basic problem with our code logic.
        Parameters:
        oldToNew - a map of already copied objects and their corresponding copies.
        source - the object to copy.
      • isEmptyHashMap

        private boolean isEmptyHashMap​(java.lang.Object source)
        As of JDK 1.7-40, the JDK relies on the HashMap#table field being identical to a constant. That will not be true if we invoke #doByFieldCopy to copy it, so we need special processing.
        Parameters:
        source - the object to copy.
      • cloneEmptyHashMap

        private java.util.HashMap cloneEmptyHashMap()
      • doByFieldCopy

        private java.lang.Object doByFieldCopy​(java.util.Map<java.lang.Object,​java.lang.Object> oldToNew,
                                               java.lang.Object source)
      • isReflectiveClassCopier

        public boolean isReflectiveClassCopier()
        Description copied from interface: ClassCopier
        We need to know whether this class copier operates via reflection or not, as the reflective class copier must be able to tell when a super class is copied by an incompatible copier.
        Specified by:
        isReflectiveClassCopier in interface ClassCopier
      • createCopy

        protected abstract java.lang.Object createCopy​(java.lang.Object source)
                                                throws ReflectiveCopyException
        Create a copy of source. The copy may or may not be fully initialized. This method must always be overridden in a subclass.
        Throws:
        ReflectiveCopyException
      • doCopy

        protected java.lang.Object doCopy​(java.util.Map<java.lang.Object,​java.lang.Object> oldToNew,
                                          java.lang.Object source,
                                          java.lang.Object result)
                                   throws ReflectiveCopyException
        Do the copying of data from source to result. This just returns the result by default, but it may be overrideden in a subclass. When this method completes, result must be fully initialized.
        Throws:
        ReflectiveCopyException