Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 291365
Collapse All | Expand All

(-)src/org/eclipse/ocl/ecore/EcoreEvaluationEnvironment.java (-1 / +21 lines)
Lines 1-7 Link Here
1
/**
1
/**
2
 * <copyright>
2
 * <copyright>
3
 *
3
 *
4
 * Copyright (c) 2005, 2008 IBM Corporation and others.
4
 * Copyright (c) 2005, 2008 IBM Corporation, Zeligsoft Inc., and others.
5
 * All rights reserved.   This program and the accompanying materials
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
7
 * which accompanies this distribution, and is available at
Lines 9-14 Link Here
9
 *
9
 *
10
 * Contributors:
10
 * Contributors:
11
 *   IBM - Initial API and implementation
11
 *   IBM - Initial API and implementation
12
 *   Zeligsoft - Bug 255469
12
 *
13
 *
13
 * </copyright>
14
 * </copyright>
14
 *
15
 *
Lines 17-22 Link Here
17
18
18
package org.eclipse.ocl.ecore;
19
package org.eclipse.ocl.ecore;
19
20
21
import java.lang.reflect.InvocationTargetException;
20
import java.lang.reflect.Method;
22
import java.lang.reflect.Method;
21
import java.util.Collection;
23
import java.util.Collection;
22
import java.util.Collections;
24
import java.util.Collections;
Lines 24-29 Link Here
24
import java.util.Map;
26
import java.util.Map;
25
import java.util.Set;
27
import java.util.Set;
26
28
29
import org.eclipse.emf.common.util.BasicEList;
30
import org.eclipse.emf.common.util.ECollections;
27
import org.eclipse.emf.common.util.EList;
31
import org.eclipse.emf.common.util.EList;
28
import org.eclipse.emf.common.util.Enumerator;
32
import org.eclipse.emf.common.util.Enumerator;
29
import org.eclipse.emf.ecore.EClass;
33
import org.eclipse.emf.ecore.EClass;
Lines 35-40 Link Here
35
import org.eclipse.emf.ecore.EReference;
39
import org.eclipse.emf.ecore.EReference;
36
import org.eclipse.emf.ecore.EStructuralFeature;
40
import org.eclipse.emf.ecore.EStructuralFeature;
37
import org.eclipse.emf.ecore.ETypedElement;
41
import org.eclipse.emf.ecore.ETypedElement;
42
import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
38
import org.eclipse.ocl.AbstractEvaluationEnvironment;
43
import org.eclipse.ocl.AbstractEvaluationEnvironment;
39
import org.eclipse.ocl.EvaluationEnvironment;
44
import org.eclipse.ocl.EvaluationEnvironment;
40
import org.eclipse.ocl.LazyExtentMap;
45
import org.eclipse.ocl.LazyExtentMap;
Lines 84-89 Link Here
84
            Object source, Object[] args)
89
            Object source, Object[] args)
85
        throws IllegalArgumentException {
90
        throws IllegalArgumentException {
86
91
92
    	// FIXME: Pull up so that UML environment can benefit. This is only here
93
    	// for now in order to avoid including org.eclipse.ocl in the patch
94
    	if (source instanceof DynamicEObjectImpl) {
95
			EList<Object> arguments = (args.length == 0)
96
				? ECollections.emptyEList()
97
				: new BasicEList.UnmodifiableEList<Object>(args.length, args);
98
99
			try {
100
				return coerceValue(operation, ((EObject) source).eCall(
101
					operation, arguments), true);
102
			} catch (InvocationTargetException e) {
103
				throw new IllegalArgumentException(e);
104
			}
105
    	}
106
    	
87
        // TODO: WBN to pull up createValue to the superclass as a pass-thru
107
        // TODO: WBN to pull up createValue to the superclass as a pass-thru
88
        // so that subclasses don't have to override callOperation
108
        // so that subclasses don't have to override callOperation
89
        return coerceValue(operation, super.callOperation(operation, opcode,
109
        return coerceValue(operation, super.callOperation(operation, opcode,
(-)META-INF/MANIFEST.MF (+2 lines)
Lines 13-19 Link Here
13
Eclipse-LazyStart: true
13
Eclipse-LazyStart: true
14
Bundle-ActivationPolicy: lazy
14
Bundle-ActivationPolicy: lazy
15
Export-Package: org.eclipse.ocl.ecore,
15
Export-Package: org.eclipse.ocl.ecore,
16
 org.eclipse.ocl.ecore.dynamic,
16
 org.eclipse.ocl.ecore.impl,
17
 org.eclipse.ocl.ecore.impl,
17
 org.eclipse.ocl.ecore.internal;x-friends:="org.eclipse.ocl.ecore.tests",
18
 org.eclipse.ocl.ecore.internal;x-friends:="org.eclipse.ocl.ecore.tests",
19
 org.eclipse.ocl.ecore.internal.l10n,
18
 org.eclipse.ocl.ecore.util
20
 org.eclipse.ocl.ecore.util
19
Bundle-RequiredExecutionEnvironment: J2SE-1.5
21
Bundle-RequiredExecutionEnvironment: J2SE-1.5
(-)src/org/eclipse/ocl/ecore/internal/l10n/OCLEcoreMessages.properties (+31 lines)
Added Link Here
1
###############################################################################
2
# Copyright (c) 2008 Zeligsoft Inc. and others.
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
#     Zeligsoft - initial API and implementation
10
#
11
# $Id$
12
#
13
###############################################################################
14
15
#
16
# Indicates an invalid derivation expression for an EStructuralFeature
17
# in the OCL setting delegate annotation
18
#
19
#   0 - the EClass name that owns the feature
20
#   1 - the EStructuralFeature name
21
#   2 - the OCL parser's error message
22
bad_attribute_derivation = Invalid OCL attribute derivation for {0}.{1}: {2}
23
24
#
25
# Indicates an invalid body expression for an EOperation
26
# in the OCL call delegate annotation
27
#
28
#   0 - the EClass name that owns the operation
29
#   1 - the EOperation name
30
#   2 - the OCL parser's error message
31
bad_operation_body = Invalid OCL operation body for {0}.{1}: {2}
(-)src/org/eclipse/ocl/ecore/dynamic/OCLCallDelegate.java (+106 lines)
Added Link Here
1
/**
2
 * <copyright>
3
 * 
4
 * Copyright (c) 2008 Zeligsoft Inc. and others.
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 * 
10
 * Contributors:
11
 *   Zeligsoft - Initial API and implementation
12
 * 
13
 * </copyright>
14
 *
15
 * $Id$
16
 */
