001: package dalma.container.model;
002:
003: import dalma.Resource;
004: import dalma.Engine;
005:
006: import java.lang.reflect.Field;
007: import java.lang.reflect.Method;
008: import java.util.ArrayList;
009: import java.util.List;
010: import java.util.Properties;
011: import java.util.Collections;
012: import java.text.ParseException;
013:
014: /**
015: * Represents a resource injection model of a class.
016: *
017: * <p>
018: * A {@link Model} consists of zero or more {@link Part}s,
019: * which each represents one resource in a model.
020: *
021: * @author Kohsuke Kawaguchi
022: */
023: public final class Model<T> {
024:
025: /**
026: * This object represents the resource injection model for this class.
027: */
028: public final Class<T> clazz;
029:
030: /**
031: * List of resoures that constitute a model.
032: */
033: public final List<Part> parts;
034:
035: /**
036: * Represents one resource.
037: */
038: public final class Part<V> {
039: public final String name;
040: public final Class<V> type;
041: public final Injector<T, V> injector;
042: public final Converter<? super V> converter;
043:
044: public final String description;
045: public final boolean optional;
046:
047: private Part(Injector<T, V> injector, Resource a)
048: throws IllegalResourceException {
049: this .injector = injector;
050: this .name = injector.getName();
051: this .type = injector.getType();
052:
053: this .description = a.description();
054: this .optional = a.optional();
055:
056: converter = Converter.get(type);
057: if (converter == null)
058: throw new IllegalResourceException(type
059: + " is not supported as a resource type");
060: }
061:
062: private void inject(Engine engine, T target, Properties prop)
063: throws ParseException, InjectionException {
064: String token = prop.getProperty(name);
065: if (token == null && !optional)
066: throw new InjectionException("resource \"" + name
067: + "\" must be configured");
068: Object value = converter.load(engine, name, token);
069: if (!type.isInstance(value))
070: throw new InjectionException("resource \"" + name
071: + "\" wants " + type.getName() + " but found "
072: + value.getClass().getName()
073: + " in configuration");
074: injector.set(target, type.cast(value));
075: }
076:
077: public String getName() {
078: return name;
079: }
080:
081: public String getDescription() {
082: return description;
083: }
084:
085: public boolean checkConfiguration(Properties props) {
086: return optional || props.getProperty(name) != null;
087: }
088: }
089:
090: /**
091: * Builds a {@link Model} from the given class.
092: *
093: * @throws IllegalResourceException
094: * if there's incorrect use of {@link Resource}.
095: */
096: public Model(Class<T> clazz) throws IllegalResourceException {
097: this .clazz = clazz;
098:
099: List<Part> parts = new ArrayList<Part>();
100:
101: for (Field f : clazz.getFields()) {
102: Resource a = f.getAnnotation(Resource.class);
103: if (a != null) {
104: parts.add(new Part(new FieldInjector(f), a));
105: }
106: }
107: for (Method m : clazz.getMethods()) {
108: Resource a = m.getAnnotation(Resource.class);
109: if (a != null) {
110: parts.add(new Part(new MethodInjector(m), a));
111: }
112: }
113: // TODO: check for non-public methods that have @Resource and report an error
114:
115: this .parts = Collections.unmodifiableList(parts);
116: }
117:
118: public void inject(Engine engine, T target, Properties prop)
119: throws InjectionException, ParseException {
120: for (Part<?> res : parts)
121: res.inject(engine, target, prop);
122: }
123:
124: /**
125: * Checks if the given properties have enough configuration
126: * for all mandatory parameters.
127: */
128: public boolean checkConfiguration(Properties props) {
129: for (Part<?> res : parts)
130: if (!res.checkConfiguration(props))
131: return false;
132: return true;
133: }
134:
135: public List<Part> getParts() {
136: return parts;
137: }
138: }
|