All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.blackbuild.klum.ast.util.KlumFactory Maven / Gradle / Ivy

There is a newer version: 2.0.0-rc.39
Show newest version
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2024 Stephan Pauxberger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.blackbuild.klum.ast.util;

import com.blackbuild.annodocimal.annotations.InlineJavadocs;
import com.blackbuild.groovy.configdsl.transform.DSL;
import groovy.lang.*;
import groovy.transform.Undefined;

import java.io.File;
import java.net.URL;
import java.util.Map;

import static com.blackbuild.klum.ast.util.DslHelper.requireDslType;
import static com.blackbuild.klum.ast.util.DslHelper.requireKeyed;

/**
 * Factory to create DSL model objects.
 * @param  The type of the DSL model object.
 */
@SuppressWarnings({"java:S100", "unused"})
@InlineJavadocs
public class KlumFactory {

    protected final Class type;
    protected KlumFactory(Class type) {
        requireDslType(type);
        this.type = getTypeOrDefaultType(type);
    }

    private Class getTypeOrDefaultType(Class type) {
        DSL annotation = type.getAnnotation(DSL.class);
        Class defaultImpl = annotation.defaultImpl();
        //noinspection unchecked - already verified via CheckDslDefaultImpl
        return defaultImpl.equals(Undefined.class) ? type : (Class) defaultImpl;
    }

    /**
     * Creates a new instance of this owner's model type by reading the script from a well-defined properties file
     * placed in '/META-INF/klum-model/"schema-classname".properties'. The properties file must contain a property name
     * "model-class" which contains the name of the compiled script to run, which must return an instance of the
     * model class.
     * @see #From(Class)
     * @return The created model object.
     */
    public T FromClasspath() {
        return FactoryHelper.createFromClasspath(type);
    }

    /**
     * Creates a new instance of this owner's model type by reading the script from a well-defined properties file
     * placed in '/META-INF/klum-model/"schema-classname".properties'. The properties file must contain a property name
     * "model-class" which contains the name of the compiled script to run, which must return an instance of the
     * model class.
     * @see #From(Class)
     * @param loader The classloader to use to load the properties file.
     * @return The created model object.
     */
    public T FromClasspath(ClassLoader loader) {
        return FactoryHelper.createFromClasspath(type, loader);
    }

