added persiJ-minimal

This commit is contained in:
Raybz@Raybz 2013-05-16 13:20:05 +02:00
parent 6eabb15f07
commit c3f05530da
5 changed files with 523 additions and 0 deletions

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2012 Darth Affe <http://wyrez.org> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.wyrez.persij;
/**
* Exception thrown by the PersiJConstructor
*
* @author Darth Affe
*/
public class NoSuitableConstructorFoundException extends Exception {
NoSuitableConstructorFoundException() {
}
NoSuitableConstructorFoundException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2012 Darth Affe <http://wyrez.org> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.wyrez.persij;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks an Constructor for primary use by the PersiJConstructor
*
* @author Darth Affe
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CONSTRUCTOR)
public @interface PersiJConstructor {
/**
* Returns the default state of the annotation
*
* @return true if default; false otherwise
*/
boolean isDefault();
/**
* Returns the id of the param mapping
*
* @return id of the param mapping
*/
int customParamMappingId() default -1;
}

View File

@ -0,0 +1,172 @@
/*
* Copyright (C) 2012 Darth Affe <http://wyrez.org> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.wyrez.persij;
import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Mapping and object container for PersiJ
*
* @author Darth Affe
*/
public final class PersiJContainer {
private static final Logger logger = Logger.getLogger("org.wyrez.persij");
private final HashMap<Class, PersiJMapping> mappings = new HashMap<Class, PersiJMapping>();
public PersiJContainer() {
registerSingleton(PersiJContainer.class, this);
}
/**
* Registers a mapping
*
* @param type Type which should be mapped
*/
public final <T> void registerType(Class<T> type) {
registerType(type, false);
}
/**
* Registers a mapping
*
* @param type Type which should be mapped
* @param singleton Singleton indicator
*/
public final <T> void registerType(Class<T> type, boolean singleton) {
registerType(type, type, singleton);
}
/**
* Registers a mapping
*
* @param type Source-type which should be mapped
* @param mapping Target-type which should be mapped
*/
public final <T> void registerType(Class<T> type, Class<? extends T> mapping) {
registerType(type, mapping, false);
}
/**
* Registers a mapping
*
* @param type Source-type which should be mapped
* @param mapping Target-type which should be mapped
* @param singleton Singleton indicator
*/
public final <T> void registerType(Class<T> type, Class<? extends T> mapping, boolean singleton) {
mappings.put(type, new PersiJMapping(mapping, singleton));
}
/**
* Registers a singleton-mapping to an existing object
*
* @param type Source-type which should be mapped
* @param instance Singleton instance
*/
public final <T> void registerSingleton(Class<T> type, T instance) {
mappings.put(type, new PersiJMapping(type, instance));
}
/**
* Tests if the specified type is registered
*
* @param type Type which should be tested
* @return true if the type is registered; else otherwise
*/
public final boolean isTypeRegistered(Class type) {
return mappings.containsKey(type);
}
/**
* Creates an instance of the type mapped to the given type
*
* @param <T> Type to resolve
* @param type Class of the type to resolve
* @return Insance of T
*/
public final <T> T resolve(Class<T> type) {
PersiJMapping mapping = mappings.get(type);
if (mapping != null) {
try {
return (T) mapping.getInstance(this, null);
} catch (NoSuitableConstructorFoundException ex) {
logger.log(Level.WARNING, "Can't create object for type: "
+ type.getName(), ex);
return null;
}
} else {
logger.log(Level.WARNING, "Can't find a mapping for type: "
+ type.getName());
return null;
}
}
/**
* Creates an instance of the type mapped to the given type
*
* @param <T> Type to resolve
* @param type Class of the type to resolve
* @param paramMapping
* @return Instance of T
*/
public final <T> T resolve(Class<T> type, PersiJParamMapping paramMapping) {
PersiJMapping mapping = mappings.get(type);
if (mapping != null) {
try {
return (T) mapping.getInstance(this, paramMapping);
} catch (NoSuitableConstructorFoundException ex) {
logger.log(Level.WARNING, "Can't create object for type: "
+ type.getName(), ex);
return null;
}
} else {
logger.log(Level.WARNING, "Can't find a mapping for type: "
+ type.getName());
return null;
}
}
/**
* Creates an array with instances of the type mapped to the given type
*
* @param <T> Type to resolve
* @param type Class of the type to resolve
* @param number Size of the array
* @return Array of T
*/
public final <T> T[] resolve(Class<T> type, int number) {
PersiJMapping mapping = mappings.get(type);
if (mapping != null) {
try {
T[] array = (T[]) Array.newInstance(type, number);
return (T[]) mapping.getInstances(this, null, array);
} catch (NoSuitableConstructorFoundException ex) {
logger.log(Level.WARNING, "Can't create object for type: "
+ type.getName(), ex);
return null;
}
} else {
logger.log(Level.WARNING, "Can't find a mapping for type: "
+ type.getName());
return null;
}
}
}

View File