17
18
package org.eclipse.ocl.ecore.dynamic;
19
20
import java.lang.reflect.InvocationTargetException;
21
22
import org.eclipse.emf.common.util.EList;
23
import org.eclipse.emf.ecore.EClass;
24
import org.eclipse.emf.ecore.EClassifier;
25
import org.eclipse.emf.ecore.EOperation;
26
import org.eclipse.emf.ecore.EPackage;
27
import org.eclipse.emf.ecore.EParameter;
28
import org.eclipse.emf.ecore.EcorePackage;
29
import org.eclipse.emf.ecore.InternalEObject;
30
import org.eclipse.emf.ecore.util.BasicCallDelegate;
31
import org.eclipse.emf.ecore.util.EcoreUtil;
32
import org.eclipse.ocl.EvaluationEnvironment;
33
import org.eclipse.ocl.ParserException;
34
import org.eclipse.ocl.ecore.OCL;
35
import org.eclipse.ocl.expressions.OCLExpression;
36
37
/**
38
 * An implementation of an operation-call delegate for OCL body expressions.
39
 * 
40
 * @author Christian W. Damus (cdamus)
41
 * 
42
 * @since 1.3
43
 */
44
public class OCLCallDelegate
45
		extends BasicCallDelegate {
46
47
	private OCL ocl;
48
49
	private OCLExpression<EClassifier> body;
50
51
	private ValueConverter converter;
52
53
	/**
54
	 * Initializes me with my operation.
55
	 * 
56
	 * @param operation
57
	 *            the operation that I handle
58
	 * 
59
	 * @throws ParserException
60
	 *             if the operation's OCL body expression is invalid
61
	 */
62
	protected OCLCallDelegate(EOperation operation, OCLCache oclCache)
63
			throws ParserException {
64
65
		super(operation);
66
67
		EClass context = operation.getEContainingClass();
68
		EPackage ePackage = context.getEPackage();
69
70
		this.ocl = oclCache.getOCL(ePackage);
71
72
		OCL.Helper helper = ocl.createOCLHelper();
73
		helper.setOperationContext(context, operation);
74
75
		String expr = EcoreUtil.getAnnotation(operation, EcorePackage.eNS_URI,
76
			"OCL"); //$NON-NLS-1$
77
78
		this.body = helper.createBodyCondition(expr).getSpecification()
79
			.getBodyExpression();
80
81
		this.converter = operation.isMany()
82
			? ValueConverter.LIST
83
			: ValueConverter.VERBATIM;
84
	}
85
86
	@Override
87
	public Object dynamicCall(InternalEObject target, EList<?> arguments)
88
			throws InvocationTargetException {
89
90
		OCL.Query query = ocl.createQuery(body);
91
92
		EList<EParameter> parms = eOperation.getEParameters();
93
		if (!parms.isEmpty()) {
94
			// bind arguments to parameter names
95
			EvaluationEnvironment<EClassifier, ?, ?, ?, ?> env = query
96
				.getEvaluationEnvironment();
97
98
			for (int i = 0; i < parms.size(); i++) {
99
				env.add(parms.get(i).getName(), arguments.get(i));
100
			}
101
		}
102
103
		return converter.convert(ocl, query.evaluate(target));
104
	}
105
	
106
}
(-)src/org/eclipse/ocl/ecore/dynamic/OCLCallDelegateFactory.java (+119 lines)
Added Link Here
1
/**
2
 * <copyright>
3
 * 
4
 * Copyright (c) 2008 Zeligsoft Inc. and others.
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 * 
10
 * Contributors:
11
 *   Zeligsoft - Initial API and implementation
12
 * 
13
 * </copyright>
14
 *
15
 * $Id$
16
 */
17
18
package org.eclipse.ocl.ecore.dynamic;
19
20
import java.lang.reflect.InvocationTargetException;
21
22
import org.eclipse.emf.common.notify.Notification;
23
import org.eclipse.emf.common.notify.impl.AdapterImpl;
24
import org.eclipse.emf.common.util.ECollections;
25
import org.eclipse.emf.common.util.EList;
26
import org.eclipse.emf.ecore.EOperation;
27
import org.eclipse.emf.ecore.EPackage;
28
import org.eclipse.emf.ecore.InternalEObject;
29
import org.eclipse.emf.ecore.resource.Resource;
30
import org.eclipse.emf.ecore.util.BasicCallDelegate;
31
import org.eclipse.ocl.ParserException;
32
import org.eclipse.ocl.ecore.EcoreEnvironmentFactory;
33
import org.eclipse.ocl.ecore.OCL;
34
import org.eclipse.ocl.ecore.internal.OCLEcorePlugin;
35
import org.eclipse.ocl.ecore.internal.l10n.OCLEcoreMessages;
36
37
/**
38
 * Factory for OCL operation-call delegates.
39
 * 
40
 * @author Christian W. Damus (cdamus)
41
 * 
42
 * @since 1.3
43
 */
44
public class OCLCallDelegateFactory
45
		extends AbstractOCLDelegateFactory
