1+ package com .dicontainer ;
2+
3+ import java .io .IOException ;
4+ import java .lang .reflect .Constructor ;
5+ import java .nio .file .Files ;
6+ import java .nio .file .Path ;
7+ import java .util .Map ;
8+
9+ import org .reflections .Reflections ;
10+
11+ import com .dicontainer .annotations .Dependency ;
12+ import com .dicontainer .annotations .ToInject ;
13+ import com .google .gson .Gson ;
14+ import com .google .gson .GsonBuilder ;
15+
16+ import lombok .Getter ;
17+ import lombok .Setter ;
18+
19+ public class Container {
20+
21+ private static Container INSTANCE ;
22+ public static final String CONFIG_FILE = "dicontainer.config" ;
23+ private static final Gson GSON = new Gson ();
24+ private static final GsonBuilder GSON_BUILDER = new GsonBuilder ();
25+ // Interface -> dependency
26+ private Map <Class , DependencyToInject > dependenciesToInjectByInterface ;
27+ private Map <Class , Constructor > constructorsToInject ;
28+ private Map <Class , Constructor > dependenciesConstructor ;
29+ private Reflections reflections = new Reflections ();
30+ private ConfigHolder configHolder ;
31+
32+ //procurar classe, procurar metodo com @toinject annotation
33+ static {
34+ GSON_BUILDER .setPrettyPrinting ();
35+ //public <T> T fromJson(String json, Class<T> classOfT)
36+ }
37+
38+ private class ConfigHolder {
39+ //interface -> class
40+ private Map <String , String > config ;
41+ }
42+
43+ @ Getter @ Setter
44+ private class DependencyToInject <T > {
45+ private Constructor <T > constructorToCall ; //Constructor of the dependency to call.
46+ private Class <T > dependencyClass ; //Class to be instantiated.
47+ private String annotatedValue ; //Value of the Dependency annotation.
48+
49+ public DependencyToInject (Constructor <T > constructor , Class <T > clazz , String annotation ) {
50+ constructorToCall = constructor ;
51+ dependencyClass = clazz ;
52+ annotatedValue = annotation ;
53+ }
54+
55+ public T instantiate () {
56+ T instance = null ;
57+ try {
58+ instance = constructorToCall .newInstance ();
59+ } catch (Exception e ) {
60+
61+ }
62+ return instance ;
63+ }
64+ }
65+
66+ private Container () {
67+ //loadConfig();
68+ loadDependencies ();
69+ loadConstructorsToInject ();
70+ }
71+
72+ private Constructor <?> getConstructorToInstantiateDependency (Class <?> dependency ) {
73+ for (Constructor <?> constructor : dependency .getConstructors ()) {
74+ if (constructor .getDeclaredAnnotation (ToInject .class ) != null )
75+ return constructor ;
76+ }
77+ return null ;
78+ }
79+
80+ private <V > void loadDependencies () {
81+ for (Class <?> clazz : reflections .getTypesAnnotatedWith (Dependency .class )) {
82+ Constructor <?> constructorToCall = getConstructorToInstantiateDependency (clazz );
83+ String annotatedValue = clazz .getDeclaredAnnotation (Dependency .class ).to ();
84+ Class referredInterface ;
85+ try {
86+ referredInterface = Class .forName (annotatedValue );
87+ } catch (Exception e ) {
88+ continue ;
89+ }
90+ test (constructorToCall , clazz , annotatedValue );
91+ dependenciesToInjectByInterface .put (referredInterface , new DependencyToInject (constructorToCall , clazz , annotatedValue ));
92+ }
93+ }
94+
95+ // Test if it can work
96+ private <V > void test (Constructor <V > a , Class <V > b , String c ) {
97+ DependencyToInject a = new DependencyToInject <V >(a , b , c );
98+ }
99+
100+ private void loadConstructorsToInject () {
101+ for (Constructor <?> constructor : reflections .getConstructorsAnnotatedWith (ToInject .class )) {
102+ constructorsToInject .put (constructor .getClass (), constructor );
103+ }
104+ }
105+
106+ private void loadConfig () {
107+ String fileContent = null ;
108+ try {
109+ fileContent = getFileContent (CONFIG_FILE );
110+ } catch (IOException e ) {
111+ //throw e;
112+ }
113+ configHolder = GSON .fromJson (fileContent , ConfigHolder .class );
114+ }
115+
116+ private String getFileContent (String filename ) throws IOException {
117+ Path filePath = Path .of (filename );
118+ return Files .readString (filePath );
119+ }
120+
121+ private synchronized static Container getInstance () {
122+ if (INSTANCE == null )
123+ INSTANCE = new Container ();
124+ return INSTANCE ;
125+ }
126+
127+ public Object getNewInstanceFor (Class dependencyReceiver ) throws Exception {
128+ if (dependenciesToInjectByInterface .containsKey (dependencyReceiver )) {
129+ DependencyToInject toInject = dependenciesToInjectByInterface .get (dependencyReceiver );
130+ return toInject .getConstructorToCall ().invoke (dependenciesToInjectByInterface .get (dependencyReceiver ), (Object []) null );
131+ }
132+ return null ;
133+ }
134+
135+ public static Object getInstanceFor (Class classToInstatiate ) throws Exception
136+ {
137+ return Container .getInstance ().getNewInstanceFor (classToInstatiate );
138+ }
139+ }
0 commit comments