Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.e6tech.elements.common.resources.ResourcesState Maven / Gradle / Ivy
/*
* Copyright 2015-2019 Futeh Kao
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.e6tech.elements.common.resources;
import net.e6tech.elements.common.inject.Injector;
import net.e6tech.elements.common.inject.Module;
import net.e6tech.elements.common.inject.ModuleFactory;
import net.e6tech.elements.common.util.SystemException;
import java.util.*;
import java.util.concurrent.Callable;
/**
* Created by futeh.
*/
@SuppressWarnings("unchecked")
class ResourcesState {
private static final List emptyResourceProviders = Collections.unmodifiableList(new ArrayList<>());
enum State {
INITIAL,
OPEN,
COMMITTED,
ABORTED,
}
private static final String CLASS_MSG = "Class ";
private static final String BOUND_TO_MSG = " is already bound to ";
private ModuleFactory factory;
private Module module;
protected Injector injector;
protected Injector parentInjector;
private State state = State.INITIAL;
private List resourceProviders = new LinkedList<>();
private LinkedList injectionList = new LinkedList<>();
private List externalResourceProviders;
private Map variables;
ResourcesState(Resources resources) {
factory = resources.getResourceManager().getModule().getFactory();
module = factory.create();
}
protected void cleanup() {
module = factory.create();
resourceProviders.clear();
state = State.INITIAL;
injectionList.clear();
injector = null;
externalResourceProviders = null;
}
public Module getModule() {
return module;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public List getResourceProviders() {
return resourceProviders;
}
public void setResourceProviders(List resourceProviders) {
this.resourceProviders = resourceProviders;
}
List getExternalResourceProviders() {
if (externalResourceProviders == null)
return emptyResourceProviders;
return externalResourceProviders;
}
void setExternalResourceProviders(List externalResourceProviders) {
this.externalResourceProviders = externalResourceProviders;
}
public void addModule(Module module) {
this.module.add(module);
}
protected void onOpen(Resources resources) {
if (!injectionList.isEmpty()) {
createInjector(resources, true);
}
}
protected Injector createInjector(Resources resources, boolean strict) {
if (injector == null || !injectionList.isEmpty()) {
injector = (resources.getResourceManager() != null) ?
getModule().build(resources.getResourceManager().getModule())
: getModule().build();
// we need to inject here for objects awaiting to be injected because
// resourceProviders may depend on these objects.
while (!injectionList.isEmpty()) {
// need to remove item because it may make resources dirty again calling bind or rebind. In such a case
// onOpen will be call again.
Object obj = injectionList.remove();
privateInject(resources, injector, obj, strict);
}
}
return injector;
}
public T inject(Resources resources, T object) {
return inject(resources, object, true);
}
public T inject(Resources resources, T object, boolean strict) {
if (object == null)
return object;
if (state == State.INITIAL) {
// to be injected when resources is opened.
injectionList.add(object);
} else {
createInjector(resources, strict);
privateInject(resources, injector, object, strict);
}
return object;
}
protected void privateInject(Resources resources, Injector injector, Object object, boolean strict) {
if (object instanceof InjectionListener) {
((InjectionListener) object).preInject(resources);
}
boolean completed;
try {
completed = injector.inject(object, strict);
} catch (Exception ex) {
if (parentInjector != null) {
completed = parentInjector.inject(object, strict);
} else {
throw ex;
}
}
if (object instanceof InjectionListener) {
if (strict || completed)
((InjectionListener) object).injected(resources);
}
}
public T tryBind(Class cls, Callable callable) {
T o = getModule().getBoundInstance(cls);
if (o != null)
return o;
T instance = null;
try {
instance = (T) getModule().bindInstance(cls, callable.call());
} catch (Exception e) {
throw new SystemException(e);
}
return instance;
}
public T bind(Class cls, T resource) {
Object o = getModule().getBoundInstance(cls);
if (o != null)
throw new AlreadyBoundException(CLASS_MSG + cls + BOUND_TO_MSG + o);
return (T) getModule().bindInstance(cls, resource);
}
public T rebind(Class cls, T resource) {
T instance = null;
try {
instance = (T) getModule().rebindInstance(cls, resource);
} catch (Exception e) {
throw new SystemException(e);
}
return instance;
}
public T unbind(Class cls) {
T instance = null;
try {
instance = (T) getModule().unbindInstance(cls);
} catch (Exception e) {
throw new SystemException(e);
}
return instance;
}
public void bindClass(Class cls, Class service) {
Class c = getModule().getBoundClass(cls);
if (c != null)
throw new AlreadyBoundException(CLASS_MSG + cls + BOUND_TO_MSG + c);
if (service != null)
getModule().bindClass(cls, service);
else getModule().bindInstance(cls, null);
}
public T bindNamedInstance(Class cls, String name, T resource) {
Object o = getModule().getBoundNamedInstance(cls, name);
if (o != null)
throw new AlreadyBoundException(CLASS_MSG + cls + BOUND_TO_MSG + o);
return rebindNamedInstance(cls, name, resource);
}
public T rebindNamedInstance(Class cls, String name, T resource) {
return (T) getModule().rebindNamedInstance(cls, name, resource);
}
public T getNamedInstance(Resources resources, Class cls, String name) {
T instance = null;
if (state == State.INITIAL) {
if (getModule().getBoundNamedInstance(cls, name) != null)
instance = getModule().getBoundNamedInstance(cls, name);
else if (resources.getResourceManager().getModule().getBoundNamedInstance(cls, name) != null)
instance = resources.getResourceManager().getModule().getBoundNamedInstance(cls, name);
} else {
instance = createInjector(resources, true).getNamedInstance(cls, name);
}
if (instance == null) {
throw new InstanceNotFoundException("No instance for class " + cls.getName() +
". Use newInstance if you meant to create an instance.");
}
return instance;
}
public boolean hasInstance(Resources resources, Class cls) {
if (cls.isAssignableFrom(Resources.class) || cls.isAssignableFrom(ResourceManager.class))
return true;
return getModule().getBoundInstance(cls) != null || resources.getResourceManager().hasInstance(cls);
}
public T getInstance(Resources resources, Class cls) {
if (cls.isAssignableFrom(Resources.class)) {
return (T) resources;
} else if (cls.isAssignableFrom(ResourceManager.class)) {
return (T) resources.getResourceManager();
}
T instance = null;
if (state == State.INITIAL) {
if (getModule().getBoundInstance(cls) != null)
instance = getModule().getBoundInstance(cls);
else if (resources.getResourceManager().hasInstance(cls))
instance = resources.getResourceManager().getInstance(cls);
} else {
instance = createInjector(resources, true).getInstance(cls);
}
if (instance == null) {
throw new InstanceNotFoundException("No instance for class " + cls.getName() +
". Use newInstance if you meant to create an instance.");
}
return instance;
}
@SuppressWarnings("unchecked")
public Optional getVariable(String key) {
if (variables == null)
return Optional.empty();
T t = (T) variables.get(key);
return Optional.ofNullable(t);
}
public void setVariable(String key, Object val) {
if (variables == null)
variables = new HashMap<>();
variables.put(key, val);
}
public Map computeMapIfAbsent(Class key) {
if (variables == null)
variables = new HashMap<>();
return (Map) variables.computeIfAbsent(key.toString(), k -> new LinkedHashMap<>());
}
public Injector getParentInjector() {
return parentInjector;
}
public void setParentInjector(Injector parentInjector) {
this.parentInjector = parentInjector;
}
}