46
		implements EOperation.Internal.CallDelegate.Factory {
47
48
	public EOperation.Internal.CallDelegate createCallDelegate(
49
			EOperation operation) {
50
51
		EOperation.Internal.CallDelegate result;
52
53
		try {
54
			result = new OCLCallDelegate(operation, getCache());
55
		} catch (ParserException e) {
56
			// I will not be able to return any values
57
			OCLEcorePlugin.error(1, OCLEcoreMessages.bind(
58
				OCLEcoreMessages.bad_operation_body, new Object[]{
59
					operation.getEContainingClass().getName(),
60
					operation.getName(), e.getLocalizedMessage()}));
61
62
			// so, return a call delegate that has no value, ever
63
			return new BasicCallDelegate(operation) {
64
65
				@Override
66
				public Object dynamicCall(InternalEObject target,
67
						EList<?> arguments)
68
						throws InvocationTargetException {
69
70
					return eOperation.isMany()
71
						? ECollections.EMPTY_ELIST
72
						: null;
73
				}
74
75
			};
76
		}
77
78
		return result;
79
	}
80
81
	/**
82
	 * Creates the OCL environment in which to parse setting delegates for the
83
	 * specified environment. Subclasses may override to create custom
84
	 * environments, but should note that the result is cached.
85
	 * 
86
	 * @param ePackage
87
	 *            an Ecore package for which to create a setting delegate
88
	 *            environment
89
	 * @return the environment
90
	 */
91
	public OCL createOCL(final EPackage ePackage) {
92
		Resource res = ePackage.eResource();
93
		EcoreEnvironmentFactory envFactory;
94
95
		if ((res != null) && (res.getResourceSet() != null)) {
96
			// it's a dynamic package. Use the local package registry
97
			envFactory = new EcoreEnvironmentFactory(res.getResourceSet()
98
				.getPackageRegistry());
99
100
			// and expunge when it's unloaded
101
			res.eAdapters().add(new AdapterImpl() {
102
103
				@Override
104
				public void notifyChanged(Notification msg) {
105
					if ((msg.getFeatureID(Resource.class) == Resource.RESOURCE__IS_LOADED)
106
						&& !msg.getNewBooleanValue()) {
107
						getCache().expunge(ePackage);
108
					}
109
				}
110
			});
111
		} else {
112
			// the shared instance uses the static package registry
113
			envFactory = EcoreEnvironmentFactory.INSTANCE;
114
		}
115
116
		return OCL.newInstance(envFactory);
117
	}
118
119
}
(-)src/org/eclipse/ocl/ecore/dynamic/ValueConverter.java (+61 lines)
Added Link Here
1
/**
2
 * <copyright>
3
 * 
4
 * Copyright (c) 2008 Zeligsoft Inc. and others.
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 * 
10
 * Contributors:
11
 *   Zeligsoft - Initial API and implementation
12
 * 
13
 * </copyright>
14
 *
15
 * $Id$
16
 */
17
18
package org.eclipse.ocl.ecore.dynamic;
19
20
import java.util.Collection;
21
22
import org.eclipse.emf.common.util.BasicEList;
23
import org.eclipse.emf.common.util.ECollections;
24
import org.eclipse.ocl.ecore.OCL;
25
26
/**
27
 * An object that converts values according to their declared multiplicities,
28
 * as collections or not.
29
 * 
30
 * @author Christian W. Damus (cdamus)
31
 * 
32
 * @since 1.3
33
 */
34
interface ValueConverter {
35
36
	ValueConverter VERBATIM = new ValueConverter() {
37
38
		public Object convert(OCL ocl, Object value) {
39
			// no way to report problem to the user in invalid case
40
			return ocl.isInvalid(value)
41
				? null
42
				: value;
43
		}
44
	};
45
46
	ValueConverter LIST = new ValueConverter() {
47
48
		public Object convert(OCL ocl, Object value) {
49
			if (ocl.isInvalid(value)) {
50
				// no way to report specific problem to the user
51
				return ECollections.EMPTY_ELIST;
52
			}
53
54
			Collection<?> collection = (Collection<?>) value;
55
			return new BasicEList.UnmodifiableEList<Object>(collection
56
				.size(), collection.toArray());
57
		}
58
	};
59
60
	Object convert(OCL ocl, Object value);
61
}
(-)src/org/eclipse/ocl/ecore/dynamic/OCLCache.java (+86 lines)
Added Link Here
1
/**
2
 * <copyright>
3
 * 
4
 * Copyright (c) 2008 Zeligsoft Inc. and others.
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 * 
10
 * Contributors:
11
 *   Zeligsoft - Initial API and implementation
12
 * 
13
 * </copyright>
14
 *
15
 * $Id$
16
 */
17
18
package org.eclipse.ocl.ecore.dynamic;
19
20
import java.lang.ref.Reference;
21
22
import org.eclipse.emf.ecore.EPackage;
23
import org.eclipse.ocl.ecore.OCL;
24
25
/**
26
 * A doubly-weak-referenced cache of OCL environments created to handle Ecore
27
 * packages.
28
 * 
29
 * @author Christian W. Damus (cdamus)
30
 * 
31
 * @since 1.3
32
 */
33
final class OCLCache
34
		extends java.util.WeakHashMap<EPackage, Reference<OCL>> {
35
36
	/**
37
	 * My OCL factory.
38
	 */
39
	private final Factory oclFactory;
40
41
	/**
42
	 * Initializes me with a factory that I may use to create OCL environments.
43
	 * 
44
	 * @param oclFactory
45
	 *            my OCL environment factory
46
	 */
47
	OCLCache(Factory oclFactory) {
48
		this.oclFactory = oclFactory;
49
	}
50
51
	protected synchronized OCL getOCL(EPackage ePackage) {
52
		Reference<OCL> result = get(ePackage);
53
54
		if ((result == null) || (result.get() == null)) {
55
			result = new java.lang.ref.WeakReference<OCL>(oclFactory
56
				.createOCL(ePackage));
57
		}
58
59
		put(ePackage, result);
60
61
		return result.get();
62
	}
63
64
	protected synchronized void expunge(EPackage ePackage) {
65
		Reference<OCL> oclRef = get(ePackage);
66
		if (oclRef != null) {
67
			OCL ocl = oclRef.get();
68
69
			if (ocl != null) {
70
				ocl.dispose();
71
			}
72
73
			remove(ePackage);
74
		}
75
	}
76
77
	/**
78
	 * A factory of OCL environment objects.
79
	 * 
80
	 * @author Christian W. Damus (cdamus)
81
	 */
82
	static interface Factory {
83
84
		OCL createOCL(EPackage ePackage);
85
	}
86
}
(-)src/org/eclipse/ocl/ecore/internal/l10n/IMessages.java (+65 lines)
Added Link Here
1
/**
2
 * <copyright>
3
 *
4
 * Copyright (c) 2006, 2008 IBM Corporation, Zeligsoft Inc., and others.
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 *
10
 * Contributors:
11
 *   IBM - Initial API and implementation
12
 *   Zeligsoft - Bug 216701
13
 *
14
 * </copyright>
15
 *
16
 * $Id: IMessages.java,v 1.2 2007/02/14 14:46:07 cdamus Exp $
17
 */
18
package org.eclipse.ocl.ecore.internal.l10n;
19
20
import java.text.MessageFormat;
21
22
/**
23
 * Abstraction of the OSGi runtime's NLS class, to abstract the dependency on
24
 * Eclipse platform.
25
 *
26
 * @author Christian W. Damus (cdamus)
27
 */
28
interface IMessages {
29
	String bind(String message, Object arg);
30
	String bind(String message, Object arg1, Object arg2);
31
	String bind(String message, Object[] args);
32
	
33
	class Default implements IMessages {
34
		public String bind(String message, Object arg) {
35
			return MessageFormat.format(message, new Object[] {arg});
36
		}
37
38
		public String bind(String message, Object arg1, Object arg2) {
39
			return MessageFormat.format(message, new Object[] {arg1, arg2});
40
		}
41
42
		public String bind(String message, Object[] args) {
43
			return MessageFormat.format(message, args);
44
		}
45
	}
46
	
47
	class NLS implements IMessages {
48
		public NLS() {
49
			org.eclipse.osgi.util.NLS.initializeMessages(
50
					OCLEcoreMessages.BUNDLE_NAME, OCLEcoreMessages.class);
51
		}
52
53
		public String bind(String message, Object arg) {
54
			return org.eclipse.osgi.util.NLS.bind(message, arg);
55
		}
56
57
		public String bind(String message, Object arg1, Object arg2) {
58
			return org.eclipse.osgi.util.NLS.bind(message, arg1, arg2);
59
		}
60
61
		public String bind(String message, Object[] args) {
62
			return org.eclipse.osgi.util.NLS.bind(message, args);
63
		}
64
	}
65
}
(-)src/org/eclipse/ocl/ecore/dynamic/AbstractOCLDelegateFactory.java (+81 lines)
Added Link Here
1
/**
2
 * <copyright>
3
 * 
4
 * Copyright (c) 2008 Zeligsoft Inc. and others.
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 * 
10
 * Contributors:
11
 *   Zeligsoft - Initial API and implementation
12
 * 
13
 * </copyright>
14
 *
15
 * $Id$
16
 */
17
18
package org.eclipse.ocl.ecore.dynamic;
19
20
import org.eclipse.emf.common.notify.Notification;
21
import org.eclipse.emf.common.notify.impl.AdapterImpl;
22
import org.eclipse.emf.ecore.EPackage;
23
import org.eclipse.emf.ecore.resource.Resource;
24
import org.eclipse.ocl.ecore.EcoreEnvironmentFactory;
25
import org.eclipse.ocl.ecore.OCL;
26
27
/**
28
 * Partial implementation of a factory of OCL delegates for Ecore features.
29
 * 
30
 * @author Christian W. Damus (cdamus)
31
 * 
32
 * @since 1.3
33
 */
34
abstract class AbstractOCLDelegateFactory
35
		implements OCLCache.Factory {
36
37
	private OCLCache oclCache = new OCLCache(this);
38
39
	protected OCLCache getCache() {
40
		return oclCache;
41
	}
42
43
	/**
44
	 * Creates the OCL environment in which to parse setting delegates for the
45
	 * specified environment. Subclasses may override to create custom
46
	 * environments, but should note that the result is cached.
47
	 * 
48
	 * @param ePackage
49
	 *            an Ecore package for which to create a setting delegate
50
	 *            environment
51
	 * @return the environment
52
	 */
53
	public OCL createOCL(final EPackage ePackage) {
54
		Resource res = ePackage.eResource();
55
		EcoreEnvironmentFactory envFactory;
56
57
		if ((res != null) && (res.getResourceSet() != null)) {
58
			// it's a dynamic package. Use the local package registry
59
			envFactory = new EcoreEnvironmentFactory(res.getResourceSet()
60
				.getPackageRegistry());
61
62
			// and expunge when it's unloaded
63
			res.eAdapters().add(new AdapterImpl() {
64
65
				@Override
66
				public void notifyChanged(Notification msg) {
67
					if ((msg.getFeatureID(Resource.class) == Resource.RESOURCE__IS_LOADED)
68
						&& !msg.getNewBooleanValue()) {
69
						getCache().expunge(ePackage);
70
					}
71
				}
72
			});
73
		} else {
74
			// the shared instance uses the static package registry
75
			envFactory = EcoreEnvironmentFactory.INSTANCE;
76
		}
77
78
		return OCL.newInstance(envFactory);
79
	}
80
81
}
(-)src/org/eclipse/ocl/ecore/dynamic/OCLSettingDelegate.java (+95 lines)
Added Link Here
1
/**
2
 * <copyright>
3
 * 
4
 * Copyright (c) 2008 Zeligsoft Inc. and others.
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 * 
10
 * Contributors:
11
 *   Zeligsoft - Initial API and implementation
12
 * 
13
 * </copyright>
14
 *
15
 * $Id$
16
 */
17
18
package org.eclipse.ocl.ecore.dynamic;
19
20
import org.eclipse.emf.ecore.EClass;
21
import org.eclipse.emf.ecore.EClassifier;
22
import org.eclipse.emf.ecore.EPackage;
23
import org.eclipse.emf.ecore.EStructuralFeature;
24
import org.eclipse.emf.ecore.EcorePackage;
25
import org.eclipse.emf.ecore.InternalEObject;
26
import org.eclipse.emf.ecore.util.BasicSettingDelegate;
27
import org.eclipse.emf.ecore.util.EcoreUtil;
28
import org.eclipse.ocl.ParserException;
29
import org.eclipse.ocl.ecore.OCL;
30
import org.eclipse.ocl.expressions.OCLExpression;
31
32
/**
33
 * An implementation of a setting delegate that computes OCL derived features.
34
 * 
35
 * @author Christian W. Damus (cdamus)
36
 * @since 1.3
37
 */