    /**
     * Creates a new instance of the model type by running the given script class. The script must either return an
     * instance of the model (i.e. contain something like 'MyClass.Create.With {...}') or must be a {@link groovy.util.DelegatingScript}
     * whose contents are the same as create/apply closure for this model class.
     * 

* Note that in case of a Keyed object in combination with a DelegatingScript, the simple name of the script class * is used as key. * @param configurationScript The script class to run. * @return The instantiated object. */ public T From(Class configurationScript) { return FactoryHelper.createFrom(type, configurationScript); } /** * Creates a new instance of the model type by instantiating the class and applying the text content of the * given url to it. In case of a keyed model, the last part of the URL is used as the key. * @param configurationUrl The URL where to take the configuration text from. * @see #From(URL, ClassLoader) * @return The instantiated object. */ public T From(URL configurationUrl) { return From(configurationUrl, null); } /** * Creates a new instance of the model type by instantiating the class and applying the text content of the * given url to it. In case of a keyed model, the last part of the URL is used as the key. * @param configurationUrl The URL where to take the configuration text from. * @param loader The classloader to use for compiling the configuration text. * @return The instantiated object. */ public T From(URL configurationUrl, ClassLoader loader) { return FactoryHelper.createFrom(type, configurationUrl, loader); } /** * Creates a new instance of the model type by instantiating the class and applying the text content of the * given file to it. In case of a keyed model, the filename is used as the key. * @param configurationFile The file where to take the configuration text from. * @see #From(File, ClassLoader) ) * @return The instantiated object. */ public T From(File configurationFile) { return From(configurationFile, null); } /** * Creates a new instance of the model type by instantiating the class and applying the text content of the * given file to it. In case of a keyed model, the filename is used as the key. * @param configurationFile The file where to take the configuration text from. * @param loader The classloader to use for compiling the configuration text. * @return The instantiated object. */ public T From(File configurationFile, ClassLoader loader) { return FactoryHelper.createFrom(type, configurationFile, loader); } /** * Creates a template instance of the model type. *

* Templates differ from regular instances in the following way: *

*
    *
  • Template instances can even be created for abstract model classes using a synthetic subclass
  • *
  • the key of a template model is always null
  • *
  • owner fields are not set
  • *
  • post-apply methods are not called
  • *
* * @see #Template(Map, Closure) * @return a template instance of the model type. */ public T Template() { return Template(null, null); } /** * Creates a template instance of the model type. *

* Templates differ from regular instances in the following way: *

*
    *
  • Template instances can even be created for abstract model classes using a synthetic subclass
  • *
  • the key of a template model is always null
  • *
  • owner fields are not set
  • *
  • post-apply methods are not called
  • *
* * @see #Template(Map, Closure) * @param configuration The closure to apply to the template instance. * @return a template instance of the model type. */ public T Template(Closure configuration) { return Template(null, configuration); } /** * Creates a template instance of the model type. *

* Templates differ from regular instances in the following way: *

*
    *
  • Template instances can even be created for abstract model classes using a synthetic subclass
  • *
  • the key of a template model is always null
  • *
  • owner fields are not set
  • *
  • post-apply methods are not called
  • *
* * @see #Template(Map, Closure) * @param configMap The values to set on the template instance. * @return a template instance of the model type. */ public T Template(Map configMap) { return Template(configMap, null); } /** * Creates a template instance of the model type. *

* Templates differ from regular instances in the following way: *

*
    *
  • Template instances can even be created for abstract model classes using a synthetic subclass
  • *
  • the key of a template model is always null
  • *
  • owner fields are not set
  • *
  • post-apply methods are not called
  • *
* * @param configMap The values to set on the template instance. * @param configuration The closure to apply to the template instance. * @return a template instance of the model type. */ public T Template(Map configMap, Closure configuration) { return FactoryHelper.createAsTemplate(type, configMap, configuration); } /** * Creates a template instance of the model type by applying the given text as configuration. *

* As with {@link #From(File)}, * the file is converted into a DelegatingScript which is then executed to create the model instance. * Templates differ from regular instances in the following way: *

*
    *
  • Template instances can even be created for abstract model classes using a synthetic subclass
  • *
  • the key of a template model is always null
  • *
  • owner fields are not set
  • *
  • post-apply methods are not called
  • *
* @param scriptFile The script to configure the template * @return a template instance of the model type. */ public T TemplateFrom(File scriptFile) { return TemplateFrom(scriptFile, null); } /** * Creates a template instance of the model type by applying the given text as configuration. *

* As with {@link #From(File)}, * the file is converted into a DelegatingScript which is then executed to create the model instance. * Templates differ from regular instances in the following way: *

*
    *
  • Template instances can even be created for abstract model classes using a synthetic subclass
  • *
  • the key of a template model is always null
  • *
  • owner fields are not set
  • *
  • post-apply methods are not called
  • *
* * @param scriptFile The script to configure the template * @param loader The classloader to use for compiling the configuration script. * @return a template instance of the model type. */ public T TemplateFrom(File scriptFile, ClassLoader loader) { return FactoryHelper.createAsTemplate(type, scriptFile, loader); } /** * Creates a template instance of the model type by applying the given text as configuration. *

* As with {@link #From(File)}, * the file is converted into a DelegatingScript which is then executed to create the model instance. * Templates differ from regular instances in the following way: *

*
    *
  • Template instances can even be created for abstract model classes using a synthetic subclass
  • *
  • the key of a template model is always null
  • *
  • owner fields are not set
  • *
  • post-apply methods are not called
  • *
* @param scriptUrl The script to configure the template * @return a template instance of the model type. */ public T TemplateFrom(URL scriptUrl) { return TemplateFrom(scriptUrl, null); } /** * Creates a template instance of the model type by applying the given text as configuration. *

* As with {@link #From(File)}, * the file is converted into a DelegatingScript which is then executed to create the model instance. * Templates differ from regular instances in the following way: *

*
    *
  • Template instances can even be created for abstract model classes using a synthetic subclass
  • *
  • the key of a template model is always null
  • *
  • owner fields are not set
  • *
  • post-apply methods are not called
  • *
* * @param scriptUrl The script to configure the template * @param loader The classloader to use for compiling the configuration script. * @return a template instance of the model type. */ public T TemplateFrom(URL scriptUrl, ClassLoader loader) { return FactoryHelper.createAsTemplate(type, scriptUrl, loader); } /** * Factory for keyed models. * @param The type of the model. */ @SuppressWarnings("java:S100") public abstract static class Keyed extends KlumFactory { protected Keyed(Class type) { super(requireKeyed(type)); } /** * Creates a new instance of the model by only setting the key, but not applying any configuration (apart from * 'postCreate' and 'postApply' methods). * @param key The key to use for the model. * @return The instantiated object. */ public T One(String key) { return With(null, key, null); } /** * Convenience methods to allow simply replacing 'X.create' with 'X.Create.With' in scripts, without * checking for arguments. This means that empty create calls like 'X.create("bla")' will correctly work afterward. * @param key The key to use for the model * @return The instantiated object. * @deprecated Use {@link #One(String)} instead. */ @Deprecated public T With(String key) { return With(null, key, null); } /** * Creates a new instance of the model with the given key and applying the given configuration closure. * @param key The key to use for the model. * @param configuration The configuration closure to apply to the model. * @return The instantiated object. */ public T With(String key, Closure configuration) { return With(null, key, configuration); } /** * Creates a new instance of the model with the given key and applying the given configuration map. * @param configMap The configuration map to apply to the model. * @param key The key to use for the model. * @return The instantiated object. */ public T With(Map configMap, String key) { return With(configMap, key, null); } /** * Creates a new instance of the model with the given key and applying the given configuration map and closure. * @param configMap The configuration map to apply to the model. * @param key The key to use for the model. * @param configuration The configuration closure to apply to the model. * @return The instantiated object. */ public T With(Map configMap, String key, Closure configuration) { return FactoryHelper.create(type, configMap, key, configuration); } /** * Creates a new instance of the model with the given key and then applying the given text as configuration. * @param key The key of the model to create. * @param configuration the configuration text to apply to the model. * @return The instantiated object. */ public T From(String key, String configuration) { return From(key, configuration, null); } /** * Creates a new instance of the model with the given key and then applying the given text as configuration. * @param key The key of the model to create. * @param configuration the configuration text to apply to the model. * @param loader The classloader used to compile the configuration text. * @return The instantiated object. */ public T From(String key, String configuration, ClassLoader loader) { return FactoryHelper.createFrom(type, key, configuration, loader); } } /** * Factory for unkeyed models. * @param The type of the model. */ @SuppressWarnings("java:S100") public abstract static class Unkeyed extends KlumFactory { protected Unkeyed(Class type) { super(DslHelper.requireNotKeyed(type)); } /** * Creates a new instance of the model applying any configuration (apart from * 'postCreate' and 'postApply' methods and any active templates). * @return The instantiated object. */ public T One() { return With(null, null); } /** * Convenience methods to allow simply replacing 'X.create' with 'X.Create.With' in scripts, without * checking for arguments. This means that emtpy create calls like 'X.create()' will correctly work afterwards. * @deprecated Use {@link #One()} instead. */ @Deprecated public T With() { return One(); } /** * Creates a new instance of the model applying the given configuration closure. * @param configuration The configuration closure to apply to the model. * @return The instantiated object. */ public T With(Closure configuration) { return With(null, configuration); } /** * Creates a new instance of the model applying the given configuration map. * @param configMap The configuration map to apply to the model. * @return The instantiated object. */ public T With(Map configMap) { return With(configMap, null); } /** * Creates a new instance of the model applying the given configuration map and closure. * @param configMap The configuration map to apply to the model. * @param configuration The configuration closure to apply to the model. * @return The instantiated object. */ public T With(Map configMap, Closure configuration) { return FactoryHelper.create(type, configMap, null, configuration); } /** * Creates a new instance of the model and then applying the given text as configuration. * @param configuration the configuration text to apply to the model. * @return The instantiated object. */ public T From(String configuration) { return From(configuration, null); } /** * Creates a new instance of the model and then applying the given text as configuration. * @param configuration the configuration text to apply to the model. * @param loader The classloader used to compile the configuration text. * @return The instantiated object. */ public T From(String configuration, ClassLoader loader) { return FactoryHelper.createFrom(type, null, configuration, loader); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy