Class TypeBuilder<CDP_TYPE extends BaseType<CDP_TYPE>>

  • Type Parameters:
    CDP_TYPE - The CDP data type produced by this builder's build() method.
    All Implemented Interfaces:
    java.io.Serializable, java.lang.Cloneable

    public class TypeBuilder<CDP_TYPE extends BaseType<CDP_TYPE>>
    extends AbstractBuilder<CDP_TYPE>
    implements java.io.Serializable, java.lang.Cloneable
    A 'Builder' software design pattern that may be used to construct instances of any of the nested domain types & classes in CDP. The goal of this class is to make it easier to construct instances of CDP types that have many, many fields. Although it is perfectly legal to invoke the constructor of any CDP data type directly, a class with only 2 or 3 fields won't provide any benefit above and beyond using the constructor of the class.

    ⚠️ Only classes with "lots and lots" of fields will benefit from using the 'TypeBuilder' design pattern!

    Included below are example uses of the class TypeBuilder

    Example:
    // ChatGPT says that "JSESSIONID" and "sessionId" are two of the more common
    // "Cookies" used inside a browser
    
    final Network.CookieParam cookie = TypeBuilder
        .builder(Network.CookieParam.descriptor())
        .accept("name",  "JSESSIONID")
        .accept("value", "4F8A2C91B6E2D77F1A0B32C9E8A5D1F4")
        .build();
    
    final Network.CookieParam cookie = TypeBuilder
        .builder(Network.CookieParam.descriptor())
        .accept("name",  "sessionId")
        .accept("value", "abc123xyz789")
        .build();
    

    Notice that the above example only assigns values to two fields in class Network.CookieParam. Thus, the other twelve optional fields in that class will be automatically assigned null when TypeBuilder.build() is finally called.

    📌 The primary purpose of class TypeBuilder is to eliminate messy, cumbersome & arduous constructor invocations for domain types that contain many optional fields.

    The code snippet below shows what "life would be like" instantiating the same exact CDP type (having many optional fields), using that class's constructor instead!

    // Creating an instance of class 'Network.CookieParam', using the constructor
    
    final Network.CookieParam cookie = new Network.CookieParam(
        null,                               // ReadOnlyList<Boolean> isPresent,
        "JSESSIONID",                       // String name,
        "4F8A2C91B6E2D77F1A0B32C9E8A5D1F",  // String value,
    
        // All 'optional' fields, but these must be included in the constructor invocation!
        null, // String url,
        null, // String domain,
        null, // String path,
        null, // Boolean secure,
        null, // Boolean httpOnly,
        null, // String sameSite,
        null, // Number expires, 
        null, // String priority,
        null, // Boolean sameParty,
        null, // String sourceScheme,
        null, // Integer sourcePort,
        null, // Network.CookiePartitionKey partitionKey  
    );
    
    See Also:
    NestedDescriptor, NestedHelper.descriptor(), Serialized Form


    • Field Detail

      • serialVersionUID

        🡇     🗕  🗗  🗖
        protected static final long serialVersionUID
        This fulfils the SerialVersion UID requirement for all classes that implement Java's interface java.io.Serializable. Using the Serializable Implementation offered by java is very easy, and can make saving program state when debugging a lot easier. It can also be used in place of more complicated systems like "hibernate" to store data as well.
        See Also:
        Constant Field Values
        Code:
        Exact Field Declaration Expression:
         protected static final long serialVersionUID = 1L;
        
    • Method Detail

      • builder

        🡅  🡇     🗕  🗗  🗖
        public static <T extends BaseType<T>> TypeBuilder<T> builder​
                    (NestedDescriptor<T> descriptor)
        
        Creates a new builder, ready to accept field assignments.
        Type Parameters:
        T - This is the object type, or 'class' which you would like to have built by this TypeBuilder.
        Parameters:
        descriptor - The singleton descriptor for the CDP data type being built. Retrieving a descriptor is as easy as invoking descriptor() on any CDP data type.
        Returns:
        a new builder instance of this class
        See Also:
        NestedHelper.descriptor()
        Code:
        Exact Method Body:
         java.util.Objects.requireNonNull(descriptor, "parameter 'descriptor' is null");
         return new TypeBuilder<>(descriptor);
        
      • witherBuilder

        🡅  🡇     🗕  🗗  🗖
        public static <T extends BaseType<T>> TypeBuilder<T> witherBuilder​
                    (NestedDescriptor<T> descriptor,
                     BaseType<T> bt)
        
        This creates a new builder, but initializes it with an actual object instance
        Type Parameters:
        T - The 'BaseType' class.
        Parameters:
        descriptor - descriptor of the CDP data carrier class being constructed
        bt - instance of the CDP data carrier class, used to populate the builder
        Returns:
        a 'TypeBuilder', initialized with the values in 'bt'
        See Also:
        NestedHelper.descriptor()
        Code:
        Exact Method Body:
         java.util.Objects.requireNonNull(descriptor, "parameter 'descriptor' is null");
         java.util.Objects.requireNonNull(bt, "parameter 'bt' is null");
        
         if (! descriptor.baseTypeClass.isInstance(bt)) throw new IllegalArgumentException
             ("'bt' is not an instance of " + descriptor.baseTypeClass.getCanonicalName());
        
         final TypeBuilder<T>        tb          = new TypeBuilder<>(descriptor);
         final ReadOnlyList<Boolean> isPresent   = bt.isPresent();
        
         for (int i=0; i < descriptor.size; i++) if (isPresent.get(i))
         {
             tb.assigned[i] = true;
        
             try
             {
                 tb.assignments[i] = descriptor
                     .baseTypeClass
                     .getField(descriptor.names.get(i))
                     .get(bt);
             }
        
             catch (NoSuchFieldException | SecurityException | IllegalAccessException e)
             {
                 throw new TypeBuilderError(
                     "Could not extract field [" + descriptor.names.get(i) + "] from instance of " +
                     descriptor.baseTypeClass.getCanonicalName(),
                     e
                 );
             }
         }
        
         return tb;
        
      • clone

        🡅     🗕  🗗  🗖
        public TypeBuilder<CDP_TYPEclone()
        Clone the current instance
        Specified by:
        clone in class AbstractBuilder<CDP_TYPE extends BaseType<CDP_TYPE>>
        Returns:
        An identical copy of 'this'.

        🔍 The concept known as a "Deep Clone" means that the internals of a type are also copied to the new instance. What is returned by this method is a "Partial Deep Clone" of 'this' instance.

        🧠 Since the internal 'descriptor' instance is a read only, singleton instance, cloning it wouldn't have any real significance. Thus, the internal 'descriptor' isn't cloned into the new instance; its reference is merely copied instead.

        🎯 However, the two internal value-assignment arrays are cloned, resulting in a separate instance which has its own, independent assignments.
        Code:
        Exact Method Body:
         return new TypeBuilder<>(this);