38
public class OCLSettingDelegate
39
		extends BasicSettingDelegate.Stateless {
40
41
	private OCL ocl;
42
43
	private OCLExpression<EClassifier> derivation;
44
45
	private ValueConverter converter;
46
47
	/**
48
	 * Initializes me with my structural feature.
49
	 * 
50
	 * @param structuralFeature
51
	 *            the structural feature that I handle
52
	 * 
53
	 * @throws ParserException
54
	 *             if the structural feature's OCL derivation is invalid
55
	 */
56
	protected OCLSettingDelegate(EStructuralFeature structuralFeature,
57
			OCLCache oclCache)
58
			throws ParserException {
59
60
		super(structuralFeature);
61
62
		EClass context = structuralFeature.getEContainingClass();
63
		EPackage ePackage = context.getEPackage();
64
65
		this.ocl = oclCache.getOCL(ePackage);
66
67
		OCL.Helper helper = ocl.createOCLHelper();
68
		helper.setAttributeContext(context, structuralFeature);
69
70
		String expr = EcoreUtil.getAnnotation(structuralFeature,
71
			EcorePackage.eNS_URI, "OCL"); //$NON-NLS-1$
72
73
		this.derivation = helper.createDerivedValueExpression(expr)
74
			.getSpecification().getBodyExpression();
75
76
		this.converter = structuralFeature.isMany()
77
			? ValueConverter.LIST
78
			: ValueConverter.VERBATIM;
79
	}
80
81
	@Override
82
	protected Object get(InternalEObject owner, boolean resolve,
83
			boolean coreType) {
84
85
		OCL.Query query = ocl.createQuery(derivation);
86
87
		return converter.convert(ocl, query.evaluate(owner));
88
	}
89
90
	@Override
91
	protected boolean isSet(InternalEObject owner) {
92
		return false; // derived features are, implicitly, never set
93
	}
94
	
95
}
(-)src/org/eclipse/ocl/ecore/internal/l10n/OCLEcoreMessages.java (+103 lines)
Added Link Here
1
/**
2
 * <copyright>
3
 *
4
 * Copyright (c) 2005, 2008 IBM Corporation, Zeligsoft Inc., and others.
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 *
10
 * Contributors:
11
 *   IBM - Initial API and implementation
12
 *   Zeligsoft - Bug 216701
13
 *
14
 * </copyright>
15
 *
16
 * $Id: OCLMessages.java,v 1.6 2007/12/12 22:08:04 cdamus Exp $
17
 */
18
19
package org.eclipse.ocl.ecore.internal.l10n;
20
21
import java.lang.reflect.Field;
22
import java.lang.reflect.Modifier;
23
import java.util.MissingResourceException;
24
import java.util.ResourceBundle;
25
26
/**
27
 * An accessor class for externalized strings.
28
 * 
29
 * @author Christian Vogt (cvogt)
30
 * @since 1.3
31
 */
32
public class OCLEcoreMessages {
33
34
	static final String BUNDLE_NAME = "org.eclipse.ocl.ecore.internal.l10n.OCLMessages"; //$NON-NLS-1$
35
36
	public static String bad_attribute_derivation;
37
	
38
	public static String bad_operation_body;
39
	
40
	private static IMessages messagesImpl;
41
	
42
	public static String bind(String message, Object arg) {
43
		return messagesImpl.bind(message, arg);
44
	}
45
	
46
	public static String bind(String message, Object arg1, Object arg2) {
47
		return messagesImpl.bind(message, arg1, arg2);
48
	}
49
	
50
	public static String bind(String message, Object[] args) {
51
		return messagesImpl.bind(message, args);
52
	}
53
54
	static {
55
		try {
56
			@SuppressWarnings("unchecked")
57
			Class<IMessages> nlsClass = (Class<IMessages>) Class.forName("org.eclipse.ocl.ecore.internal.l10n.IMessages$NLS"); //$NON-NLS-1$
58
			messagesImpl = nlsClass.newInstance();
59
		} catch (NoClassDefFoundError e) {
60
			// expected in non-Eclipse environment
61
		} catch (Exception e) {
62
			// expected in non-Eclipse environment
63
		}
64
		
65
		if (messagesImpl == null) {
66
			// could not find the NLS class.  Try initializing the messages,
67
			//    ourselves
68
			initializeMessages();
69
			messagesImpl = new IMessages.Default();
70
		}
71
	}
72
	
73
	private static void initializeMessages() {
74
		ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME);
75
		int publicStatic = Modifier.PUBLIC | Modifier.STATIC;
76
		
77
		Class<OCLEcoreMessages> clazz = OCLEcoreMessages.class;
78
		
79
		if (bundle != null) {
80
			Field[] fields = clazz.getDeclaredFields();
81
			
82
			for (int i = 0; i < fields.length; i++) {
83
				Field next = fields[i];
84
				
85
				if (((next.getModifiers() & publicStatic) == publicStatic)
86
						&& (next.getType() == String.class)) {
87
					String name = next.getName();
88
					
89
					try {
90
						try {
91
							next.set(null, bundle.getString(name));
92
						} catch (MissingResourceException e) {
93
							// just use its own name, then
94
							next.set(null, "Missing message for key: " + name); //$NON-NLS-1$
95
						}
96
					} catch (Exception e) {
97
						// oh, well.  Can't set a value for this one
98
					}
99
				}
100
			}
101
		}
102
	}
103
}
(-)src/org/eclipse/ocl/ecore/dynamic/OCLSettingDelegateFactory.java (+76 lines)
Added Link Here
1
/**
2
 * <copyright>
3
 * 
4
 * Copyright (c) 2008 Zeligsoft Inc. and others.
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 * 
10
 * Contributors:
11
 *   Zeligsoft - Initial API and implementation
12
 * 
13
 * </copyright>
14
 *
15
 * $Id$
16
 */
17
18
package org.eclipse.ocl.ecore.dynamic;
19
20
import org.eclipse.emf.common.util.ECollections;
21
import org.eclipse.emf.ecore.EStructuralFeature;
22
import org.eclipse.emf.ecore.InternalEObject;
23
import org.eclipse.emf.ecore.util.BasicSettingDelegate;
24
import org.eclipse.ocl.ParserException;
25
import org.eclipse.ocl.ecore.internal.OCLEcorePlugin;
26
import org.eclipse.ocl.ecore.internal.l10n.OCLEcoreMessages;
27
28
/**
29
 * Factory for OCL derived-attribute setting delegates.
30
 * 
31
 * @author Christian W. Damus (cdamus)
32
 * 
33
 * @since 1.3
34
 */
