package com.github.czyzby.uedi.impl; import com.github.czyzby.kiwi.util.common.Strings; import com.github.czyzby.uedi.Context; import com.github.czyzby.uedi.reflection.impl.MockMember; import com.github.czyzby.uedi.reflection.impl.Modifier; import com.github.czyzby.uedi.scanner.ClassScanner; import com.github.czyzby.uedi.stereotype.Factory; import com.github.czyzby.uedi.stereotype.Property; import com.github.czyzby.uedi.stereotype.Provider; import com.github.czyzby.uedi.stereotype.Singleton; /** Implements common functionalities of {@link Context} implementations. Holds preference. * * @author MJ * @see DefaultContext */ public abstract class AbstractContext implements Context { private ClassScanner classScanner; private int fieldsIgnoreFilter = Modifier.TRANSIENT | Modifier.STATIC; private int fieldsIgnoreSignature = Modifier.TRANSIENT; private int methodsIgnoreFilter = Modifier.STATIC | Modifier.NATIVE; private int methodsIgnoreSignature = Modifier.PUBLIC | Modifier.STATIC; private int iterationsAmount = 15; private boolean failIfUnknown = true; private boolean failIfAmbiguous = true; private boolean processSuperFields = true; private boolean mapSuperTypes = true; private boolean ignoreStrings; // Limits unnecessary objects creation: private final MockMember helperMember = new MockMember(Strings.EMPTY_STRING); /** @param classScanner can be null, but {@link #scan(Class)} method will not work correctly. */ public AbstractContext(final ClassScanner classScanner) { this.classScanner = classScanner; } @Override public ClassScanner getClassScanner() { return classScanner; } @Override public void setClassScanner(final ClassScanner classScanner) { this.classScanner = classScanner; } @Override public void scan(final Class<?> root) { if (classScanner == null) { throw new RuntimeException("Unable to scan root package: " + root.getName() + " without a scanner."); } processClasses(classScanner.getClassesImplementing(root, Factory.class, Property.class, Provider.class, Singleton.class)); } /** @param classes were scanned for. Should be created, initiated and processed. */ protected abstract void processClasses(Iterable<Class<?>> classes); @Override public Context initiate(final Object component) { processComponent(component); return this; } /** @param component its non-primitive, empty, non-transient fields should be injected. Must be included for * initiation and destruction if implements any life cycle interfaces. */ protected abstract void processComponent(Object component); @Override public void addProvider(final Provider<?> provider) { add(provider); processProvider(provider); } /** @param provider was registered as a provider component. Must be bound to the class tree of the supported * type. */ protected abstract void processProvider(Provider<?> provider); @Override public void addFactory(final Object factory) { add(factory); processFactory(factory); } /** @param factory was registered as a factory component. Its public methods much be converted into providers. */ protected abstract void processFactory(Object factory); @Override public <Component> Component get(final Class<Component> type) { return get(type, null, null); } @Override public <Component> Component get(final String id, final Class<Component> type) { helperMember.setName(id); return get(type, null, helperMember); } @Override public <Component> Component get(final Class<Component> type, final Object forObject) { return get(type, forObject, null); } @Override public <Component> Component getOrElse(final Class<Component> type, final Component alternative) { final Component component = get(type); return component != null ? component : alternative; } @Override public void setFailIfUnknownType(final boolean fail) { failIfUnknown = fail; } @Override public boolean isFailIfAmbiguousDependency() { return failIfAmbiguous; } @Override public void setFailIfAmbiguousDependency(final boolean fail) { failIfAmbiguous = fail; } @Override public boolean isFailIfUnknownType() { return failIfUnknown; } @Override public void setProcessSuperFields(final boolean process) { processSuperFields = process; } @Override public boolean isProcessSuperFields() { return processSuperFields; } @Override public void setMapSuperTypes(final boolean process) { mapSuperTypes = process; } @Override public boolean isMapSuperTypes() { return mapSuperTypes; } @Override public int getFieldsIgnoreFilter() { return fieldsIgnoreFilter; } @Override public void setFieldsIgnoreFilter(final int filter) { fieldsIgnoreFilter = filter; } @Override public int getFieldsIgnoreSignature() { return fieldsIgnoreSignature; } @Override public void setFieldsIgnoreSignature(final int signature) { fieldsIgnoreSignature = signature; } @Override public void setIgnoreStrings(final boolean ignore) { ignoreStrings = ignore; } @Override public boolean isIgnoreStrings() { return ignoreStrings; } @Override public void setIterationsAmount(final int iterations) { iterationsAmount = iterations; } @Override public void setMethodsIgnoreFilter(final int filter) { methodsIgnoreFilter = filter; } @Override public void setMethodsIgnoreSignature(final int signature) { methodsIgnoreSignature = signature; } @Override public int getMethodsIgnoreFilter() { return methodsIgnoreFilter; } @Override public int getMethodsIgnoreSignature() { return methodsIgnoreSignature; } @Override public int getIterationsAmount() { return iterationsAmount; } }