1
|
|
/*
|
2
|
|
* JBind
|
3
|
|
*
|
4
|
|
* Copyright (c) by Stefan Wachter. All rights reserved.
|
5
|
|
*
|
6
|
|
* Usage, modification, and redistribution is subject to license terms that are
|
7
|
|
* available at 'http://www.jbind.org'. The JBind license is like the
|
8
|
|
* 'Apache Software License V 1.1'.
|
9
|
|
*/
|
10
|
|
package org.jbind.xml.schema.compiler;
|
11
|
|
|
12
|
|
import java.io.BufferedReader;
|
13
|
|
import java.io.File;
|
14
|
|
import java.io.IOException;
|
15
|
|
import java.io.Reader;
|
16
|
|
import java.util.ArrayList;
|
17
|
|
import java.util.Collections;
|
18
|
|
import java.util.Comparator;
|
19
|
|
import java.util.HashMap;
|
20
|
|
import java.util.Iterator;
|
21
|
|
import java.util.List;
|
22
|
|
import java.util.Map;
|
23
|
|
import java.util.StringTokenizer;
|
24
|
|
import java.util.TreeMap;
|
25
|
|
|
26
|
|
import org.jbind.message.IMessage;
|
27
|
|
import org.jbind.util.collection.ConcatIterator;
|
28
|
|
import org.jbind.util.reflect.ReflectUtil;
|
29
|
|
import org.jbind.xml.base.IAttribute;
|
30
|
|
import org.jbind.xml.base.IBindingAttributes;
|
31
|
|
import org.jbind.xml.base.IRange;
|
32
|
|
import org.jbind.xml.base.IRef;
|
33
|
|
import org.jbind.xml.base.RefComparator;
|
34
|
|
import org.jbind.xml.base.StringUtil;
|
35
|
|
import org.jbind.xml.core.bridge.IXPathMethod;
|
36
|
|
import org.jbind.xml.core.cmp.IAttributesModel;
|
37
|
|
import org.jbind.xml.core.cmp.IBinding;
|
38
|
|
import org.jbind.xml.core.cmp.IComponent;
|
39
|
|
import org.jbind.xml.core.cmp.IContentModel;
|
40
|
|
import org.jbind.xml.core.cmp.ISourceInfo;
|
41
|
|
import org.jbind.xml.core.constraint.ConstraintType;
|
42
|
|
import org.jbind.xml.core.constraint.IIdRefOrIdRefsConstraint;
|
43
|
|
import org.jbind.xml.core.constraint.IReferenceConstraint;
|
44
|
|
import org.jbind.xml.core.constraint.ITypeKeyRefConstraint;
|
45
|
|
import org.jbind.xml.core.content.IAttrRefOrDecl;
|
46
|
|
import org.jbind.xml.core.content.IDataRefOrDecl;
|
47
|
|
import org.jbind.xml.core.content.IElemRefOrDecl;
|
48
|
|
import org.jbind.xml.core.type.IAnyType;
|
49
|
|
import org.jbind.xml.msg.XmlException;
|
50
|
|
import org.jbind.xml.msg.XmlMessages;
|
51
|
|
|
52
|
|
public abstract class DataCartridge extends BaseCartridge {
|
53
|
|
|
54
|
6
|
public DataCartridge(String aCartridgeAttributePrefix, String aNamePrefix, String aNameSuffix) {
|
55
|
6
|
super(aCartridgeAttributePrefix, aNamePrefix, aNameSuffix);
|
56
|
|
}
|
57
|
|
|
58
|
1132
|
public boolean overwrite() {
|
59
|
1132
|
return true;
|
60
|
|
}
|
61
|
|
|
62
|
397
|
public boolean isUpToDate(Reader aReader, IFileInfo aFileInfo) throws IOException {
|
63
|
397
|
BufferedReader reader = new BufferedReader(aReader);
|
64
|
397
|
StringTokenizer stringTokenizer = new StringTokenizer(aFileInfo.getGeneratedCode(), "\n");
|
65
|
397
|
while (true) {
|
66
|
25926
|
String previousLine = reader.readLine();
|
67
|
25926
|
if (null == previousLine) {
|
68
|
397
|
if (stringTokenizer.hasMoreElements()) {
|
69
|
0
|
return false;
|
70
|
|
} else {
|
71
|
397
|
return true;
|
72
|
|
}
|
73
|
|
}
|
74
|
25529
|
if (!stringTokenizer.hasMoreElements()) {
|
75
|
0
|
return false;
|
76
|
|
}
|
77
|
25529
|
String generatedLine = (String)stringTokenizer.nextElement();
|
78
|
25529
|
if (!previousLine.equals(generatedLine)) {
|
79
|
0
|
return false;
|
80
|
|
}
|
81
|
|
}
|
82
|
|
}
|
83
|
|
|
84
|
0
|
public IMessage getEditHint(File aFile, IComponent aComponent) {
|
85
|
|
assert false;
|
86
|
0
|
return null;
|
87
|
|
}
|
88
|
|
|
89
|
118
|
public IBinding createGlobalAttrDeclBinding(IComponent aComponent, String aRootPackage, boolean aUseBuiltInClassesOnly) {
|
90
|
118
|
return new PackageBinding(aRootPackage, this, aComponent);
|
91
|
|
}
|
92
|
70
|
public IBinding createGlobalGroupDeclBinding(IComponent aComponent, String aRootPackage, boolean aUseBuiltInClassesOnly) {
|
93
|
70
|
return new GlobalBinding(aRootPackage, this, aComponent);
|
94
|
|
}
|
95
|
580
|
public IBinding createGlobalElemDeclBinding(IComponent aComponent, String aRootPackage, boolean aUseBuiltInClassesOnly) {
|
96
|
580
|
return new PackageBinding(aRootPackage, this, aComponent);
|
97
|
|
}
|
98
|
88
|
public IBinding createGlobalAttrGroupBinding(IComponent aComponent, String aRootPackage, boolean aUseBuiltInClassesOnly) {
|
99
|
88
|
return new GlobalBinding(aRootPackage, this, aComponent);
|
100
|
|
}
|
101
|
564
|
public IBinding createBuiltInBinding(IComponent aComponent) {
|
102
|
564
|
return new BuiltInBinding(aComponent, doGetBuiltInPackage(), getNamePrefix(aComponent), getNameSuffix(aComponent));
|
103
|
|
}
|
104
|
60
|
public IBinding createInnerAttrRefBinding(IComponent aComponent, IBinding aParentBinding, boolean aUseBuiltInClassesOnly) {
|
105
|
60
|
return aParentBinding;
|
106
|
|
}
|
107
|
1120
|
public IBinding createInnerAttrDeclBinding(IComponent aComponent, IBinding aParentBinding, boolean aUseBuiltInClassesOnly) {
|
108
|
1120
|
return aParentBinding;
|
109
|
|
}
|
110
|
132
|
public IBinding createInnerAttrWildcardBinding(IComponent aComponent, IBinding aParentBinding, boolean aUseBuiltInClassesOnly) {
|
111
|
132
|
return aParentBinding;
|
112
|
|
}
|
113
|
772
|
public IBinding createInnerGroupRefOrDeclBinding(IComponent aComponent, IBinding aParentBinding, boolean aUseBuiltInClassesOnly) {
|
114
|
772
|
return aParentBinding;
|
115
|
|
}
|
116
|
420
|
public IBinding createInnerElemRefBinding(IComponent aComponent, IBinding aParentBinding, boolean aUseBuiltInClassesOnly) {
|
117
|
420
|
return aParentBinding;
|
118
|
|
}
|
119
|
740
|
public IBinding createInnerElemDeclBinding(IComponent aComponent, IBinding aParentBinding, boolean aUseBuiltInClassesOnly) {
|
120
|
740
|
return aParentBinding;
|
121
|
|
}
|
122
|
54
|
public IBinding createInnerElemWildcardBinding(IComponent aComponent, IBinding aParentBinding, boolean aUseBuiltInClassesOnly) {
|
123
|
54
|
return aParentBinding;
|
124
|
|
}
|
125
|
988
|
public IBinding createInnerAttrGroupBinding(IComponent aComponent, IBinding aParentBinding, boolean aUseBuiltInClassesOnly) {
|
126
|
988
|
return aParentBinding;
|
127
|
|
}
|
128
|
|
|
129
|
|
protected abstract String doGetBuiltInPackage();
|
130
|
|
|
131
|
874
|
protected boolean doVisitAnyTypeStart(IAnyType aType) throws XmlException {
|
132
|
874
|
writeMultiLn(typeComment(aType));
|
133
|
874
|
writeLn(declaration(aType) + " {");
|
134
|
874
|
addIndent();
|
135
|
874
|
writeMultiLn(begin(aType));
|
136
|
874
|
setOuterComponent(aType);
|
137
|
874
|
if (!treatMethods(aType)) {
|
138
|
6
|
return true;
|
139
|
|
}
|
140
|
868
|
setNotEmpty();
|
141
|
|
|
142
|
|
/**
|
143
|
|
* Maps property names to their components. Used to indicate naming problems
|
144
|
|
* during generation.
|
145
|
|
*/
|
146
|
868
|
Map propertyNames = new HashMap();
|
147
|
|
|
148
|
868
|
MethodVariant pv = null;
|
149
|
|
|
150
|
|
//
|
151
|
|
// elements
|
152
|
|
//
|
153
|
|
|
154
|
|
// The elements are sorted to guarantee the same sequence of generation.
|
155
|
868
|
Map elementInfos = new TreeMap(RefComparator.INSTANCE);
|
156
|
868
|
collectElementInfos(aType, elementInfos, false);
|
157
|
|
|
158
|
868
|
for (Iterator i = elementInfos.values().iterator(); i.hasNext(); ) {
|
159
|
1106
|
ElementInfo elementInfo = (ElementInfo)i.next();
|
160
|
1106
|
IElemRefOrDecl elemRefOrDecl = elementInfo.elemRefOrDecl;
|
161
|
|
|
162
|
|
// check if the property name is unique
|
163
|
1106
|
String propertyName = propertyName(elemRefOrDecl);
|
164
|
1106
|
ISourceInfo previous = (ISourceInfo)propertyNames.put(propertyName, elemRefOrDecl);
|
165
|
1106
|
if (null != previous) {
|
166
|
0
|
throw new XmlException(XmlMessages.ambiguousProperty(propertyName, previous.getLocation(), elemRefOrDecl));
|
167
|
|
}
|
168
|
|
|
169
|
1106
|
boolean useDataClass = useDataClass(elemRefOrDecl);
|
170
|
|
|
171
|
1106
|
if (elementInfo.isSingle && (!elementInfo.isInheritedSingle || treatInherited())) {
|
172
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(elemRefOrDecl, IBindingAttributes.GETTER, "normal"))) {
|
173
|
374
|
writeMultiLn(elementGetter(aType, elemRefOrDecl, pv, useDataClass));
|
174
|
|
}
|
175
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(elemRefOrDecl, IBindingAttributes.CHECKER, "none"))) {
|
176
|
46
|
writeMultiLn(elementChecker(aType, elemRefOrDecl, pv));
|
177
|
|
}
|
178
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(elemRefOrDecl, IBindingAttributes.REMOVER, "none"))) {
|
179
|
24
|
writeMultiLn(elementRemover(aType, elemRefOrDecl, pv));
|
180
|
|
}
|
181
|
|
}
|
182
|
|
|
183
|
1106
|
if (!elementInfo.isInherited || treatInherited()) {
|
184
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(elemRefOrDecl, IBindingAttributes.CREATOR, "none"))) {
|
185
|
10
|
writeMultiLn(elementCreator(aType, elemRefOrDecl, pv));
|
186
|
|
}
|
187
|
|
}
|
188
|
|
|
189
|
1106
|
if (!elementInfo.isInherited || treatInherited()) {
|
190
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(elemRefOrDecl, IBindingAttributes.CREATOR_WITH_TYPE, "none"))) {
|
191
|
30
|
writeMultiLn(elementCreatorWithType(aType, elemRefOrDecl, pv));
|
192
|
|
}
|
193
|
|
}
|
194
|
|
|
195
|
1106
|
if (elementInfo.isMultiple && (!elementInfo.isInheritedMultiple || treatInherited())) {
|
196
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(elemRefOrDecl, IBindingAttributes.ITERATOR, "normal"))) {
|
197
|
500
|
writeMultiLn(elementIterator(aType, elemRefOrDecl, pv, useDataClass));
|
198
|
|
}
|
199
|
|
}
|
200
|
|
|
201
|
|
}
|
202
|
|
|
203
|
868
|
IAnyType baseType = aType.getBaseType();
|
204
|
|
|
205
|
|
//
|
206
|
|
// attributes
|
207
|
|
//
|
208
|
|
|
209
|
868
|
for (Iterator i = aType.getAttributesModel().iterAttributes();
|
210
|
1619
|
i.hasNext(); ) {
|
211
|
751
|
IAttrRefOrDecl attr = (IAttrRefOrDecl)i.next();
|
212
|
751
|
IRef ref = attr.getGlobalRef();
|
213
|
751
|
IAttrRefOrDecl baseAttr = getBaseAttributeDecl(ref, aType);
|
214
|
|
|
215
|
|
// check if the property name is unique
|
216
|
751
|
String propertyName = propertyName(attr);
|
217
|
751
|
ISourceInfo previous = (ISourceInfo)propertyNames.put(propertyName, attr);
|
218
|
751
|
if (null != previous) {
|
219
|
0
|
throw new XmlException(XmlMessages.ambiguousProperty(propertyName, previous.getLocation(), attr));
|
220
|
|
}
|
221
|
|
|
222
|
751
|
boolean useDataClass = useDataClass(baseAttr);
|
223
|
|
|
224
|
|
// indicates if the attribute is inherited
|
225
|
751
|
boolean inherited = baseType.getAttributesModel().hasAttribute(ref);
|
226
|
|
|
227
|
751
|
if (!inherited || treatInherited()) {
|
228
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(baseAttr, IBindingAttributes.GETTER, "normal"))) {
|
229
|
580
|
writeMultiLn(attributeGetter(aType, baseAttr, pv, useDataClass));
|
230
|
|
}
|
231
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(baseAttr, IBindingAttributes.SETTER, "none"))) {
|
232
|
114
|
writeMultiLn(attributeSetter(aType, baseAttr, pv, useDataClass));
|
233
|
|
}
|
234
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(baseAttr, IBindingAttributes.ITERATOR, "normal"))) {
|
235
|
580
|
writeMultiLn(attributeIterator(aType, baseAttr, pv, useDataClass));
|
236
|
|
}
|
237
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(baseAttr, IBindingAttributes.CHECKER, "none"))) {
|
238
|
206
|
writeMultiLn(attributeChecker(aType, baseAttr, pv));
|
239
|
|
}
|
240
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(baseAttr, IBindingAttributes.REMOVER, "none"))) {
|
241
|
114
|
writeMultiLn(attributeRemover(aType, baseAttr, pv));
|
242
|
|
}
|
243
|
|
}
|
244
|
|
}
|
245
|
|
|
246
|
|
//
|
247
|
|
// reference constraints
|
248
|
|
//
|
249
|
|
|
250
|
868
|
List l = new ArrayList();
|
251
|
868
|
for (Iterator i = aType.getConstraints().getConstraintList(ConstraintType.TYPE_KEY_REF).iterator();
|
252
|
876
|
i.hasNext(); ) {
|
253
|
8
|
ITypeKeyRefConstraint c = (ITypeKeyRefConstraint)i.next();
|
254
|
8
|
String propertyName = c.getLocalStringBindingAttribute(IBindingAttributes.NAME);
|
255
|
8
|
if (null == propertyName) {
|
256
|
8
|
propertyName = c.getName();
|
257
|
|
}
|
258
|
8
|
String comment = "keyRef (" + c.getName() + ")";
|
259
|
8
|
l.add(new RefConstraintInfo(c, c.getConstraintKey(), StringUtil.firstUpper(StringUtil.toJavaIdentifier(propertyName)), comment, c.getDataType()));
|
260
|
|
}
|
261
|
868
|
Iterator i1 = aType.getConstraints().getConstraintList(ConstraintType.ID_REF).iterator();
|
262
|
868
|
Iterator i2 = aType.getConstraints().getConstraintList(ConstraintType.ID_REFS).iterator();
|
263
|
868
|
for (Iterator i = new ConcatIterator(i1, i2); i.hasNext(); ) {
|
264
|
8
|
IIdRefOrIdRefsConstraint c = (IIdRefOrIdRefsConstraint)i.next();
|
265
|
8
|
String propertyName = c.getAttrRefOrDecl().getLocalStringBindingAttribute(IBindingAttributes.NAME);
|
266
|
8
|
if (null == propertyName) {
|
267
|
8
|
propertyName = c.getAttrRefOrDecl().getGlobalRef().getLocalPart();
|
268
|
|
}
|
269
|
8
|
String comment = null;
|
270
|
8
|
if (c.isSingleNotMultipleReference()) {
|
271
|
4
|
comment = "IDREF(" + c.getAttrRefOrDecl().getGlobalRef().getLocalPart() + ")";
|
272
|
|
} else {
|
273
|
4
|
comment = "IDREFS(" + c.getAttrRefOrDecl().getGlobalRef().getLocalPart() + ")";
|
274
|
|
}
|
275
|
|
|
276
|
8
|
l.add(new RefConstraintInfo(c, c.getConstraintKey(), StringUtil.firstUpper(StringUtil.toJavaIdentifier(propertyName)), comment, c.getDataType()));
|
277
|
|
}
|
278
|
868
|
for (Iterator i = l.iterator(); i.hasNext(); ) {
|
279
|
16
|
RefConstraintInfo constraintInfo = (RefConstraintInfo)i.next();
|
280
|
16
|
IReferenceConstraint constraint = constraintInfo.referenceConstraint;
|
281
|
|
// indicates if the constraint is inherited
|
282
|
16
|
boolean inherited = baseType.getConstraints().hasConstraint(constraint);
|
283
|
16
|
if (!inherited || treatInherited()) {
|
284
|
16
|
if (constraint.isSingleNotMultipleReference()) {
|
285
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(constraint, IBindingAttributes.REFERENCE_GETTER, "normal"))) {
|
286
|
10
|
writeMultiLn(referenceGetter(aType, constraintInfo, pv));
|
287
|
|
}
|
288
|
|
}
|
289
|
16
|
if (!constraint.isSingleNotMultipleReference()) {
|
290
|
?
|
if (MethodVariant.NONE != (pv = MethodVariant.getMethodVariant(constraint, IBindingAttributes.REFERENCE_ITERATOR, "normal"))) {
|
291
|
6
|
writeMultiLn(referenceIterator(aType, constraintInfo, pv));
|
292
|
|
}
|
293
|
|
}
|
294
|
|
}
|
295
|
|
}
|
296
|
|
|
297
|
868
|
ArrayList xPathMethods = new ArrayList(aType.getXPathMethods().values());
|
298
|
868
|
Collections.sort(xPathMethods, new Comparator() {
|
299
|
14
|
public int compare(Object anObject1, Object anObject2) {
|
300
|
14
|
IXPathMethod m1 = (IXPathMethod)anObject1;
|
301
|
14
|
IXPathMethod m2 = (IXPathMethod)anObject2;
|
302
|
14
|
return m1.getName().compareTo(m2.getName());
|
303
|
|
}
|
304
|
|
});
|
305
|
|
|
306
|
868
|
for (Iterator i = xPathMethods.iterator(); i.hasNext(); ) {
|
307
|
12
|
IXPathMethod m = (IXPathMethod)i.next();
|
308
|
12
|
boolean inherited = null != baseType.getXPathMethods().get(m.getName());
|
309
|
12
|
if (!inherited || treatInherited()) {
|
310
|
12
|
writeMultiLn(xPathMethod(aType, m, pv));
|
311
|
|
}
|
312
|
|
}
|
313
|
|
|
314
|
868
|
return true;
|
315
|
|
}
|
316
|
|
|
317
|
874
|
protected void doVisitAnyTypeEnd(IAnyType aType) {
|
318
|
874
|
removeIndent();
|
319
|
874
|
writeLn("}");
|
320
|
|
}
|
321
|
|
|
322
|
|
/**
|
323
|
|
* Collects the property infos of all element declarations of this type and
|
324
|
|
* all of its super types. Element declararations may have be removed from a
|
325
|
|
* type be restriction. Yet, the corresponding methods must be generated in
|
326
|
|
* the data class.
|
327
|
|
*/
|
328
|
4059
|
private void collectElementInfos(IAnyType aType, Map aMap, boolean aSuperType) {
|
329
|
4059
|
if (null != aType) {
|
330
|
3191
|
collectElementInfos(aType.getBaseType(), aMap, true);
|
331
|
3191
|
IContentModel contentModel = aType.getContentModel();
|
332
|
3191
|
for (Iterator i = contentModel.iterElements(); i.hasNext(); ) {
|
333
|
1653
|
IElemRefOrDecl e = (IElemRefOrDecl)i.next();
|
334
|
1653
|
IRef ref = e.getGlobalRef();
|
335
|
1653
|
ElementInfo ei = (ElementInfo)aMap.get(ref);
|
336
|
1653
|
if (null == ei) {
|
337
|
1106
|
ei = new ElementInfo(e);
|
338
|
1106
|
aMap.put(ref, ei);
|
339
|
|
}
|
340
|
1653
|
IRange range = contentModel.getRange(ref);
|
341
|
1653
|
boolean isSingle = range.compareMaxOccurs(1);
|
342
|
1653
|
boolean isMultiple = range.isUnbounded() || (range.getMaxOccurs() > 1);
|
343
|
1653
|
ei.isSingle |= isSingle;
|
344
|
1653
|
ei.isMultiple |= isMultiple;
|
345
|
1653
|
ei.isInheritedSingle |= isSingle && aSuperType;
|
346
|
1653
|
ei.isInheritedMultiple |= isMultiple && aSuperType;
|
347
|
1653
|
ei.isInherited |= aSuperType;
|
348
|
|
}
|
349
|
|
}
|
350
|
|
}
|
351
|
|
|
352
|
7317
|
protected boolean useDataClass(IDataRefOrDecl aRefOrDecl) {
|
353
|
7317
|
boolean res = false;
|
354
|
7317
|
IAttribute a = null;
|
355
|
7317
|
a = aRefOrDecl.getBindingAttribute(IBindingAttributes.USE_DATA_CLASS);
|
356
|
7317
|
if (a != null) {
|
357
|
48
|
res = a.getBoolean();
|
358
|
|
} else {
|
359
|
7269
|
a = aRefOrDecl.getType().getDefaultedLocalBindingAttribute(IBindingAttributes.HAS_BEHAVIOUR);
|
360
|
7269
|
if (a != null) {
|
361
|
605
|
res = a.getBoolean();
|
362
|
|
}
|
363
|
|
}
|
364
|
7317
|
return res;
|
365
|
|
}
|
366
|
|
|
367
|
|
/**
|
368
|
|
* Gets the property name of the decl. The first letter of the property name
|
369
|
|
* is guaranteed to be an upper case letter.
|
370
|
|
*
|
371
|
|
* @param anAttrOrElem <i>(required)</i>.
|
372
|
|
* @return <i>(required)</i>.
|
373
|
|
*/
|
374
|
5685
|
protected String propertyName(IDataRefOrDecl anAttrOrElem) {
|
375
|
5685
|
String res = anAttrOrElem.getLocalStringBindingAttribute(IBindingAttributes.NAME);
|
376
|
5685
|
if (null == res) {
|
377
|
5685
|
res = StringUtil.firstUpper(anAttrOrElem.getName());
|
378
|
|
}
|
379
|
5685
|
return StringUtil.firstUpper(StringUtil.toJavaIdentifier(res));
|
380
|
|
}
|
381
|
|
|
382
|
|
/**
|
383
|
|
* Gets the base attribute declaration for a reference. The base attribute
|
384
|
|
* declaration is the attribute declaration from that base type that has no base
|
385
|
|
* type that also has the attribute.
|
386
|
|
*/
|
387
|
751
|
private IAttrRefOrDecl getBaseAttributeDecl(IRef aRef, IAnyType aType) {
|
388
|
751
|
IAttrRefOrDecl res = null;
|
389
|
751
|
for (IAnyType t = aType; ; t = t.getBaseType()) {
|
390
|
1991
|
IAttributesModel m = t.getAttributesModel();
|
391
|
1991
|
IAttrRefOrDecl a = m.getAttrRefOrDecl(aRef);
|
392
|
1991
|
if (null == a) {
|
393
|
751
|
break;
|
394
|
|
}
|
395
|
1240
|
res = a;
|
396
|
|
}
|
397
|
751
|
return res;
|
398
|
|
}
|
399
|
|
|
400
|
|
//
|
401
|
|
// Hook methods
|
402
|
|
//
|
403
|
|
|
404
|
|
protected abstract String typeComment(IAnyType aType);
|
405
|
|
protected abstract String declaration(IAnyType aType);
|
406
|
|
protected abstract String begin(IAnyType aType);
|
407
|
|
|
408
|
|
protected abstract String elementGetter(IAnyType aType, IElemRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant, boolean aUseDataClass);
|
409
|
|
protected abstract String elementChecker(IAnyType aType, IElemRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant);
|
410
|
|
protected abstract String elementRemover(IAnyType aType, IElemRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant);
|
411
|
|
protected abstract String elementCreator(IAnyType aType, IElemRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant);
|
412
|
|
protected abstract String elementCreatorWithType(IAnyType aType, IElemRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant);
|
413
|
|
protected abstract String elementIterator(IAnyType aType, IElemRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant, boolean aUseDataClass);
|
414
|
|
|
415
|
|
protected abstract String attributeGetter(IAnyType aType, IAttrRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant, boolean aUseDataClass);
|
416
|
|
protected abstract String attributeChecker(IAnyType aType, IAttrRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant);
|
417
|
|
protected abstract String attributeRemover(IAnyType aType, IAttrRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant);
|
418
|
|
protected abstract String attributeSetter(IAnyType aType, IAttrRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant, boolean aUseDataClass);
|
419
|
|
protected abstract String attributeIterator(IAnyType aType, IAttrRefOrDecl aRefOrDecl, MethodVariant aPropertyVariant, boolean aUseDataClass);
|
420
|
|
|
421
|
|
protected abstract String referenceGetter(IAnyType aType, RefConstraintInfo aConstraintInfo, MethodVariant aPropertyVariant);
|
422
|
|
protected abstract String referenceIterator(IAnyType aType, RefConstraintInfo aConstraintInfo, MethodVariant aPropertyVariant);
|
423
|
|
|
424
|
|
protected abstract String xPathMethod(IAnyType aType, IXPathMethod aMethod, MethodVariant aPropertyVariant);
|
425
|
|
|
426
|
|
/**
|
427
|
|
* Checks if code for methods is to be created. No method code is generated for
|
428
|
|
* abstract data classes. Yet the abstract data class itself is to be created
|
429
|
|
* because it may contain inner classes that are not abstract.
|
430
|
|
*
|
431
|
|
* @param aType <i>(required)</i>.
|
432
|
|
* @return Returns <code>true</code> iff code for methods is to be created.
|
433
|
|
*/
|
434
|
|
protected abstract boolean treatMethods(IAnyType aType);
|
435
|
|
|
436
|
|
protected abstract boolean treatInherited();
|
437
|
|
|
438
|
|
protected static class RefConstraintInfo {
|
439
|
|
|
440
|
|
IReferenceConstraint referenceConstraint;
|
441
|
|
/**
|
442
|
|
* Key of the reference constraint. The key must be unique within the
|
443
|
|
* type the reference constraint belongs to. The key is used by the methods
|
444
|
|
* that are generated to access their referenced data.
|
445
|
|
*/
|
446
|
|
String constraintKey;
|
447
|
|
String propertyName;
|
448
|
|
String comment;
|
449
|
|
IAnyType dataType;
|
450
|
16
|
RefConstraintInfo(IReferenceConstraint aConstraint, String aConstraintKey, String aPropertyName, String aComment, IAnyType aDataType) {
|
451
|
16
|
referenceConstraint = aConstraint;
|
452
|
16
|
constraintKey = aConstraintKey;
|
453
|
16
|
propertyName = aPropertyName;
|
454
|
16
|
comment = aComment;
|
455
|
16
|
dataType = aDataType;
|
456
|
|
}
|
457
|
|
}
|
458
|
|
|
459
|
|
/**
|
460
|
|
*
|
461
|
|
*/
|
462
|
|
private static class ElementInfo {
|
463
|
|
|
464
|
|
public IElemRefOrDecl elemRefOrDecl;
|
465
|
|
/**
|
466
|
|
* Indicates that the element is already present in a super type.
|
467
|
|
*/
|
468
|
|
public boolean isInherited = false;
|
469
|
|
|
470
|
|
/**
|
471
|
|
* Inidicates that the element is already present in a super type where it
|
472
|
|
* had a maximum occurence of 1.
|
473
|
|
*/
|
474
|
|
public boolean isInheritedSingle = false;
|
475
|
|
|
476
|
|
/**
|
477
|
|
* Indicates that the element had somewhere in the derivation hierarchy
|
478
|
|
* a maximum occurence of 1.
|
479
|
|
*/
|
480
|
|
public boolean isSingle = false;
|
481
|
|
|
482
|
|
/**
|
483
|
|
* Indicates that the element had somewhere in the derivation hierarchy
|
484
|
|
* a maximum number of occurences greater than 1.
|
485
|
|
*/
|
486
|
|
public boolean isMultiple = false;
|
487
|
|
|
488
|
|
/**
|
489
|
|
* Indicates that the element is already present in a super type with a
|
490
|
|
* maximum number of occurences greater than 1.
|
491
|
|
*/
|
492
|
|
public boolean isInheritedMultiple = false;
|
493
|
|
|
494
|
1106
|
public ElementInfo(IElemRefOrDecl anElemRefOrDecl) {
|
495
|
1106
|
elemRefOrDecl = anElemRefOrDecl;
|
496
|
|
}
|
497
|
|
}
|
498
|
|
|
499
|
2888
|
protected String simpleTypeName(IAnyType aType, boolean aUseDataClass) {
|
500
|
2888
|
String res = null;
|
501
|
2888
|
if (!aUseDataClass) {
|
502
|
2866
|
Class c = aType.getSimpleStorageType();
|
503
|
2866
|
if (null != c) {
|
504
|
1603
|
res = ReflectUtil.getTypeName(c);
|
505
|
|
}
|
506
|
|
}
|
507
|
2888
|
if (null == res) {
|
508
|
1285
|
res = interfaceName(aType);
|
509
|
|
}
|
510
|
2888
|
return res;
|
511
|
|
}
|
512
|
|
|
513
|
2840
|
protected String interfaceName(IAnyType aType) {
|
514
|
2840
|
return getBehaviourInterfaceCartridge().getUsableFqName(aType.getInstanceType());
|
515
|
|
}
|
516
|
|
|
517
|
452
|
protected String ssoAccessor(Class aClass) {
|
518
|
|
assert !aClass.isArray();
|
519
|
452
|
String s = aClass.getName();
|
520
|
|
assert !(s.lastIndexOf('$') >= 0);
|
521
|
452
|
String n = s.substring(s.lastIndexOf('.') + 1);
|
522
|
452
|
StringBuffer sb = null;
|
523
|
452
|
if (aClass.isInterface() && n.startsWith("I") && Character.isUpperCase(n.charAt(1))) {
|
524
|
32
|
sb = new StringBuffer(n.substring(1));
|
525
|
|
} else {
|
526
|
420
|
sb = new StringBuffer(n);
|
527
|
|
}
|
528
|
452
|
sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
|
529
|
452
|
return sb.toString();
|
530
|
|
}
|
531
|
|
|
532
|
24
|
protected String simpleStorageObjectTypeName(IAnyType aType) {
|
533
|
24
|
return ReflectUtil.getWrapperClass(aType.getSimpleStorageType()).getName();
|
534
|
|
}
|
535
|
|
|
536
|
|
/**
|
537
|
|
* Get the plural form of a property name. The plural form is constructed
|
538
|
|
* by the following rules: if the property name ends with a "y" and the second
|
539
|
|
* last character is not a vowel then the
|
540
|
|
* "y" is replaced by "ies", if the property name ends with a
|
541
|
|
* "s" then "es" is appended, otherwise a "s" is appended.
|
542
|
|
*
|
543
|
|
* @param aPropertyName <i>(required)</i>.
|
544
|
|
* @return <i>(required)</i>.
|
545
|
|
*/
|
546
|
500
|
protected String pluralForm(String aPropertyName) {
|
547
|
500
|
String res = null;
|
548
|
500
|
if (aPropertyName.endsWith("y") && (aPropertyName.length() > 1)) {
|
549
|
30
|
char c = aPropertyName.charAt(aPropertyName.length() - 2);
|
550
|
30
|
if ((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u')) {
|
551
|
8
|
res = aPropertyName + "s";
|
552
|
|
} else {
|
553
|
22
|
res = aPropertyName.substring(0, aPropertyName.length() - 1) + "ies";
|
554
|
|
}
|
555
|
470
|
} else if (aPropertyName.endsWith("s")) {
|
556
|
30
|
res = aPropertyName + "es";
|
557
|
|
} else {
|
558
|
440
|
res = aPropertyName + "s";
|
559
|
|
}
|
560
|
500
|
return res;
|
561
|
|
}
|
562
|
|
|
563
|
|
}
|
564
|
|
|