35
public class OCLSettingDelegateFactory
36
extends AbstractOCLDelegateFactory
37
		implements EStructuralFeature.Internal.SettingDelegate.Factory {
38
39
	public EStructuralFeature.Internal.SettingDelegate createSettingDelegate(
40
			EStructuralFeature structuralFeature) {
41
42
		EStructuralFeature.Internal.SettingDelegate result;
43
44
		try {
45
			result = new OCLSettingDelegate(structuralFeature, getCache());
46
		} catch (ParserException e) {
47
			// I will not be able to return any values
48
			OCLEcorePlugin.error(1, OCLEcoreMessages.bind(
49
				OCLEcoreMessages.bad_attribute_derivation, new Object[]{
50
					structuralFeature.getEContainingClass().getName(),
51
					structuralFeature.getName(), e.getLocalizedMessage()}));
52
53
			// so, return a setting delegate that has no value, ever
54
			return new BasicSettingDelegate.Stateless(structuralFeature) {
55
56
				@Override
57
				protected Object get(InternalEObject owner, boolean resolve,
58
						boolean coreType) {
59
60
					return eStructuralFeature.isMany()
61
						? ECollections.EMPTY_ELIST
62
						: null;
63
				}
64
65
				@Override
66
				protected boolean isSet(InternalEObject owner) {
67
					return false;
68
				}
69
70
			};
71
		}
72
73
		return result;
74
	}
75
76
}
(-)src/org/eclipse/ocl/ecore/tests/AbstractTestSuite.java (-1 / +2 lines)
Lines 9-15 Link Here
9
 *
9
 *
10
 * Contributors:
10
 * Contributors:
11
 *   IBM - Initial API and implementation
11
 *   IBM - Initial API and implementation
12
 *   Zeligsoft - Bugs 243079, 244948, 244886, 245619
12
 *   Zeligsoft - Bugs 243079, 244948, 244886, 245619, 216701
13
 *
13
 *
14
 * </copyright>
14
 * </copyright>
15
 *
15
 *
Lines 197-202 Link Here
197
		result.addTest(RegressionTest.suite());
197
		result.addTest(RegressionTest.suite());
198
		result.addTest(EcoreEnvironmentTest.suite());
198
		result.addTest(EcoreEnvironmentTest.suite());
199
        result.addTest(ExtensibilityTest.suite());
199
        result.addTest(ExtensibilityTest.suite());
200
        result.addTest(OCLSettingDelegateTest.suite());
200
		result.addTest(ValidationTest.suite());
201
		result.addTest(ValidationTest.suite());
201
		result.addTest(ProblemOptionTest.suite());
202
		result.addTest(ProblemOptionTest.suite());
202
		result.addTest(ParsingOptionsTest.suite());
203
		result.addTest(ParsingOptionsTest.suite());
(-)src/org/eclipse/ocl/ecore/tests/OCLSettingDelegateTest.java (+331 lines)
Added Link Here
1
/**
2
 * <copyright>
3
 * 
4
 * Copyright (c) 2008 Zeligsoft Inc. and others.
5
 * All rights reserved.   This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 * 
10
 * Contributors:
11
 *   Zeligsoft - Initial API and implementation
12
 * 
13
 * </copyright>
14
 *
15
 * $Id$
16
 */
17
18
package org.eclipse.ocl.ecore.tests;
19
20
import java.lang.reflect.InvocationTargetException;
21
import java.util.Arrays;
22
import java.util.Map;
23
24
import junit.framework.Test;
25
import junit.framework.TestSuite;
26
27
import org.eclipse.emf.common.util.BasicEList;
28
import org.eclipse.emf.common.util.ECollections;
29
import org.eclipse.emf.common.util.EList;
30
import org.eclipse.emf.common.util.Enumerator;
31
import org.eclipse.emf.common.util.URI;
32
import org.eclipse.emf.ecore.EAttribute;
33
import org.eclipse.emf.ecore.EClass;
34
import org.eclipse.emf.ecore.EEnum;
35
import org.eclipse.emf.ecore.EFactory;
36
import org.eclipse.emf.ecore.EObject;
37
import org.eclipse.emf.ecore.EOperation;
38
import org.eclipse.emf.ecore.EPackage;
39
import org.eclipse.emf.ecore.EReference;
40
import org.eclipse.emf.ecore.EStructuralFeature;
41
import org.eclipse.emf.ecore.resource.Resource;
42
import org.eclipse.emf.ecore.resource.ResourceSet;
43
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
44
import org.eclipse.ocl.ecore.dynamic.OCLCallDelegateFactory;
45
import org.eclipse.ocl.ecore.dynamic.OCLSettingDelegateFactory;
46
47
/**
48
 * Tests for the OCL setting delegate implementation.
49
 * 
50
 * @author Christian W. Damus (cdamus)
51
 */
