{"id":37021487,"url":"https://github.com/antkudruk/uniformfactory","last_synced_at":"2026-01-14T02:32:31.573Z","repository":{"id":37026002,"uuid":"277545091","full_name":"antkudruk/uniformfactory","owner":"antkudruk","description":"Uniform Factory implements an Adapter pattern based on Reflection information. Normally, it generates adapters based on annotations. For each target class, it implements the common wrapper interface.","archived":false,"fork":false,"pushed_at":"2023-04-01T09:34:28.000Z","size":871,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2023-06-30T12:01:01.075Z","etag":null,"topics":["annotation-processor","annotations","bytebuddy","bytecode","bytecode-manipulation","gradle-plugin","java","members-annotated","reflection","wrapper-interface"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/antkudruk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-06T13:10:26.000Z","updated_at":"2021-12-17T18:49:04.000Z","dependencies_parsed_at":"2023-02-09T23:45:57.320Z","dependency_job_id":null,"html_url":"https://github.com/antkudruk/uniformfactory","commit_stats":null,"previous_names":[],"tags_count":4,"template":null,"template_full_name":null,"purl":"pkg:github/antkudruk/uniformfactory","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antkudruk%2Funiformfactory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antkudruk%2Funiformfactory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antkudruk%2Funiformfactory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antkudruk%2Funiformfactory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/antkudruk","download_url":"https://codeload.github.com/antkudruk/uniformfactory/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antkudruk%2Funiformfactory/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["annotation-processor","annotations","bytebuddy","bytecode","bytecode-manipulation","gradle-plugin","java","members-annotated","reflection","wrapper-interface"],"created_at":"2026-01-14T02:32:31.081Z","updated_at":"2026-01-14T02:32:31.563Z","avatar_url":"https://github.com/antkudruk.png","language":"Java","readme":"# Library for Generating Adapters Based On Annotations in Java\n**UniformFactory** is a\n[Java library to generate adapters (wrappers) based on reflection](https://github.com/antkudruk/uniformfactory).\nAdapters are classes implementing a common interface to manipulate different\nclasses the common way.\n\nIn the **Uniform Factory** library, we're using the term **wrapper**\nto denote adapter class.\n\n## Why do you Need to Generate Adapters in Java?\n\nSupposing you define some annotations to mark arbitrary class members with.\nThe classes may have different structure.\nYou even may be not aware of the classes structure if you publish your\nfunctionality as a framework to share it with other developers. The task is\njust to process the annotated class members.\n\nThe common way of doing that is to look through annotated class members each\ntime you use them, find them and process. However, that approach is too\ncumbersome. It's slow as well because reflective operations are too expensive.\n\nYou'd like to process the annotated members more convenient way.\n\n**Uniform Factory** allows you just to define a common interface for the classes.\nWe'll call the interface **wrapper interface**. Then you let\n**Uniform Factory** automatically generate an implementation of that interface\nfor each **origin** class. Then you can access annotated members using the\ncommon wrapper interface regardless of a class structure.\n\n**Uniform Factory** works at the bytecode level. Thus, it's significantly faster\nthan iteration over class members to look for the annotated members.\n\nLet's consider the following example.\n\nYou defined `@Label` annotation to mark a member to identify an\nobject. And you defined `@Propery` annotation to mark an objects named\nproperties. You don't know the **origin** classes structure. One of the\n**origin** classes may look like in the following listing:\n\n```\n@Marker\nclass OriginImpl {\n    @Label\n    private String name;\n    \n    @Property('width')\n    private long width;\n    \n    @Property('height')\n    public long getHeight() {\n        // ...\n    }\n}\n```      \n\n**First**, you should define the following interfaces to generate wrapper\nimplementations from:\n\n* **Wrapper** interface. It's a common interface to generate the wrapper\n  classes from. A wrapper class is generated for each Origin class.\n* **Functional** interfaces. As soon as in this example you define an\n  annotation to apply to multiple class members annotated with the same\n  annotation, you have to define a functional interface to access each\n  member.\n\n```\n// Your wrapper interface\ninterface Wrapper {\n    String getName();\n    Map\u003cString, Property\u003e getProperties();\n}\n\n// Your functional interface.\ninterface Property {\n    Object get();\n}\n```\n\n**Second**, you should perform some settings of Uniform Factory. \nOn this step, you should decide how you're doing to use **UniformFactory** and\nset it up. You can find some explanations with examples further.\n\n**After applying Uniform Factory**, you can operate the annotated members the\nfollowing way.\n\n1. Get the wrapper for the **origin** object. Depending on whe way you're using\n   UniformFactory, il may look the following:\n   \n   * **Way 1**: Using Maven/Gradle plugin:   \n    ```\n    Wrapper wrapper = ((Origin)origin).getWrapper();// get the wrapper built with UniformFactory\n    ```\n   * **Way 2**: Using factory (doesn't require Maven/Gradle plugin)\n    ```\n    Wrapper wrapper = wrapperFactory.get(origin);// get the wrapper built with UniformFactory\n    ```\n2. Operate with the wrapper\n    ```\n    wrapper.getName();\n    Property widthProperty = wrapper.getProperties().get(\"width\");\n    widthProperty.get();\n    ```\n\n## Setting up ClassFactory\n\nAn instance of **ClassFactory** allows you to create adapters for a needed \ntype.\n\n## Ways to Use Uniform Factory\n\nYou can use Uniform Factory two ways:\n* As a Maven/Gradle plugin\n* Using an object factory. This way doesn't require any plugin\n\n|                                       | Using Maven/Gradle plugin | Using object factory |\n|---------------------------------------|---------------------------|----------------------|\n| Works without applying plugin         | -                         | +                    |\n| Origin has a reference to its Wrapper | +                         | -                    |\n\n### Using Object Factory\n\nYou can create an instance of object factory.\n\n```\nWrapperFactory\u003cWrapper\u003e wrapperFactory = classFactory.buildWrapperFactory(); \n```\n\nAfter that, you can create an adapter instance for each object:\n\n```\nWrapper wrapper = wrapperFactory.get(yourObject);\n```\n\nThis method doesn't require applying Maven/Gradle plugin. That makes it easier\nto debug. However, UniformFactory can't change loaded classes format, and \ntherefore, can't introduce a reference to the wrapper into the origin object.\n\nSee example for using Object Factory option \n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-12-wrapper-factory)\n\n### Using Maven/Gradle plugin\n\nMaven/Gradle plugin get applied before a class gets loaded. Thus, Maven/Gradle \nplugin allows adding fields to the classes (e. g. a reference to the Adapter object) \n\nThe plugin does the following:\n\n* Makes the class implement `Origin` interface.\n* Created the *wrapper* property and assigns it with the needed adapter implementation\n\nFor instance, this class\n\n```\n@Marker\nclass Origin {\n    //\n    // Annotated class members are defined here\n    //\n}\n```\n\nbecomes transformed to this one\n\n```\n@Marker\nclass Origin implements OriginInterface {\n    //\n    // Annotated class members are defined here\n    // \n    \n    private WrapperInterface wrapper = new Wrapper();\n    \n    @Override\n    public WrapperInterface getWrapper() {\n        return wrapper;\n    }\n}\n```\n\nThe following tutorial describes how to set up **Uniform Factory** to generate\nwrapper classes properly.\n\n### Notes on testing\n\nIt's difficult to test Maven/Gradle plugin. However, both Plugin and Wrapper \nFactory use the common classes to generate adapters. Thus, even if you chose \nPlugin option, you still can test the generated wrapper without applying a \nplugin.\n\nJust use the method `buildWrapperFactory` in your unit test in the Plugin:\n(example from the example [Custom method list](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-4-2-custom-method-list))\n```\n        // when\n        Function\u003cOrigin1, ? extends Wrapper\u003e meta = testSubject.generateMetaClass(Origin1.class);\n        Wrapper w = meta.apply(origin);\n```\n\n## Installing Uniform Factory Into Your Project\n\nYou can download **Uniform Factory** into your project from Maven Central.\n\nHere is an example for Gradle:\n\n```\ndependencies {\n   compile group: 'com.github.antkudruk', name: 'uniform-factory', version: '0.6.5'\n}\n```\n\nand for Maven:\n\n```\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.antkudruk\u003c/groupId\u003e\n    \u003cartifactId\u003euniform-factory\u003c/artifactId\u003e\n    \u003cversion\u003e0.6.5\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nIf you choose to apply **Uniform Factory** with ByteBuddy Gradle Plugin, just import and apply  \n`byte-buddy-gradle-plugin` and specify your plugin class.\n\nHere is an example for Gradle:\n\n```\nplugins {\n    id 'java'\n    id \"net.bytebuddy.byte-buddy-gradle-plugin\" version \"1.12.18\"\n}\n\nbyteBuddy {\n    transformation {\n        plugin = // Specify reference to your plugin class here, see the next chapter\n    }\n}\n```\n\nand in Maven:\n\n```\n    \u003cplugin\u003e\n        \u003cgroupId\u003enet.bytebuddy\u003c/groupId\u003e\n        \u003cartifactId\u003ebyte-buddy-maven-plugin\u003c/artifactId\u003e\n        \u003cversion\u003e1.12.18\u003c/version\u003e\n        \u003cexecutions\u003e\n            \u003cexecution\u003e\n                \u003cgoals\u003e\n                    \u003cgoal\u003etransform\u003c/goal\u003e\n                \u003c/goals\u003e\n            \u003c/execution\u003e\n        \u003c/executions\u003e\n        \u003cconfiguration\u003e\n            \u003ctransformations\u003e\n                \u003ctransformation\u003e\n                    \u003cplugin\u003e\u003c!-- Specify your plugin class reference here --\u003e\u003c/plugin\u003e\n                \u003c/transformation\u003e\n            \u003c/transformations\u003e\n        \u003c/configuration\u003e\n    \u003c/plugin\u003e\n```\n\nLet's take a look at some examples.\n\n## Examples\n\nYou can find compilable \n[example](https://github.com/antkudruk/uniformfactory/tree/develop/examples)\nfolder of this project.\n\n### Empty Adapter\n\nHere is an example of an empty wrapper. Empty wrapper is an interface that\ndoesn't define any methods. Even though an empty wrapper is practically useless,\nit's a good point to start.\n\nThis plugin example adds an empty wrapper to an object satisfying a\nspecial criteria. Furthermore, the plugin makes these object implement\nthe `Origin` interface. Thus, you can access the wrapper the following way:\n\n```\nObject origin = new OriginImpl();\nWrapper wrapper = ((Origin)origin).getWrapper();\n```\n\nYou can find th whole compilable example that implements an empty wrapper\n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-1-1-test)\n\n### Using Explicit Interface as an Adapter\n\nYon can avoid class cast from the previous example. To do it, your domain class\nshould implement the `Origin` interface. If you mark `Origin` interface with\nthe `@Marker` annotation, the standard **Uniform Factory** plugin is going to\nadd the wrapper into this domain class:\n\n```\n@Marker\npublic interface Origin {\n    default Wrapper getWrapper() {\n        throw new RuntimeException(\"Wrapper method hasn't been implemented.\");\n    }\n}\n```\n\nYou can find an example of an explicit interface\n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-1-2-interface-inherited)\n\n### Select Type Criteria\n\nYou may specify custom criteria to choose classes to add adapters to. For\nexample, matching class names to a special regular expression.\n**UniformFactory** provides a flexible way to select particular classes for\nthat.\n\nLet's implement a plugin to add wrappers to methods that explicitly implement\nthe `Origin` interface, but using custom class selection criteria.\n\n```\npublic class PluginImpl extends WrapperPlugin\u003cWrapper\u003e {\n    public PluginImpl() {\n        super(\n                Origin.class,\n                Wrapper.class,\n                // Class selection criteria\n                td -\u003e td.getInterfaces()\n                        .stream()\n                        .map(TypeDefinition::asErasure)\n                        .anyMatch(new TypeDescription.ForLoadedType(Origin.class)::equals),\n                \"examplePlugin\",\n                ClassFactoryGeneratorImpl.class);\n    }\n}\n```\n\nSee compilable code\n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-1-3-custom-select-type-criteria)\n\n### Using Abstract Class as an Adapter\n\nInterfaces are stateless. So you can't have any variables inside interfaces.\n\nBut what if you'd like to store a state in your wrapper? For instance,\nyou have to make a cache in your wrapper.\n\nYou can use a **wrapper** class instead of an interface.\n\nLet's consider an example. Your wrapper hs an accumulator. And the\naccumulator increases by a number from an underlying object. It happens\neach time you get the accumulator value.\n\n```\npublic abstract class Wrapper {\n\n    private int accumulator;\n\n    public int getAccumulated() {\n        return accumulator += getDelta();\n    }\n\n    public abstract int getDelta();\n}\n\n``` \n\nNote that the abstract class **must be public**.\n\nYou can use that kind of wrapper exactly the same way as for the\ninterface case. See compilable exampless and detailed description\n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-8-wrapper-class)\n\n## Generate Adapter that Implements Method Singleton\n\nLet's enhance our empty `Wrapper` class.\n\nSupposing we need to mark different class members to provide an object\nidentity, just like in the following listing:\n\n```\n@Marker\npublic class Origin1 {\n    @Identity\n    private Long number = 10L;\n}\n\n@Marker\npublic class Origin2 {\n    @Identity\n    public String getName() {\n        return \"name\";\n    }\n}\n``` \n\nWe need the common interface to get these identities:\n\n```\n    public interface Wrapper {\n        String getId();\n    }\n```\n\nHow can we achieve this behaviour with **UniformFactory**?\nYou can find a compilable example\n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-3-method-singleton)\n\n### Application: Tree\n\nLet's consider an example.\nSupposing we have the following structure of objects:\n\n* Company\n* Department\n* Employee\n\nEach class has a method returning nested object. And each object has a label\nstring to render. We'd like to make a uniform tree structure to use by UI to\nrender.\n\n```\n// Wrapper interface\npublic interface TreeElement {\n    String getLabel();\n    List\u003cHasTreeElement\u003e nested();\n}\n\n// Origin interface\npublic interface HasTreeElement {\n    TreeElement getTreeElement();\n}\n``` \n\nYou can find an example of a tree\n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-2-tree-example)\n\n## Generate Wrappers that Provides List Of Methods\n\nWe'd like to be able to mark multiple class members with an annotation and\nwork with them. How can we do that?\n\nWe can define the common interface containing the method:\n\n```\npublic interface Processor {\n\n    @Retention(RetentionPolicy.RUNTIME)\n    @Target({ElementType.METHOD, ElementType.FIELD})\n    @interface Process {\n\n    }\n\n    boolean process(String eventName);\n}\n```\n\nThen we make our `Wrapper` interface return an element of that functional interface:\n\n```\npublic interface Wrapper {\n    List\u003cProcessor\u003e getProcessors();\n}\n```\n\nYou can find a compilable example here:\n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-4-2-custom-method-list)\n\n## Custom MetaclassGenerator to Generate Wrappers in Java\n\nIn the previous examples we used only default implementation\n`DefaultMetaClassFactory`, implementing interface `MetaClassFactory`.\n`MetaClassFactory` instance is a singleton per application.\n\nSupposing, in the previous task we'd like to store a link to each object\n\nLet's define custom `MetaClassFactory`.\n\n```\npublic class ClassFactoryGeneratorImpl implements MetaClassFactory\u003cWrapper\u003e {\n\n    private final ClassFactory\u003cWrapper\u003e classFactory;\n\n    public ClassFactoryGeneratorImpl() throws NoSuchMethodException {\n        this.classFactory = new ClassFactory.Builder\u003c\u003e(Wrapper.class)\n                .addMethodList(\n                        Wrapper.class.getMethod(\"getProcessors\"),\n                        boolean.class\n                )\n                .setMarkerAnnotation(Processor.Process.class)\n                .setFunctionalInterface(Processor.class)\n\n                .addResultTranslator(void.class, t -\u003e true)\n                .addResultTranslator(Long.class, t -\u003e t \u003e= 0)\n                .addResultTranslator(String.class, \"yes\"::equalsIgnoreCase)\n                .addResultTranslator(Boolean.class, t -\u003e t)\n\n                .parameterSource(String.class, 0)\n                .applyTo(new AnyParameterFilter())\n                .addTranslator(Integer.class, Integer::parseInt)\n                .finishParameterDescription()\n\n                .endMethodDescription()\n\n                .build();\n    }\n\n    @Override\n    public \u003cO\u003e Function\u003cO, ? extends Wrapper\u003e generateMetaClass(Class\u003cO\u003e originClass) {\n        try {\n            Constructor\u003c? extends Wrapper\u003e wrapperConstructor = classFactory\n                    .build(new TypeDescription.ForLoadedType(originClass))\n                    .load(DefaultMetaClassFactory.class.getClassLoader())\n                    .getLoaded()\n                    .getConstructor(originClass);\n\n            return new WrapperObjectGenerator\u003c\u003e(wrapperConstructor);\n        } catch (ClassGeneratorException | NoSuchMethodException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public static class WrapperObjectGenerator\u003cO\u003e extends DefaultMetaClassFactory.WrapperObjectGenerator\u003cO, Wrapper\u003e {\n\n        WrapperObjectGenerator(Constructor\u003c? extends Wrapper\u003e wrapperConstructor) {\n            super(wrapperConstructor);\n        }\n\n        @Override\n        public Wrapper apply(O t) {\n            Wrapper w = super.apply(t);\n            CallableObjectsRegistry.INSTANCE.addObject(w);\n            return w;\n        }\n    }\n}\n```\n\nIt's a good practice to move event notification functionality to a separate\nclass (named `CallableObjectsRegistry` for instance). Let's implement it.\n\n```\npublic class CallableObjectsRegistry {\n\n    public static final CallableObjectsRegistry INSTANCE = new CallableObjectsRegistry();\n\n    private final WeakHashMap\u003cWrapper, Object\u003e object = new WeakHashMap\u003c\u003e();\n\n    void addObject(Wrapper wrapper) {\n        object.put(wrapper, null);\n    }\n\n    public boolean call(String eventName) {\n        return object.keySet().stream()\n                .map(Wrapper::getProcessors)\n                .flatMap(Collection::stream)\n                .map(t -\u003e t.process(eventName))\n                .reduce(true, (a, b) -\u003e a \u0026 b );\n    }\n}\n``` \n\nIn case you're not familiar with Weak References, in a nutshell\n`java.util.WeakHashMap` allows to store references as keys and avoid holding\nobjects in the memory after all the hard references to the objects are removed.\n\nYou can call `assertTrue(CallableObjectsRegistry.INSTANCE.call(EVENT_TYPE_STRING));`\nto trigger the events and cause event handler methods to be invoked..\n\nAfter that you can define classes processing\n\n```\n@Marker\npublic class Origin2 {\n\n    private final Function\u003cString, String\u003e consumerString;\n    private final Function\u003cInteger, Boolean\u003e consumerInteger;\n\n    public Origin2(Function\u003cString, String\u003e consumerString, Function\u003cInteger, Boolean\u003e consumerInteger) {\n        this.consumerString = consumerString;\n        this.consumerInteger = consumerInteger;\n    }\n\n    @Processor.Process\n    public String processString(String event) {\n        return consumerString.apply(event);\n    }\n\n    @Processor.Process\n    public Boolean processInteger(Integer event) {\n        return consumerInteger.apply(event);\n    }\n}\n```\n\n## Generate Adapters with Map of Methods\n\nIn the previous example, we just took all annotated class members. But what if\nwe'd like to use some additional information?\n\nWe can use a map instead of a list. UniformFactory takes keys from the\nannotation parameters and generate values implementing functional interface:\n\n```\npublic interface Coordinate {\n    long getCoordinate(Long scale);\n}\n\npublic interface PointWrapper {\n    Map\u003cString, Coordinate\u003e getCoords();\n}\n```\n\nYou can find a compilable example\n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-6-method-map)\n\n### Using Multiple Wrappers\n\n**Uniform Factory** can generate multiple wrappers for one object.\n\nWhere it may be convenient?\n\nAdapters generated by **UniformFactory** are stateless. But what if you're going to\nenhance your objects with state? For instance, with cache.\n\nYou can use two wrappers:\n* An adapter generated by **Uniform Factory**\n* Your cache object that works with the adapter\n\nThe example of code for multiple adapters at one origin class may be found\n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-9-multiple-wrappers)\n\n### Setting up a Field in the Origin Class\n\nYou can do setting up the field marked with an annotation exactly the same way\nas MethodSingleton does. \nSee the example \n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-10-setter)\n\n### Setting up Multiple Fields\n\nUniformFactory may implement adapters for multiple fields in the origin class\nfor you. See the example \n[here](https://github.com/antkudruk/uniformfactory/tree/develop/examples/listing-11-setter-map)\n\n### Translating parameters and result\n\n#### Translating result\n\nLet's take a look at the following example.\nWe have a wrapper containing two methods. Both methods return the same type\nand consume the same types, like in the following example.\n\n```\npublic interface Wrapper {\n    String processFirst(Integer scale);\n    String processSecond(Integer scale);\n}\n```\n\nTo follow DRY (Don't Repeat Yourself) principle, it's better to use the common\nresult and parameter translators to avoid adding them twice. `setResultMapper`\nand `setMapper` methods will help you to use specified mappers.\n\n```\npublic class ClassFactoryGeneratorImpl extends DefaultMetaClassFactory\u003cWrapper\u003e {\n\n    private static ParameterMappersCollection\u003cInteger\u003e parameterMapper = new ParameterMappersCollection\u003c\u003e(Integer.class)\n            .add(new TypeDescription.ForLoadedType(String.class), Object::toString)\n            .add(new TypeDescription.ForLoadedType(Long.class), Integer::longValue);\n\n    private static ResultMapperCollection\u003cString\u003e resultMapperCollection = new ResultMapperCollection\u003c\u003e(String.class)\n            .addMapper(Long.class, Object::toString)\n            .addMapper(int.class, Object::toString);\n\n    public ClassFactoryGeneratorImpl() throws NoSuchMethodException {\n        super(new ClassFactory.Builder\u003c\u003e(Wrapper.class)\n\n                .addMethodSingleton(FirstMethodMarker.class, Wrapper.class.getMethod(\"process\", Integer.class), String.class)\n                .setResultMapper(resultMapperCollection)\n                .parameterSource(Integer.class, 0)\n                .applyTo(new AnyParameterFilter())\n                .setMapper(parameterMapper)\n                .finishParameterDescription()\n                .endMethodDescription()\n\n                .addMethodSingleton(SecondMethodMarker.class, Wrapper.class.getMethod(\"processSecond\", Integer.class), String.class)\n                .setResultMapper(resultMapperCollection)\n                .parameterSource(Integer.class, 0)\n                .applyTo(new AnyParameterFilter())\n                .setMapper(parameterMapper)\n                .finishParameterDescription()\n                .endMethodDescription()\n\n                .build());\n    }\n}\n\n```\n\n## History\n\n| version | Description                                                       |\n|---------|-------------------------------------------------------------------|\n| 0.2.2   | Added pure ByteBuddy implementation                               |\n| 0.3.0   | Gave up builder experiments                                       |\n| 0.4.0   | Added an opportunity to implement custom method map               |\n| 0.4.1   | Clean up exceptions                                               |\n| 0.5.1   | Allowed subclasses in element factories. Cleaned up method        |\n|         | collections                                                       |\n| 0.5.2   | Cleaned up messages in some exceptions.                           |\n|         | Cleaned up method descriptors and builders from spare properties. |\n| 0.5.3   | Small cleanup                                                     |\n| 0.6.0   | Fixed bug for parameter mapper super types.                       |\n|         | Added automated boxing of primitives.                             |\n|         | Got rid of default translators in children mappers                |\n| 0.6.1   | Fixed a bug in selecting parameter by type                        |\n| 0.6.2   | Verbose a non-intuitive  message 'Invisible return type interface |\n|         | Enabled getOrigin method in any Wrapper interface                 |\n| 0.6.3   | Enabled multiple lists in the same wrapper and multiple maps in   | \n|         | the same wrapper                                                  |\n| 0.6.4   | Modification of DynamicType.Builder in the pure ByteBuddy         |\n|         | implementation (e. g. adding required dynamic types)              |\n|         | Added required dynamic types to typeConstant BbImplementation     |\n| 0.6.5   | Enhanced adapters creating without Maven or Gradle plugin         | \n\n## License\n\n```\nCopyright 2020 - Present Anton Kudruk\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantkudruk%2Funiformfactory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fantkudruk%2Funiformfactory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantkudruk%2Funiformfactory/lists"}