001: package org.databene.model.data;
002:
003: import org.databene.commons.Operation;
004: import org.databene.commons.OrderedMap;
005: import org.databene.commons.BeanUtil;
006: import org.databene.commons.Validator;
007: import org.databene.commons.converter.AnyConverter;
008:
009: import java.util.List;
010:
011: /**
012: * Common parent class of all descriptors.<br/><br/>
013: * Created: 17.07.2006 21:30:45
014: * @author Volker Bergmann
015: */
016: public abstract class FeatureDescriptor {
017:
018: protected FeatureDescriptor parent;
019: protected OrderedMap<String, FeatureDetail<? extends Object>> details;
020:
021: // constructor -----------------------------------------------------------------------------------------------------
022:
023: public FeatureDescriptor(String name, FeatureDescriptor parent) {
024: this .details = new OrderedMap<String, FeatureDetail<? extends Object>>();
025: this .parent = parent;
026: addDetailConfig("name", String.class, true, null);
027: addDetailConfig("generator", Object.class, false, null);
028: addDetailConfig("source", String.class, false, null);
029: addDetailConfig("encoding", String.class, false, null);
030: addDetailConfig("pattern", String.class, false, null);
031: addDetailConfig("unique", Boolean.class, true, false);
032: addDetailConfig("cyclic", Boolean.class, false, null);
033: addDetailConfig("selector", String.class, false, null);
034: addDetailConfig("mode", Mode.class, false, Mode.normal);
035: addDetailConfig("proxy", Iteration.class, false, null);
036: addDetailConfig("proxy-param1", Long.class, false, null);
037: addDetailConfig("proxy-param2", Long.class, false, null);
038: addDetailConfig("validator", String.class, false, null);
039: setName(name);
040: }
041:
042: // typed interface -------------------------------------------------------------------------------------------------
043:
044: public void setParent(FeatureDescriptor parent) {
045: this .parent = parent;
046: }
047:
048: public String getName() {
049: return (String) getDetailValue("name");
050: }
051:
052: public void setName(String name) {
053: setDetail("name", name);
054: }
055:
056: public String getPattern() {
057: return (String) getDetailValue("pattern");
058: }
059:
060: public void setPattern(String pattern) {
061: setDetail("pattern", pattern);
062: }
063:
064: public Boolean isUnique() {
065: return (Boolean) getDetailValue("unique");
066: }
067:
068: public void setUnique(Boolean unique) {
069: setDetail("unique", unique);
070: }
071:
072: public String getSelector() {
073: return (String) getDetailValue("selector");
074: }
075:
076: public void setSelector(String selector) {
077: setDetail("selector", selector);
078: }
079:
080: public Mode getMode() {
081: return (Mode) getDetailValue("mode");
082: }
083:
084: public void setMode(Mode mode) {
085: setDetail("mode", mode);
086: }
087:
088: public Boolean isCyclic() {
089: return (Boolean) getDetailValue("cyclic");
090: }
091:
092: public void setCyclic(boolean cyclic) {
093: setDetail("cyclic", cyclic);
094: }
095:
096: public String getGenerator() {
097: return (String) getDetailValue("generator");
098: }
099:
100: public void setGenerator(String generatorName) {
101: setDetail("generator", generatorName);
102: }
103:
104: public Validator<? extends Object> getValidator() {
105: String validatorClassName = (String) getDetailValue("validator");
106: if (validatorClassName == null)
107: return null;
108: return (Validator<? extends Object>) BeanUtil
109: .newInstance(validatorClassName);
110: }
111:
112: public void setValidator(String validatorName) {
113: setDetail("validator", validatorName);
114: }
115:
116: public String getSource() {
117: return (String) getDetailValue("source");
118: }
119:
120: public void setSource(String source) {
121: setDetail("source", source);
122: }
123:
124: public String getEncoding() {
125: return (String) getDetailValue("encoding");
126: }
127:
128: public void setEncoding(String encoding) {
129: setDetail("encoding", encoding);
130: }
131:
132: public Iteration getProxy() {
133: return (Iteration) getDetailValue("proxy");
134: }
135:
136: public Long getProxyParam1() {
137: return (Long) getDetailValue("proxy-param1");
138: }
139:
140: public void setProxyParam1(Long param) {
141: setDetail("proxy-param1", param);
142: }
143:
144: public Long getProxyParam2() {
145: return (Long) getDetailValue("proxy-param2");
146: }
147:
148: public void setProxyParam2(Long param) {
149: setDetail("proxy-param2", param);
150: }
151:
152: // literal construction helpers ------------------------------------------------------------------------------------
153:
154: public FeatureDescriptor withParent(FeatureDescriptor parent) {
155: this .parent = parent;
156: return this ;
157: }
158:
159: public FeatureDescriptor withName(String name) {
160: setName(name);
161: return this ;
162: }
163:
164: public FeatureDescriptor withPattern(String pattern) {
165: setPattern(pattern);
166: return this ;
167: }
168:
169: public FeatureDescriptor withUnique(Boolean unique) {
170: setDetail("unique", unique);
171: return this ;
172: }
173:
174: public FeatureDescriptor withSelector(String selector) {
175: setSelector(selector);
176: return this ;
177: }
178:
179: public FeatureDescriptor withMode(Mode mode) {
180: setMode(mode);
181: return this ;
182: }
183:
184: public FeatureDescriptor withCyclic(boolean cyclic) {
185: setCyclic(cyclic);
186: return this ;
187: }
188:
189: public FeatureDescriptor withGenerator(String generatorName) {
190: setGenerator(generatorName);
191: return this ;
192: }
193:
194: public FeatureDescriptor withValidator(String validatorName) {
195: setValidator(validatorName);
196: return this ;
197: }
198:
199: public FeatureDescriptor withSource(String source) {
200: setSource(source);
201: return this ;
202: }
203:
204: public FeatureDescriptor withProxyParam1(Long param) {
205: setProxyParam1(param);
206: return this ;
207: }
208:
209: public FeatureDescriptor withProxyParam2(Long param) {
210: setProxyParam2(param);
211: return this ;
212: }
213:
214: // generic detail access -------------------------------------------------------------------------------------------
215:
216: public boolean supportsDetail(String name) {
217: return (details.get(name) != null);
218:
219: }
220:
221: public Object getDeclaredDetailValue(String name) {
222: return getDeclaredDetail(name).getValue();
223: }
224:
225: public Object getDetailValue(String name) {
226: FeatureDetail<? extends Object> detail = getDeclaredDetail(name);
227: Object value = detail.getValue();
228: if (value == null && parent != null
229: && parent.supportsDetail(name) && detail.isConstraint())
230: value = parent.getDetailValue(name);
231: return value;
232: }
233:
234: public <T> void setDetail(String detailName, Object detailValue) {
235: FeatureDetail<T> detail = (FeatureDetail<T>) getDeclaredDetail(detailName);
236: if (detail == null)
237: throw new UnsupportedOperationException(getClass()
238: .getSimpleName()
239: + " does not support detail type: " + detailName);
240: detail.setValue(AnyConverter.convert(detailValue, detail
241: .getType()));
242: }
243:
244: public Object getDetailDefault(String name) {
245: return getDeclaredDetail(name).getDefault();
246: }
247:
248: public List<FeatureDetail<? extends Object>> getDetails() {
249: return details.values();
250: }
251:
252: // java.lang.io overrides ------------------------------------------------------------------------------------------
253:
254: public String toString() {
255: StringBuilder buffer = new StringBuilder(getName()).append("[");
256: boolean empty = true;
257: for (FeatureDetail<? extends Object> descriptor : details
258: .values())
259: if (descriptor.getValue() != null
260: && !"name".equals(descriptor.getName())) {
261: if (!empty)
262: buffer.append(", ");
263: empty = false;
264: buffer.append(descriptor.getName()).append('=').append(
265: descriptor.getValue());
266: }
267: return buffer.append("]").toString();
268: }
269:
270: public boolean equals(Object o) {
271: if (this == o)
272: return true;
273: if (o == null || getClass() != o.getClass())
274: return false;
275: final FeatureDescriptor that = (FeatureDescriptor) o;
276: if (!this .details.equals(that.details)) // TODO v0.5 consider capitalization
277: return false;
278: return !(parent != null ? !parent.equals(that.parent)
279: : that.parent != null);
280: }
281:
282: public int hashCode() {
283: return (getClass().hashCode() * 29 + (parent != null ? parent
284: .hashCode() : 0))
285: * 29 + details.hashCode();
286: }
287:
288: // helpers ---------------------------------------------------------------------------------------------------------
289:
290: protected Class<? extends Object> getDetailType(String detailName) {
291: FeatureDetail<? extends Object> detail = details
292: .get(detailName);
293: if (detail == null)
294: throw new UnsupportedOperationException(
295: "Feature detail not supported: " + detailName);
296: return detail.getType();
297: }
298:
299: protected <T> void addDetailConfig(String detailName,
300: Class<T> detailType, boolean constraint, T defaultValue,
301: Operation<T, T> combinator) {
302: this .details.put(detailName, new FeatureDetail<T>(detailName,
303: detailType, constraint, defaultValue, combinator));
304: }
305:
306: protected <T> void addDetailConfig(String detailName,
307: Class<T> detailType, boolean constraint, T defaultValue) {
308: this .details.put(detailName, new FeatureDetail<T>(detailName,
309: detailType, constraint, defaultValue));
310: }
311:
312: protected FeatureDetail<? extends Object> getDeclaredDetail(
313: String name) {
314: FeatureDetail<? extends Object> detail = details.get(name);
315: if (detail == null)
316: throw new UnsupportedOperationException(
317: "Feature detail not supported: " + name);
318: return detail;
319: }
320:
321: }
|