52
@SuppressWarnings("nls")
53
public class OCLSettingDelegateTest
54
		extends AbstractTestSuite {
55
56
	private ResourceSet rset;
57
58
	private Resource testResource;
59
60
	private EPackage companyPackage;
61
62
	private EFactory companyFactory;
63
64
	private EClass companyClass;
65
66
	private EAttribute companyName;
67
68
	private EReference companyEmployees;
69
70
	private EAttribute companySize;
71
72
	private EClass employeeClass;
73
74
	private EAttribute employeeName;
75
76
	private EReference employeeManager;
77
78
	private EReference employeeDirectReports;
79
80
	private EReference employeeAllReports;
81
82
	private EOperation employeeReportsTo;
83
84
	private EEnum sizeKind;
85
86
	private Enumerator sizeSmall;
87
88
	private Enumerator sizeMedium;
89
90
	private Enumerator sizeLarge;
91
92
	private EObject acme;
93
94
	private Map<String, EObject> employees;
95
96
	public OCLSettingDelegateTest(String name) {
97
		super(name);
98
	}
99
100
	public static Test suite() {
101
		return new TestSuite(OCLSettingDelegateTest.class,
102
			"OCL Setting Delegate Tests");
103
	}
104
105
	public void test_eattributeDerivation() {
106
		assertSame(sizeSmall, size(acme));
107
108
		// add a load of employees
109
		EList<EObject> emps = employees(acme);
110
		for (int i = 0; i < 60; i++) {
111
			emps.add(companyFactory.create(employeeClass));
112
		}
113
114
		assertSame(sizeMedium, size(acme));
115
116
		// and another bunch
117
		for (int i = 0; i < 1000; i++) {
118
			emps.add(companyFactory.create(employeeClass));
119
		}
120
121
		assertSame(sizeLarge, size(acme));
122
	}
123
124
	public void test_ereferenceDerivation() {
125
		EList<EObject> amyReports = directReports(employee("Amy"));
126
		assertEquals(3, amyReports.size());
127
		assertTrue(amyReports.contains(employee("Bob")));
128
		assertTrue(amyReports.contains(employee("Jane")));
129
		assertTrue(amyReports.contains(employee("Fred")));
130
131
		EList<EObject> bobReports = directReports(employee("Bob"));
132
		assertEquals(2, bobReports.size());
133
		assertTrue(bobReports.contains(employee("Norbert")));
134
		assertTrue(bobReports.contains(employee("Sally")));
135
136
		EList<EObject> sallyReports = directReports(employee("Sally"));
137
		assertEquals(0, sallyReports.size());
138
	}
139
140
	public void test_allInstances() {
141
		EList<EObject> amyAllReports = allReports(employee("Amy"));
142
		assertEquals(5, amyAllReports.size());
143
		assertTrue(amyAllReports.contains(employee("Bob")));
144
		assertTrue(amyAllReports.contains(employee("Jane")));
145
		assertTrue(amyAllReports.contains(employee("Fred")));
146
		assertTrue(amyAllReports.contains(employee("Norbert")));
147
		assertTrue(amyAllReports.contains(employee("Sally")));
148
149
		// change the set of all instances of Employee
150
		set(create(acme, companyEmployees, employeeClass, "Manuel"),
151
			employeeManager, employee("Bob"));
152
153
		amyAllReports = allReports(employee("Amy"));
154
		assertEquals(6, amyAllReports.size());
155
		assertTrue(amyAllReports.contains(employee("Manuel")));
156
	}
157
158
	public void test_operationCall() {
159
		EObject amy = employee("Amy");
160
161
		// allReports is implemented using reportsTo()
162
		EList<EObject> amyAllReports = allReports(amy);
163
		assertEquals(5, amyAllReports.size());
164
165
		for (EObject next : amyAllReports) {
166
			assertTrue(this.<Boolean> call(next, employeeReportsTo, amy));
167
		}
168
	}
169
170
	//
171
	// Test framework
172
	//
173
174
	@Override
175
	protected void setUp()
176
			throws Exception {
177
178
		super.setUp();
179
180
		EStructuralFeature.Internal.SettingDelegate.Factory.Registry.INSTANCE
181
			.registerFactory("org.eclipse.ocl.ecore.OCL",
182
				new OCLSettingDelegateFactory());
183
		EOperation.Internal.CallDelegate.Factory.Registry.INSTANCE
184
			.registerFactory("org.eclipse.ocl.ecore.OCL",
185
				new OCLCallDelegateFactory());
186
187
		rset = new ResourceSetImpl();
188
		testResource = rset.getResource(URI.createPlatformPluginURI(
189
			"/org.eclipse.ocl.ecore.tests/model/TestCompany.xmi", true), true);
190
191
		acme = testResource.getContents().get(0);
192
193
		companyClass = acme.eClass();
194
		companyPackage = companyClass.getEPackage();
195
		companyFactory = companyPackage.getEFactoryInstance();
196
197
		companyName = (EAttribute) companyClass.getEStructuralFeature("name");
198
		companyEmployees = (EReference) companyClass
199
			.getEStructuralFeature("employees");
200
		companySize = (EAttribute) companyClass.getEStructuralFeature("size");
201
202
		employeeClass = companyEmployees.getEReferenceType();
203
		employeeName = (EAttribute) employeeClass.getEStructuralFeature("name");
204
		employeeManager = (EReference) employeeClass
205
			.getEStructuralFeature("manager");
206
		employeeDirectReports = (EReference) employeeClass
207
			.getEStructuralFeature("directReports");
208
		employeeAllReports = (EReference) employeeClass
209
			.getEStructuralFeature("allReports");
210
		employeeReportsTo = employeeClass.getEOperations().get(0);
211
212
		sizeKind = (EEnum) companySize.getEAttributeType();
213
		sizeSmall = sizeKind.getEEnumLiteral("small");
214
		sizeMedium = sizeKind.getEEnumLiteral("medium");
215
		sizeLarge = sizeKind.getEEnumLiteral("large");
216
217
		employees = new java.util.HashMap<String, EObject>();
218
	}
219
220
	@Override
221
	protected void tearDown()
222
			throws Exception {
223
224
		for (Resource next : rset.getResources()) {
225
			next.unload();
226
		}
227
		rset.getResources().clear();
228
		rset = null;
229
		testResource = null;
230
		companyPackage = null;
231
		companyFactory = null;
232
		employees = null;
233
234
		EOperation.Internal.CallDelegate.Factory.Registry.INSTANCE
235
			.deregisterFactory("org.eclipse.ocl.ecore.OCL");
236
		EStructuralFeature.Internal.SettingDelegate.Factory.Registry.INSTANCE
237
			.deregisterFactory("org.eclipse.ocl.ecore.OCL");
238
239
		super.tearDown();
240
	}
241
242
	EObject employee(String name) {
243
		EObject result = employees.get(name);
244
		if (result == null) {
245
			EList<EObject> emps = get(acme, companyEmployees);
246
			for (EObject next : emps) {
247
				if (name.equals(name(next))) {
248
					result = next;
249
					employees.put(name, result);
250
					break;
251
				}
252
			}
253
		}
254
255
		return result;
256
	}
257
258
	String name(EObject employeeOrCompany) {
259
		EAttribute name = employeeClass.isInstance(employeeOrCompany)
260
			? employeeName
261
			: companyName;
262
		return get(employeeOrCompany, name);
263
	}
264
265
	EObject manager(EObject employee) {
266
		return get(employee, employeeManager);
267
	}
268
269
	EList<EObject> directReports(EObject employee) {
270
		return get(employee, employeeDirectReports);
271
	}
272
273
	EList<EObject> allReports(EObject employee) {
274
		return get(employee, employeeAllReports);
275
	}
276
277
	EList<EObject> employees(EObject company) {
278
		return get(company, companyEmployees);
279
	}
280
281
	Enumerator size(EObject company) {
282
		return get(company, companySize);
283
	}
284
285
	@SuppressWarnings("unchecked")
286
	<T> T get(EObject owner, EStructuralFeature feature) {
287
		return (T) owner.eGet(feature);
288
	}
289
290
	void set(EObject owner, EStructuralFeature feature, Object value) {
291
		owner.eSet(feature, value);
292
	}
293
294
	void add(EObject owner, EStructuralFeature feature, Object value) {
295
		this.<EList<Object>> get(owner, feature).add(value);
296
	}
297
298
	EObject create(EObject owner, EReference containment, EClass type,
299
			String name) {
300
		EObject result = companyFactory.create(type);
301
302
		if (containment.isMany()) {
303
			add(owner, containment, result);
304
		} else {
305
			set(owner, containment, result);
306
		}
307
308
		if (name != null) {
309
			set(result, type.getEStructuralFeature("name"), name);
310
		}
311
312
		return result;
313
	}
314
315
	<T> EList<T> list(T... element) {
316
		return new BasicEList<T>(Arrays.asList(element));
317
	}
318
319
	@SuppressWarnings("unchecked")
320
	<T> T call(EObject target, EOperation operation, Object... arguments) {
321
		try {
322
			return (T) target.eCall(operation, (arguments.length == 0)
323
				? ECollections.<Object> emptyEList()
324
				: new BasicEList.UnmodifiableEList<Object>(arguments.length,
325
					arguments));
326
		} catch (InvocationTargetException e) {
327
			fail("Failed to call operation: " + e.getLocalizedMessage());
328
			return null;
329
		}
330
	}
331
}
(-)model/SettingDelegateTest.ecore (+58 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<ecore:EPackage xmi:version="2.0"
3
    xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="settingtest"
5
    nsURI="http://www.eclipse.org/ocl/test/2008/SettingDelegate" nsPrefix="st">
6
  <eClassifiers xsi:type="ecore:EClass" name="Company">
7
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
8
    <eStructuralFeatures xsi:type="ecore:EReference" name="employees" upperBound="-1"
9
        eType="#//Employee" containment="true" eOpposite="#//Employee/company"/>
10
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="size" lowerBound="1" eType="#//CompanySizeKind"
11
        changeable="false" volatile="true" transient="true" derived="true">
12
      <eAnnotations source="http://www.eclipse.org/emf/2002/Ecore">
13
        <details key="settingDelegate" value="org.eclipse.ocl.ecore.OCL"/>
14
        <details key="OCL" value="let table : Set(Tuple(range : Sequence(Integer), size : CompanySizeKind)) =&#xD;    Set{Tuple{range=Sequence{0..49}, size=CompanySizeKind::small},&#xD;         Tuple{range=Sequence{50..999}, size=CompanySizeKind::medium},&#xD;         Tuple{range=Sequence{1000..1000000}, size=CompanySizeKind::large}} in&#xD;table->any(range->includes(employees->size())).size"/>
15
      </eAnnotations>
16
    </eStructuralFeatures>
17
  </eClassifiers>
18
  <eClassifiers xsi:type="ecore:EClass" name="Employee">
19
    <eOperations name="reportsTo" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean">
20
      <eAnnotations source="http://www.eclipse.org/emf/2002/Ecore">
21
        <details key="callDelegate" value="org.eclipse.ocl.ecore.OCL"/>
22
        <details key="OCL" value="self.reportingChain->includes(manager)"/>
23
      </eAnnotations>
24
      <eParameters name="manager" eType="#//Employee"/>
25
    </eOperations>
26
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
27
    <eStructuralFeatures xsi:type="ecore:EReference" name="manager" eType="#//Employee"/>
28
    <eStructuralFeatures xsi:type="ecore:EReference" name="company" lowerBound="1"
29
        eType="#//Company" eOpposite="#//Company/employees"/>
30
    <eStructuralFeatures xsi:type="ecore:EReference" name="directReports" upperBound="-1"
31
        eType="#//Employee" changeable="false" volatile="true" transient="true" derived="true">
32
      <eAnnotations source="http://www.eclipse.org/emf/2002/Ecore">
33
        <details key="settingDelegate" value="org.eclipse.ocl.ecore.OCL"/>
34
        <details key="OCL" value="company.employees->select(manager = self)"/>
35
      </eAnnotations>
36
    </eStructuralFeatures>
37
    <eStructuralFeatures xsi:type="ecore:EReference" name="allReports" ordered="false"
38
        upperBound="-1" eType="#//Employee" changeable="false" volatile="true" transient="true"
39
        derived="true">
40
      <eAnnotations source="http://www.eclipse.org/emf/2002/Ecore">
41
        <details key="settingDelegate" value="org.eclipse.ocl.ecore.OCL"/>
42
        <details key="OCL" value="Employee.allInstances()->select(reportsTo(self))"/>
43
      </eAnnotations>
44
    </eStructuralFeatures>
45
    <eStructuralFeatures xsi:type="ecore:EReference" name="reportingChain" upperBound="-1"
46
        eType="#//Employee" changeable="false" volatile="true" transient="true" derived="true">
47
      <eAnnotations source="http://www.eclipse.org/emf/2002/Ecore">
48
        <details key="settingDelegate" value="org.eclipse.ocl.ecore.OCL"/>
49
        <details key="OCL" value="if (manager.oclIsUndefined()) then&#xD;    OrderedSet{}&#xD;else&#xD;    manager.reportingChain->prepend(manager)&#xD;endif"/>
50
      </eAnnotations>
51
    </eStructuralFeatures>
52
  </eClassifiers>
53
  <eClassifiers xsi:type="ecore:EEnum" name="CompanySizeKind">
54
    <eLiterals name="small"/>
55
    <eLiterals name="medium" value="1"/>
56
    <eLiterals name="large" value="2"/>
57
  </eClassifiers>
58
</ecore:EPackage>
(-)model/TestCompany.xmi (+9 lines)
Added Link Here
1
<?xml version="1.0" encoding="ASCII"?>
2
<st:Company xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:st="http://www.eclipse.org/ocl/test/2008/SettingDelegate" xsi:schemaLocation="http://www.eclipse.org/ocl/test/2008/SettingDelegate SettingDelegateTest.ecore" name="Acme">
3
  <employees name="Bob" manager="//@employees.3"/>
4
  <employees name="Jane" manager="//@employees.3"/>
5
  <employees name="Fred" manager="//@employees.3"/>
6
  <employees name="Amy"/>
7
  <employees name="Norbert" manager="//@employees.0"/>
8
  <employees name="Sally" manager="//@employees.0"/>
9
</st:Company>

Return to bug 291365