Package: AnyServices$1

AnyServices$1

nameinstructionbranchcomplexitylinemethod
compare(IService, IService)
M: 24 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
{...}
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2015 Obeo.
3: * All rights reserved. This program and the accompanying materials
4: * are made available under the terms of the Eclipse Public License v1.0
5: * which accompanies this distribution, and is available at
6: * http://www.eclipse.org/legal/epl-v10.html
7: *
8: * Contributors:
9: * Obeo - initial API and implementation
10: *******************************************************************************/
11: package org.eclipse.acceleo.query.services;
12:
13: import java.lang.reflect.Method;
14: import java.util.ArrayList;
15: import java.util.Collection;
16: import java.util.Collections;
17: import java.util.Comparator;
18: import java.util.Iterator;
19: import java.util.LinkedHashSet;
20: import java.util.List;
21: import java.util.Set;
22:
23: import org.eclipse.acceleo.annotations.api.documentation.Documentation;
24: import org.eclipse.acceleo.annotations.api.documentation.Example;
25: import org.eclipse.acceleo.annotations.api.documentation.Other;
26: import org.eclipse.acceleo.annotations.api.documentation.Param;
27: import org.eclipse.acceleo.annotations.api.documentation.ServiceProvider;
28: import org.eclipse.acceleo.query.ast.Call;
29: import org.eclipse.acceleo.query.runtime.IReadOnlyQueryEnvironment;
30: import org.eclipse.acceleo.query.runtime.IService;
31: import org.eclipse.acceleo.query.runtime.IValidationResult;
32: import org.eclipse.acceleo.query.runtime.impl.AbstractServiceProvider;
33: import org.eclipse.acceleo.query.runtime.impl.JavaMethodService;
34: import org.eclipse.acceleo.query.runtime.impl.Nothing;
35: import org.eclipse.acceleo.query.runtime.impl.ValidationServices;
36: import org.eclipse.acceleo.query.validation.type.ClassType;
37: import org.eclipse.acceleo.query.validation.type.EClassifierType;
38: import org.eclipse.acceleo.query.validation.type.IType;
39: import org.eclipse.emf.common.util.Enumerator;
40: import org.eclipse.emf.ecore.EClass;
41: import org.eclipse.emf.ecore.EClassifier;
42: import org.eclipse.emf.ecore.EDataType;
43: import org.eclipse.emf.ecore.EEnum;
44: import org.eclipse.emf.ecore.EEnumLiteral;
45: import org.eclipse.emf.ecore.EObject;
46: import org.eclipse.emf.ecore.EPackage;
47:
48: //@formatter:off
49: @ServiceProvider(
50:         value = "Services available for all types"
51: )
52: //@formatter:on
53: @SuppressWarnings({"checkstyle:javadocmethod", "checkstyle:javadoctype" })
54: public class AnyServices extends AbstractServiceProvider {
55:
56:         /**
57:          * Line separator constant.
58:          */
59:         private static final String LINE_SEP = System.getProperty("line.separator");
60:
61:         /**
62:          * The {@link IReadOnlyQueryEnvironment}.
63:          */
64:         private final IReadOnlyQueryEnvironment queryEnvironment;
65:
66:         /**
67:          * Constructor.
68:          *
69:          * @param queryEnvironment
70:          * the {@link IReadOnlyQueryEnvironment}
71:          */
72:         public AnyServices(IReadOnlyQueryEnvironment queryEnvironment) {
73:                 this.queryEnvironment = queryEnvironment;
74:         }
75:
76:         @Override
77:         protected IService getService(Method publicMethod) {
78:                 final IService result;
79:
80:                 if ("oclAsType".equals(publicMethod.getName())) {
81:                         result = new OCLAsTypeService(publicMethod, this);
82:                 } else {
83:                         result = new JavaMethodService(publicMethod, this);
84:                 }
85:
86:                 return result;
87:         }
88:
89:         // @formatter:off
90:         @Documentation(
91:                 value = "Indicates whether the object \"o1\" i\"the same as the object \"o2\". For more " +
92:          "information refer to the Object#equals(Object) method.",
93:          params = {
94:                         @Param(name = "o1", value = "The object to compare for equality"),
95:                         @Param(name = "o2", value = "The reference object with which to compare")
96:                 },
97:                 result = "true\" if the object \"o1\" is the same as the object \"o2\", " +
98:                  "\"false\" otherwise",
99:                 examples = {
100:                         @Example(expression = "'Hello'.equals('World')", result = "false"),
101:                         @Example(expression = "'Hello'.equals('Hello')", result = "true")
102:                 }
103:         )
104:         // @formatter:on
105:         public Boolean equals(Object o1, Object o2) {
106:                 final boolean result;
107:
108:                 if (o1 == null) {
109:                         result = o2 == null;
110:                 } else {
111:                         result = o1.equals(o2);
112:                 }
113:
114:                 return Boolean.valueOf(result);
115:         }
116:
117:         // @formatter:off
118:         @Documentation(
119:                 value = "Indicates whether the object \"o1\" is a different object from the object \"o2\".",
120:                 params = {
121:                         @Param(name = "o1", value = "The object to compare"),
122:                         @Param(name = "o2", value = "The reference object with which to compare")
123:                 },
124:                 result = "\"true\" if the object \"o1\" is not the same as the object \"o2\", " +
125:                                  "\"false\" otherwise.",
126:                 examples = {
127:                         @Example(expression = "'Hello'.differs('World')", result = "true"),
128:                         @Example(expression = "'Hello'.differs('Hello')", result = "false")
129:                 }
130:         )
131:         // @formatter:on
132:         public Boolean differs(Object o1, Object o2) {
133:                 return Boolean.valueOf(!equals(o1, o2));
134:         }
135:
136:         // @formatter:off
137:         @Documentation(
138:                 value = "Returns the concatenation of self (as a String) and the given string \"s\".",
139:                 params = {
140:                         @Param(name = "self", value = "The current object at the end of which to append \"s\"."),
141:                         @Param(name = "s", value = "The string we want to append at the end of the current object's string representation.")
142:                 },
143:                 result = "The string representation of self for which we added the string \"s\".",
144:                 examples = {
145:                         @Example(expression = "42.add(' times')", result = "'42 times'")
146:                 }
147:         )
148:         // @formatter:on
149:         public String add(Object self, String s) {
150:                 final String result;
151:
152:                 if (s == null) {
153:                         result = toString(self);
154:                 } else {
155:                         result = toString(self) + s;
156:                 }
157:
158:                 return result;
159:         }
160:
161:         // @formatter:off
162:         @Documentation(
163:                 value = "Returns the concatenation of the current string and the given object \"any\" (as a String).",
164:                 params = {
165:                         @Param(name = "self", value = "The current string."),
166:                         @Param(name = "any", value = "The object we want to append, as a string, at the end of the current string.")
167:                 },
168:                 result = "The current string with the object \"any\" appended (as a String).",
169:                 examples = {
170:                         @Example(expression = "'times '.add(42)", result = "'times 42'")
171:                 }
172:         )
173:         // @formatter:on
174:         public String add(String self, Object any) {
175:                 final String result;
176:
177:                 if (self == null) {
178:                         result = toString(any);
179:                 } else {
180:                         result = self + toString(any);
181:                 }
182:
183:                 return result;
184:         }
185:
186:         // @formatter:off
187:         @Documentation(
188:                 value = "Casts the current object to the given type.",
189:                 params = {
190:                         @Param(name = "object", value = "The object to cast"),
191:                         @Param(name = "type", value = "The type to cast the object to")
192:                 },
193:                 result = "The current object cast to a \"type\"",
194:                 examples = {
195:                         @Example(
196:                                 expression = "anEPackage.oclAsType(ecore::EPackage)", result = "anEPackage",
197:                                 others = {
198:                                         @Other(
199:                                                 language = Other.ACCELEO_3, expression = "anEPackage.oclAsType(ecore::EPackage)", result = "anEPackage"
200:                                         )
201:                                 }
202:                         ),
203:                         @Example(
204:                                 expression = "anEPackage.oclAsType(ecore::EClass)", result = "anEPackage",
205:                                 others = {
206:                                         @Other(
207:                                                 language = Other.ACCELEO_3, expression = "anEPackage.oclAsType(ecore::EClass)", result = "oclInvalid"
208:                                         )
209:                                 }
210:                         ),
211:                 },
212:                 comment = "Contrary to Acceleo 3, the type is ignored, the given object will be returned directly."
213:         )
214:         // @formatter:on
215:         public Object oclAsType(Object object, Object type) {
216:                 if (oclIsKindOf(object, type)) {
217:                         return object;
218:                 }
219:                 throw new ClassCastException(object + " cannot be cast to " + type);
220:         }
221:
222:         // @formatter:off
223:         @Documentation(
224:                 value = "Evaluates to \"true\" if the type of the object o1 conforms to the type \"classifier\". That is, " +
225:                                 "o1 is of type \"classifier\" or a subtype of \"classifier\".",
226:                 params = {
227:                         @Param(name = "object", value = "The reference Object we seek to test."),
228:                         @Param(name = "type", value = "The expected supertype classifier.")
229:                 },
230:                 result = "\"true\" if the object o1 is a kind of the classifier, \"false\" otherwise.",
231:                 examples = {
232:                         @Example(expression = "anEPackage.oclIsKindOf(ecore::EPackage)", result = "true"),
233:                         @Example(expression = "anEPackage.oclIsKindOf(ecore::ENamedElement)", result = "true")
234:                 }
235:         )
236:         // @formatter:on
237:         public Boolean oclIsKindOf(Object object, Object type) {
238:                 Boolean result;
239:                 if (object == null && type != null) {
240:                         // OCL considers "null" (OclVoid) to be compatible with everything.
241:                         // AQL considers it incompatible with anything.
242:                         result = false;
243:                 } else if (type instanceof EClass) {
244:                         EClass eClass = (EClass)type;
245:                         if (object instanceof EObject) {
246:                                 result = eClass.isInstance(object);
247:                         } else {
248:                                 result = false;
249:                         }
250:                 } else if (type instanceof EEnum) {
251:                         if (object instanceof EEnumLiteral) {
252:                                 result = ((EEnumLiteral)object).getEEnum().equals(type);
253:                         } else if (object instanceof Enumerator) {
254:                                 EEnumLiteral literal = ((EEnum)type).getEEnumLiteral(((Enumerator)object).getName());
255:                                 result = literal.getEEnum().equals(type);
256:                         } else {
257:                                 result = false;
258:                         }
259:                 } else if (type instanceof EDataType) {
260:                         result = ((EDataType)type).isInstance(object);
261:                 } else if (object != null && type instanceof Class<?>) {
262:                         result = ((Class<?>)type).isInstance(object);
263:                 } else {
264:                         result = false;
265:                 }
266:                 return result;
267:         }
268:
269:         // @formatter:off
270:         @Documentation(
271:                 value = "Evaluates to \"true\" if the object o1 if of the type \"classifier\" but not a subtype of the " +
272:                                 "\"classifier\".",
273:                 params = {
274:                         @Param(name = "object", value = "The reference Object we seek to test."),
275:                         @Param(name = "type", value = "The expected type classifier.")
276:                 },
277:                 result = "\"true\" if the object o1 is a type of the classifier, \"false\" otherwise.",
278:                 examples = {
279:                         @Example(expression = "anEPackage.oclIsKindOf(ecore::EPackage)", result = "true"),
280:                         @Example(expression = "anEPackage.oclIsKindOf(ecore::ENamedElement)", result = "false")
281:                 }
282:         )
283:         // @formatter:on
284:         public Boolean oclIsTypeOf(Object object, Object type) {
285:                 Boolean result;
286:                 if (object == null && type != null) {
287:                         // OCL considers "null" (OclVoid) to be compatible with everything.
288:                         // AQL considers it incompatible with anything.
289:                         result = false;
290:                 } else if (type instanceof EClass) {
291:                         EClass eClass = (EClass)type;
292:                         if (object instanceof EObject) {
293:                                 result = eClass == ((EObject)object).eClass();
294:                         } else {
295:                                 result = false;
296:                         }
297:                 } else if (type instanceof EEnum) {
298:                         if (object instanceof EEnumLiteral) {
299:                                 result = ((EEnumLiteral)object).getEEnum().equals(type);
300:                         } else if (object instanceof Enumerator) {
301:                                 EEnumLiteral literal = ((EEnum)type).getEEnumLiteral(((Enumerator)object).getName());
302:                                 result = literal.getEEnum().equals(type);
303:                         } else {
304:                                 result = false;
305:                         }
306:                 } else if (type instanceof EDataType) {
307:                         result = ((EDataType)type).isInstance(object);
308:                 } else if (object != null && type instanceof Class<?>) {
309:                         result = ((Class<?>)type).equals(object.getClass());
310:                 } else {
311:                         result = false;
312:                 }
313:                 return result;
314:         }
315:
316:         // @formatter:off
317:         @Documentation(
318:                 value = "Returns a string representation of the current object.",
319:                 params = {
320:                         @Param(name = "self", value = "The current object")
321:                 },
322:                 result = "a String representation of the given Object. For Collections, this will be the concatenation of " +
323:                                  "all contained Objects' toString.",
324:                 examples = {
325:                         @Example(expression = "42.toString()", result = "'42'")
326:                 }
327:         )
328:         // @formatter:on
329:         public String toString(Object object) {
330:                 final StringBuffer buffer = new StringBuffer();
331:                 if (object instanceof Collection<?>) {
332:                         final Iterator<?> childrenIterator = ((Collection<?>)object).iterator();
333:                         while (childrenIterator.hasNext()) {
334:                                 buffer.append(toString(childrenIterator.next()));
335:                         }
336:                 } else if (object != null && !(object instanceof Nothing)) {
337:                         final String toString = object.toString();
338:                         if (toString != null) {
339:                                 buffer.append(toString);
340:                         }
341:                 }
342:                 // else return empty String
343:                 return buffer.toString();
344:         }
345:
346:         // @formatter:off
347:         @Documentation(
348:                 value = "Returns a string representation of the current environment.",
349:                 params = {
350:                         @Param(name = "self", value = "The current object")
351:                 },
352:                 result = "a string representation of the current environment.",
353:                 examples = {
354:                         @Example(expression = "42.trace()", result = "'Metamodels:\n\thttp://www.eclipse.org/emf/2002/Ecore\n" +
355:                                         "Services:\n\torg.eclipse.acceleo.query.services.AnyServices\n\t\tpublic java.lang.String org." +
356:                                         "eclipse.acceleo.query.services.AnyServices.add(java.lang.Object,java.lang.String)\n\t\t...\nreceiver: 42\n'")
357:                 }
358:         )
359:         // @formatter:on
360:         public String trace(Object object) {
361:                 final StringBuilder result = new StringBuilder();
362:
363:                 result.append("Metamodels:" + LINE_SEP);
364:                 for (EPackage ePgk : queryEnvironment.getEPackageProvider().getRegisteredEPackages()) {
365:                         result.append("\t" + ePgk.getNsURI() + LINE_SEP);
366:                 }
367:                 result.append("Services:" + LINE_SEP);
368:                 final List<IService> services = new ArrayList<IService>(queryEnvironment.getLookupEngine()
369:                                 .getRegisteredServices());
370:                 Collections.sort(services, new Comparator<IService>() {
371:
372:                         /**
373:                          * {@inheritDoc}
374:                          *
375:                          * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
376:                          */
377:                         @Override
378:                         public int compare(IService service1, IService service2) {
379:                                 final int result;
380:
381:•                                if (service1.getPriority() < service2.getPriority()) {
382:                                         result = -1;
383:•                                } else if (service1.getPriority() > service2.getPriority()) {
384:                                         result = 1;
385:                                 } else {
386:                                         result = service1.getName().compareTo(service2.getName());
387:                                 }
388:                                 return result;
389:                         }
390:
391:                 });
392:                 for (IService service : services) {
393:                         result.append("\t\t" + service.getLongSignature() + LINE_SEP);
394:                 }
395:                 result.append("receiver: ");
396:                 result.append(toString(object) + LINE_SEP);
397:
398:                 return result.toString();
399:         }
400:
401:         private static class OCLAsTypeService extends FilterService {
402:                 public OCLAsTypeService(Method publicMethod, Object serviceInstance) {
403:                         super(publicMethod, serviceInstance);
404:                 }
405:
406:                 @Override
407:                 public Set<IType> getType(Call call, ValidationServices services, IValidationResult validationResult,
408:                                 IReadOnlyQueryEnvironment environment, List<IType> argTypes) {
409:                         final Set<IType> result = new LinkedHashSet<IType>();
410:
411:                         final IType receiverType = argTypes.get(0);
412:                         final IType filterType = argTypes.get(1);
413:                         if (services.lower(receiverType, filterType) != null) {
414:                                 Object resultType = filterType.getType();
415:                                 if (resultType instanceof EClassifier) {
416:                                         result.add(new EClassifierType(environment, (EClassifier)resultType));
417:                                 } else if (resultType instanceof Class) {
418:                                         result.add(new ClassType(environment, (Class<?>)resultType));
419:                                 } else if (resultType != null) {
420:                                         result.add(services.nothing("Unknown type %s", resultType));
421:                                 } else {
422:                                         result.add(services.nothing("Unknown type %s", "null"));
423:                                 }
424:                         } else {
425:                                 if (receiverType instanceof EClassifierType
426:                                                 && !environment.getEPackageProvider().isRegistered(
427:                                                                 ((EClassifierType)receiverType).getType())) {
428:                                         result.add(services.nothing("%s is not registered within the current environment.",
429:                                                         receiverType));
430:                                 } else if (filterType instanceof EClassifierType
431:                                                 && !environment.getEPackageProvider().isRegistered(
432:                                                                 ((EClassifierType)filterType).getType())) {
433:                                         result.add(services.nothing("%s is not registered within the current environment.",
434:                                                         filterType));
435:                                 } else {
436:                                         result.add(services
437:                                                         .nothing("%s is not compatible with type %s", receiverType, filterType));
438:                                 }
439:                         }
440:
441:                         return result;
442:                 }
443:         }
444: }