Class Installable<T>
- Type Parameters:
T
- the type of object to store
- All Implemented Interfaces:
Supplier<T>
When an object is an asset that is costly to initialize, for instance because it requires data to be computed by a complex algorithm, it may be advantageous to have the initial data precomputed and load it from persistent storage, thus trading space for startup time. However, the successful initialization then requires the precomputed data to be actually available as a loadable resource.
This class functions as a wrapper to such a costly-to-initialize asset object, which can either load precomputed data or transparently fall back to procedural construction.
Usage (Run Time)
Instead of creating an object explicitly during initialization,
class Owner { static final Asset myAsset = createCostlyAsset(); }
… the initialization can be delegated to a new Installable
wrapper
object with enough metadata to choose between deserialization and creation:
class Owner { static final Installable<Asset> myAsset = new Installable<Asset>(Owner.class, Asset.class, "myAsset", () -> createCostlyAsset()); }
The actual asset object can be retrieved later via Supplier.get()
.
Installation (Build Time)
During application build time, a data file with the serialized asset object can be created and written someplace:
myAsset.store(myGeneratedFilesDirectory);
The file name is determined by the given metadata, see getResourceName()
. The file can then be placed in the class path
of the application being built, thus making the serialized object available
at run time. Note that the code of the owner class is shared between both
phases.
The process can be automated for all accessible static fields of a class:
Installable.storeAllStaticFields(myGeneratedFilesDirectory, false, Owner.class);
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic class
A simple command line interface application for writing data files. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final String
The separator between the class name and simple name of a resource. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionget()
Returns the stored object.Returns the resource name for the stored object.void
Writes the stored object to a file.static void
storeAllStaticFields
(File targetDirectory, boolean deep, Class<?> ownerClass) Writes all appropriate static fields of a class to files.
-
Field Details
-
resourceSeparator
The separator between the class name and simple name of a resource.- See Also:
-
-
Constructor Details
-
Installable
public Installable(Class<?> ownerClass, Class<? extends T> valueClass, String name, Supplier<? extends T> creator) Creates a new instance.An attempt is made to load the serialized object as a resource. If that fails, the object is created newly.
The resource given name, localized to an owner class, is used to try and obtain a data file via
Class.getResource(java.lang.String)
. The file should contain a single serialized object graph written viaObjectOutput.writeObject(java.lang.Object)
, which is then deserialized. All usual caveats apply.If deserialization succeeds, the deserialized object is stored. Otherwise, the given function object is invoked to create the object from scratch.
- Parameters:
ownerClass
- the class that owns the stored object and the resourcevalueClass
- the type of the stored objectname
- the simple name of the object and resource; must be a valid Java identifiercreator
- a function object to create the object on the fly- Throws:
IllegalArgumentException
- ifname
is not a valid Java identifierRuntimeException
- ifcreator
is invoked and throws an exception
-
-
Method Details
-
get
Returns the stored object.Invoking this method does not cause the object to be created or loaded (that happens during constructor invocation). The identical object is returned every time this method is invoked.
-
getResourceName
Returns the resource name for the stored object.The resource name is always of the form c
+
s+
n, where c is the unqualified name of the owner class, s is the value ofresourceSeparator
, and n is the unqualified name of the resource.The stored object will be loaded from the named resource file if possible.
- Returns:
- a string containing the resource name for the stored object
-
store
Writes the stored object to a file.The relative file name is the resource name for the stored object.
To install the file as a resource, place it in the classpath beside the owner class.
- Parameters:
targetDirectory
- the target directory- Throws:
IOException
- if the object file cannot be written- See Also:
-
storeAllStaticFields
public static void storeAllStaticFields(File targetDirectory, boolean deep, Class<?> ownerClass) throws IOException Writes all appropriate static fields of a class to files.All accessible static fields of type
Installable
of the given owner class are queried via reflection, and processed withstore(java.io.File)
.Exceptions that arise from reflection are silently caught, and the concerned field is omitted. By contrast,
IOException
s that arise from writing are not caught.- Parameters:
targetDirectory
- the target directorydeep
- iftrue
, turn the package prefix of the owner class into subdirectories which must exist already; iffalse
, store files in target directory directlyownerClass
- the owner class- Throws:
IOException
- if some object file cannot be written
-