@ -0,0 +1,208 @@
/*
* Copyright (C) 2012 Darth Affe <http://wyrez.org> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.wyrez.persij;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Darth Affe
*/
final class PersiJMapping {
private static final Logger logger = Logger.getLogger("org.wyrez.persij");
private Object singletonInstance;
private Class type;
private boolean singleton;
PersiJMapping(Class type, boolean singleton) {
this.type = type;
this.singleton = singleton;
}
PersiJMapping(Class type, Object singleton) {
this.type = type;
this.singleton = true;
singletonInstance = singleton;
}
final boolean isSingleton() {
return singleton;
}
/**
* Creates a new instance
*
* @param container Container to resolve missing dependencies
* @param paramMapping Optional parameters used to resolve dependencies
* (null if not used)
* @return New instance
* @throws NoSuitableConstructorFoundException thrown if no suitable
* constructor to instantiate could be found
*/
final Object getInstance(PersiJContainer container, PersiJParamMapping paramMapping) throws NoSuitableConstructorFoundException {
if (isSingleton()) {
if (singletonInstance == null) {
singletonInstance = createInstance(container, paramMapping);
}
return singletonInstance;
} else {
return createInstance(container, paramMapping);
}
}
/**
* Creates an array with new instances
*
* @param container Container to resolve missing dependencies
* @param paramMapping Optional parameters used to resolve dependencies
* (null if not used)
* @param array Array which should be filled and returned
* @return New array with instances
* @throws NoSuitableConstructorFoundException thrown if no suitable
* constructor to instantiate could be found
*/
final Object getInstances(PersiJContainer container, PersiJParamMapping paramMapping, Object[] array) throws NoSuitableConstructorFoundException {
if (isSingleton()) {
if (singletonInstance == null) {
singletonInstance = createInstance(container, paramMapping);
}
for (int i = 0; i < array.length; i++) {
array[i] = singletonInstance;
}
return array;
} else {
return createInstances(container, paramMapping, array);
}
}
/**
* Creates a new instance
*
* @param container Container to resolve missing dependencies
* @param paramMapping Optional parameters used to resolve dependencies
* (null if not used)
* @return New instance
* @throws NoSuitableConstructorFoundException thrown if no suitable
* constructor to instantiate could be found
*/
private Object createInstance(PersiJContainer container, PersiJParamMapping paramMapping) throws NoSuitableConstructorFoundException {
Constructor constructor = getBestConstructor(container, paramMapping);
return createInstance(container, constructor, paramMapping);
}
/**
* Creates an array with new instances
*
* @param container Container to resolve missing dependencies
* @param paramMapping Optional parameters used to resolve dependencies
* (null if not used)
* @param array Array which should be filled and returned
* @return New array with instances
* @throws NoSuitableConstructorFoundException thrown if no suitable
* constructor to instantiate could be found
*/
private Object createInstances(PersiJContainer container, PersiJParamMapping paramMapping, Object[] array) throws NoSuitableConstructorFoundException {
Constructor constructor = getBestConstructor(container, paramMapping);
for (int i = 0; i < array.length; i++) {
array[i] = createInstance(container, constructor, paramMapping);
}
return array;
}
/**
* Creates an instance using the given constructor
*
* @param container Container to resolve missing dependencies
* @param constructor Constructor to instantiate
* @param paramMapping Optional parameters used to resolve dependencies
* (null if not used)
* @return New instance
* @throws NoSuitableConstructorFoundException thrown if no suitable
* constructor to instantiate could be found
*/
private Object createInstance(PersiJContainer container, Constructor constructor, PersiJParamMapping paramMapping) throws NoSuitableConstructorFoundException {
Object[] params;
if (paramMapping != null && paramMapping.getType() == type) {
params = paramMapping.getParams();
} else {
Class[] conParams = constructor.getParameterTypes();
int paramCount = conParams.length;
params = new Object[paramCount];
for (int i = 0; i < paramCount; i++) {
params[i] = container.resolve(conParams[i], paramMapping);
}
}
try {
return constructor.newInstance(params);
} catch (Exception ex) {
logger.log(Level.WARNING, "Error while creating instance of an object", ex);
return null;
}
}
/**
* Determines the best constructor to instantiate
*
* @param container Container to check registered types
* @param paramMapping Optional parameters used to resolve dependencies
* (null if not used)
* @return Best constructor to instantiate
* @throws NoSuitableConstructorFoundException thrown if no suitable
* constructor to instantiate could be found
*/
private Constructor getBestConstructor(PersiJContainer container, PersiJParamMapping paramMapping) throws NoSuitableConstructorFoundException {
Constructor bestToCreate = null;
int paramCount = -1;
for (Constructor c : type.getConstructors()) {
Annotation annotation = c.getAnnotation(PersiJConstructor.class);
if (paramMapping != null && paramMapping.getType() == type) {
if (annotation != null && ((PersiJConstructor) annotation).customParamMappingId() == paramMapping.getParamMappingId()) {
bestToCreate = c;
break;
}
} else {
boolean possible = true;
for (Class t : c.getParameterTypes()) {
if (t.isPrimitive() || t == String.class || t == Object.class || !container.isTypeRegistered(t)) {
possible = false;
break;
}
}
if (possible) {
int pCount = c.getParameterTypes().length;
if (annotation != null) {
if (((PersiJConstructor) annotation).isDefault()) {
bestToCreate = c;
break;
}
} else if (pCount > paramCount) {
bestToCreate = c;
paramCount = pCount;
}
}
}
}
if (bestToCreate == null) {
throw new NoSuitableConstructorFoundException();
}
return bestToCreate;
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2012 Darth Affe <http://wyrez.org> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.wyrez.persij;
/**
*
* @author Darth Affe
*/
public final class PersiJParamMapping {
private Class type;
private Object[] params;
private int paramMappingId;
public PersiJParamMapping(Class type, Object... params) {
this(-1, type, params);
}
public PersiJParamMapping(int paramMappingId, Class type, Object... params) {
this.type = type;
this.params = params;
this.paramMappingId = paramMappingId;
}
/**
* Returns the Type to which the ParamMapping belongs
*
* @return Type of the ParamMapping
*/
public final Class getType() {
return type;
}
/**
* Returns the mapped parameters
*
* @return Array with mapped parameters
*/
public final Object[] getParams() {
return params;
}
/**
* Returns the id of the mapping
*
* @return id of the mapping
*/
public final int getParamMappingId() {
return paramMappingId;
}
}