2020public final class PicoFactory implements ObjectFactory {
2121
2222 private final Set <Class <?>> classes = new HashSet <>();
23+ private final Set <Class <Provider >> providers = new HashSet <>();
2324 private MutablePicoContainer pico ;
2425
2526 private static boolean isInstantiable (Class <?> clazz ) {
@@ -35,23 +36,18 @@ public void start() {
3536 .withCaching ()
3637 .withLifecycle ()
3738 .build ();
38- Set <Class <?>> providers = new HashSet <>();
3939 Set <Class <?>> providedClasses = new HashSet <>();
40- for (Class <?> clazz : classes ) {
41- if (isProvider (clazz )) {
42- providers .add (clazz );
43- ProviderAdapter adapter = adapterForProviderClass (clazz );
44- pico .addAdapter (adapter );
45- providedClasses .add (adapter .getComponentImplementation ());
46- }
40+ for (Class <Provider > clazz : providers ) {
41+ ProviderAdapter adapter = adapterForProviderClass (clazz );
42+ pico .addAdapter (adapter );
43+ providedClasses .add (adapter .getComponentImplementation ());
4744 }
4845 for (Class <?> clazz : classes ) {
49- // do not add the classes that represent a picocontainer
50- // Provider, and also do not add those raw classes that are
51- // already provided (otherwise this causes exceptional
52- // situations, e.g. PicoCompositionException with message
53- // "Duplicate Keys not allowed. Duplicate for 'class XXX'")
54- if (!providers .contains (clazz ) && !providedClasses .contains (clazz )) {
46+ // do not add classes that are already provided (otherwise this
47+ // causes exceptional situations, e.g. PicoCompositionException
48+ // with message "Duplicate Keys not allowed. Duplicate for
49+ // 'class XXX'")
50+ if (!providedClasses .contains (clazz )) {
5551 pico .addComponent (clazz );
5652 }
5753 }
@@ -69,6 +65,10 @@ public void start() {
6965 pico .start ();
7066 }
7167
68+ static boolean hasCucumberPicoProvider (Class <?> clazz ) {
69+ return clazz .isAnnotationPresent (CucumberPicoProvider .class );
70+ }
71+
7272 static boolean isProvider (Class <?> clazz ) {
7373 return Provider .class .isAssignableFrom (clazz );
7474 }
@@ -77,9 +77,9 @@ static boolean isProviderAdapter(Class<?> clazz) {
7777 return ProviderAdapter .class .isAssignableFrom (clazz );
7878 }
7979
80- private static ProviderAdapter adapterForProviderClass (Class <? > clazz ) {
80+ private static ProviderAdapter adapterForProviderClass (Class <Provider > clazz ) {
8181 try {
82- Provider provider = ( Provider ) clazz .getDeclaredConstructor ().newInstance ();
82+ Provider provider = clazz .getDeclaredConstructor ().newInstance ();
8383 return isProviderAdapter (clazz ) ? (ProviderAdapter ) provider : new ProviderAdapter (provider );
8484 } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException | PicoException e ) {
8585 throw new CucumberBackendException (e .getMessage (), e );
@@ -96,9 +96,12 @@ public void stop() {
9696
9797 @ Override
9898 public boolean addClass (Class <?> clazz ) {
99- checkMeaningfulPicoAnnotation (clazz );
100- if (isInstantiable (clazz ) && classes .add (clazz )) {
101- addConstructorDependencies (clazz );
99+ if (hasCucumberPicoProvider (clazz )) {
100+ providers .add (checkProperPicoProvider (clazz ));
101+ } else {
102+ if (isInstantiable (clazz ) && classes .add (clazz )) {
103+ addConstructorDependencies (clazz );
104+ }
102105 }
103106 return true ;
104107 }
@@ -112,19 +115,19 @@ private static boolean hasDefaultConstructor(Class<?> clazz) {
112115 return false ;
113116 }
114117
115- private static void checkMeaningfulPicoAnnotation (Class <?> clazz ) {
116- if (clazz .isAnnotationPresent (CucumberPicoProvider .class )) {
117- if (!isProvider (clazz ) || !hasDefaultConstructor (clazz )) {
118- throw new CucumberBackendException (String .format ("" +
119- "Glue class %1$s was annotated with @CucumberPicoProvider; marking it as a candidate for declaring a"
120- +
121- "PicoContainer Provider instance. Please ensure that all the following requirements are satisfied:\n "
122- +
123- "1) the class implements org.picocontainer.injectors.Provider\n " +
124- "2) the class provides a default constructor." ,
125- clazz .getName ()));
126- }
118+ @ SuppressWarnings ("unchecked" )
119+ private static Class <Provider > checkProperPicoProvider (Class <?> clazz ) {
120+ if (!isProvider (clazz ) || !hasDefaultConstructor (clazz )) {
121+ throw new CucumberBackendException (String .format ("" +
122+ "Glue class %1$s was annotated with @CucumberPicoProvider; marking it as a candidate for declaring a"
123+ +
124+ "PicoContainer Provider instance. Please ensure that all the following requirements are satisfied:\n "
125+ +
126+ "1) the class implements org.picocontainer.injectors.Provider\n " +
127+ "2) the class provides a default constructor." ,
128+ clazz .getName ()));
127129 }
130+ return (Class <Provider >) clazz ;
128131 }
129132
130133 @ Override
0 commit comments