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 245446
Collapse All | Expand All

(-)src/org/eclipse/emf/workspace/tests/AbstractEMFOperationTest.java (-2 / +63 lines)
Lines 9-16 Link Here
9
 *
9
 *
10
 * Contributors:
10
 * Contributors:
11
 *   IBM - Initial API and implementation
11
 *   IBM - Initial API and implementation
12
 *   Zeligsoft - Bugs 218276, 245419, 245393, 250253
12
 *   Zeligsoft - Bugs 218276, 245419, 245393, 250253, 247691 (restore method accessibility)
13
 *   IBM - Bug 245393
13
 *   IBM - Bugs 245393, 247691
14
 *
14
 *
15
 * </copyright>
15
 * </copyright>
16
 *
16
 *
Lines 18-23 Link Here
18
 */
18
 */
19
package org.eclipse.emf.workspace.tests;
19
package org.eclipse.emf.workspace.tests;
20
20
21
import java.lang.reflect.Method;
22
import java.util.Collections;
21
import java.util.Map;
23
import java.util.Map;
22
24
23
import junit.framework.Test;
25
import junit.framework.Test;
Lines 962-967 Link Here
962
			l.uninstall(domain);
964
			l.uninstall(domain);
963
		}
965
		}
964
	}
966
	}
967
    
968
    /**
969
	 * Tests that child operations reuse their parent's transaction when the parent 
970
	 * has the {@link Transaction#OPTION_VALIDATE_EDIT} option, but the child does not.
971
	 */
972
    public void test_inheritValidateEditOption_247691() {
973
974
		final CompositeEMFOperation outer = new CompositeEMFOperation(domain,
975
			"outer", //$NON-NLS-1$
976
			Collections.singletonMap(Transaction.OPTION_VALIDATE_EDIT,
977
				Boolean.TRUE));
978
979
		outer.setTransactionNestingEnabled(false);
980
981
		AbstractEMFOperation inner = new AbstractEMFOperation(domain, "inner") { //$NON-NLS-1$
982
983
			@Override
984
			public boolean canExecute() {
985
				return true;
986
			}
987
988
			@Override
989
			protected IStatus doExecute(IProgressMonitor monitor,
990
					IAdaptable info)
991
					throws ExecutionException {
992
993
				Method getTransactionMethod = null;
994
				
995
				try {
996
					getTransactionMethod = AbstractEMFOperation.class
997
						.getDeclaredMethod("getTransaction", new Class[0]); //$NON-NLS-1$
998
					getTransactionMethod.setAccessible(true);
999
					Object outerTransaction = getTransactionMethod.invoke(
1000
						outer, new Object[0]);
1001
					Object innerTransaction = getTransactionMethod.invoke(this,
1002
						new Object[0]);
1003
					assertTrue("Should have reused the parent transaction", //$NON-NLS-1$
1004
						innerTransaction == null
1005
							|| innerTransaction == outerTransaction);
1006
					return Status.OK_STATUS;
1007
1008
				} catch (Exception e) {
1009
					throw new ExecutionException(e.getMessage(), e);
1010
				} finally {
1011
					if (getTransactionMethod != null) {
1012
						getTransactionMethod.setAccessible(false);
1013
					}
1014
				}
1015
			}
1016
		};
1017
1018
		outer.add(inner);
1019
1020
		try {
1021
			outer.execute(new NullProgressMonitor(), null);
1022
		} catch (ExecutionException e) {
1023
			fail("Unexpected exception: " + e.getLocalizedMessage()); //$NON-NLS-1$
1024
		}
1025
	}
965
	
1026
	
966
	//
1027
	//
967
	// Fixtures
1028
	// Fixtures
(-)src/org/eclipse/emf/transaction/util/TransactionUtil.java (-1 / +27 lines)
Lines 1-7 Link Here
1
/**
1
/**
2
 * <copyright>
2
 * <copyright>
3
 *
3
 *
4
 * Copyright (c) 2006, 2007 IBM Corporation and others.
4
 * Copyright (c) 2006, 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 245446
12
 *
13
 *
13
 * </copyright>
14
 * </copyright>
14
 *
15
 *
Lines 352-355 Link Here
352
    	
353
    	
353
    	return (RunnableWithResult<T>) domain.createPrivilegedRunnable(runnable);
354
    	return (RunnableWithResult<T>) domain.createPrivilegedRunnable(runnable);
354
    }
355
    }
356
    
357
	/**
358
	 * Gets the best transaction-option registry available for the specified
359
	 * editing <tt>domain</tt>. Usually, it will be a registry that is local to
360
	 * that domain, but it may be the
361
	 * {@linkplain Transaction.OptionMetadata.Registry#INSTANCE shared instance}
362
	 * under extreme circumstances.
363
	 * 
364
	 * @param domain
365
	 *            an editing domain
366
	 * @return its transaction options registry, never <code>null</code>
367
	 * 
368
	 * @since 1.3
369
	 */
370
	public static Transaction.OptionMetadata.Registry getTransactionOptionRegistry(
371
			TransactionalEditingDomain domain) {
372
		Transaction.OptionMetadata.Registry result = getAdapter(domain,
373
			Transaction.OptionMetadata.Registry.class);
374
375
		if (result == null) {
376
			result = Transaction.OptionMetadata.Registry.INSTANCE;
377
		}
378
379
		return result;
380
	}
355
}
381
}
(-)src/org/eclipse/emf/transaction/impl/TransactionImpl.java (-18 / +12 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 145877, 250253
12
 *   Zeligsoft - Bugs 145877, 250253, 245446
13
 *
13
 *
14
 * </copyright>
14
 * </copyright>
15
 *
15
 *
Lines 832-857 Link Here
832
	private void inheritOptions(Transaction parent) {
832
	private void inheritOptions(Transaction parent) {
833
        
833
        
834
	    // if we have no parent transaction, then we are a root and we "inherit"
834
	    // if we have no parent transaction, then we are a root and we "inherit"
835
	    // the editing domain's default transaction options
835
	    // the editing domain's default transaction options.  In the root case,
836
        Map<?, ?> parentOptions = (parent == null) ?
836
		// we don't consider whether an option is hereditary because, of course,
837
		// we aren't actually inheriting it from any other transaction
838
		final boolean isRoot = parent == null;
839
        Map<?, ?> parentOptions = isRoot ?
837
        	getDefaultOptions(getEditingDomain()) : parent.getOptions();
840
        	getDefaultOptions(getEditingDomain()) : parent.getOptions();
838
        
841
        
839
        if (parentOptions != null) {
842
        if (parentOptions != null) {
840
            for (Map.Entry<?, ?> next : parentOptions.entrySet()) {
843
			Transaction.OptionMetadata.Registry reg = TransactionUtil
841
                Object option = next.getKey();
844
				.getTransactionOptionRegistry(getEditingDomain());
842
                
845
			
843
                if (ALLOW_CHANGE_PROPAGATION_BLOCKING.equals(option)) {
846
            for (Object option : parentOptions.keySet()) {
844
                    // Do not inherit the allow block option if we have the
847
				reg.getOptionMetadata(option).inherit(parentOptions,
845
                    // block option applied
848
					mutableOptions, isRoot);
846
                    if (!mutableOptions.containsKey(BLOCK_CHANGE_PROPAGATION)) {
847
                        mutableOptions.put(option, next.getValue());
848
                    }
849
                } else if (BLOCK_CHANGE_PROPAGATION.equals(option)) {
850
                    // don't inherit the block option!
851
                } else if (!mutableOptions.containsKey(option)) {
852
                    // overridden by child transaction options
853
                    mutableOptions.put(option, next.getValue());
854
                }
855
            }            
849
            }            
856
        }
850
        }
857
	}
851
	}
(-)src/org/eclipse/emf/transaction/impl/TransactionalEditingDomainImpl.java (-2 / +35 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 177642, 145877
12
 *   Zeligsoft - Bugs 177642, 145877, 245446
13
 *
13
 *
14
 * </copyright>
14
 * </copyright>
15
 *
15
 *
Lines 56-61 Link Here
56
import org.eclipse.emf.transaction.internal.Tracing;
56
import org.eclipse.emf.transaction.internal.Tracing;
57
import org.eclipse.emf.transaction.internal.l10n.Messages;
57
import org.eclipse.emf.transaction.internal.l10n.Messages;
58
import org.eclipse.emf.transaction.util.Adaptable;
58
import org.eclipse.emf.transaction.util.Adaptable;
59
import org.eclipse.emf.transaction.util.BasicTransactionOptionMetadataRegistry;
59
import org.eclipse.emf.transaction.util.Lock;
60
import org.eclipse.emf.transaction.util.Lock;
60
import org.eclipse.emf.transaction.util.TransactionUtil;
61
import org.eclipse.emf.transaction.util.TransactionUtil;
61
62
Lines 68-73 Link Here
68
 * <ul>
69
 * <ul>
69
 *   <li>{@link TransactionalEditingDomain.DefaultOptions}</li>
70
 *   <li>{@link TransactionalEditingDomain.DefaultOptions}</li>
70
 *   <li>{@link TransactionalEditingDomain.Lifecycle} (since 1.3)</li>
71
 *   <li>{@link TransactionalEditingDomain.Lifecycle} (since 1.3)</li>
72
 *   <li>{@link Transaction.Option.Registry} (since 1.3)</li>
71
 * </ul>
73
 * </ul>
72
 *
74
 *
73
 * @author Christian W. Damus (cdamus)
75
 * @author Christian W. Damus (cdamus)
Lines 112-117 Link Here
112
	    TransactionImpl.DEFAULT_UNDO_REDO_OPTIONS);
114
	    TransactionImpl.DEFAULT_UNDO_REDO_OPTIONS);
113
	
115
	
114
	private LifecycleImpl lifecycle;
116
	private LifecycleImpl lifecycle;
117
	private Transaction.OptionMetadata.Registry optionMetadata;
115
	
118
	
116
	/**
119
	/**
117
	 * Initializes me with my adapter factory, command stack, and resource set.
120
	 * Initializes me with my adapter factory, command stack, and resource set.
Lines 931-937 Link Here
931
	public <T> T getAdapter(Class<? extends T> adapterType) {
934
	public <T> T getAdapter(Class<? extends T> adapterType) {
932
	    T result;
935
	    T result;
933
	    
936
	    
934
	    if (adapterType == DefaultOptions.class) {
937
	    if (adapterType == Transaction.OptionMetadata.Registry.class) {
938
	        result = (T) getOptionMetadata();
939
	    } else if (adapterType == DefaultOptions.class) {
935
	        result = (T) this;
940
	        result = (T) this;
936
	    } else if (adapterType == Lifecycle.class) {
941
	    } else if (adapterType == Lifecycle.class) {
937
	        result = (T) getLifecycle();
942
	        result = (T) getLifecycle();
Lines 1014-1019 Link Here
1014
		return new LifecycleImpl();
1019
		return new LifecycleImpl();
1015
	}
1020
	}
1016
	
1021
	
1022
	/**
1023
	 * Obtains my lazily-created transaction option metadata registry.
1024
	 * 
1025
	 * @return my option metadata registry
1026
	 * 
1027
	 * @since 1.3
1028
	 */
1029
	protected synchronized final Transaction.OptionMetadata.Registry getOptionMetadata() {
1030
		if (optionMetadata == null) {
1031
			optionMetadata = createOptionMetadataRegistry();
1032
		}
1033
1034
		return optionMetadata;
1035
	}
1036
1037
	/**
1038
	 * Creates a new transaction option metadata registry.
1039
	 * Subclasses may override to create their own implementation, although it
1040
	 * would hardly seem interesting to do so.
1041
	 * 
1042
	 * @return a new option metadata registry
1043
	 * 
1044
	 * @since 1.3
1045
	 */
1046
	protected Transaction.OptionMetadata.Registry createOptionMetadataRegistry() {
1047
		return new BasicTransactionOptionMetadataRegistry();
1048
	}
1049
	
1017
	//
1050
	//
1018
	// Nested classes
1051
	// Nested classes
1019
	//
1052
	//
(-)src/org/eclipse/emf/transaction/Transaction.java (-2 / +224 lines)
Lines 1-7 Link Here
1
/**
1
/**
2
 * <copyright>
2
 * <copyright>
3
 *
3
 *
4
 * Copyright (c) 2005, 2007 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 245446
12
 *
13
 *
13
 * </copyright>
14
 * </copyright>
14
 *
15
 *
Lines 19-24 Link Here
19
import java.util.Map;
20
import java.util.Map;
20
21
21
import org.eclipse.core.runtime.IStatus;
22
import org.eclipse.core.runtime.IStatus;
23
import org.eclipse.emf.transaction.impl.TransactionImpl;
24
import org.eclipse.emf.transaction.internal.AllowChangePropagationBlockingOption;
25
import org.eclipse.emf.transaction.internal.BlockChangePropagationOption;
26
import org.eclipse.emf.transaction.internal.ValidateEditOption;
27
import org.eclipse.emf.transaction.util.BasicTransactionOptionMetadata;
28
import org.eclipse.emf.transaction.util.BasicTransactionOptionMetadataRegistry;
22
import org.eclipse.emf.transaction.util.ValidateEditSupport;
29
import org.eclipse.emf.transaction.util.ValidateEditSupport;
23
30
24
31
Lines 187-193 Link Here
187
	
194
	
188
	/**
195
	/**
189
	 * Obtains the special options with which I was created.  The options
196
	 * Obtains the special options with which I was created.  The options
190
	 * (map keys) are defined by the {@link TransactionalEditingDomain} interface.
197
	 * (map keys) are defined by the {@link #OPTION_NO_NOTIFICATIONS Transaction}
198
	 * interface.
191
	 * 
199
	 * 
192
	 * @return an unmodifiable view of my options
200
	 * @return an unmodifiable view of my options
193
	 */
201
	 */
Lines 310-313 Link Here
310
	 * @return my status, most interesting after I have closed
318
	 * @return my status, most interesting after I have closed
311
	 */
319
	 */
312
	public IStatus getStatus();
320
	public IStatus getStatus();
321
	
322
	//
323
	// Nested types
324
	//
325
	
326
	/**
327
	 * <p>
328
	 * An optional interface that allows clients to query certain meta-data
329
	 * about transaction options.
330
	 * </p>
331
	 * <p>
332
	 * This interface is not intended to be implemented by clients.  Extend the
333
	 * {@link BasicTransactionOptionMetadata} class, instead.
334
	 * </p>
335
	 * 
336
	 * @noimplement This interface is not intended to be implemented by clients.
337
	 * 
338
	 * @author Christian W. Damus (cdamus)
339
	 * 
340
	 * @since 1.3
341
	 * 
342
	 * @see BasicTransactionOptionMetadata
343
	 */
344
	interface OptionMetadata {
345
346
		/**
347
		 * Obtains the key of the option that I describe. This is the key that
348
		 * would be used in the options map of a transaction.
349
		 * 
350
		 * @return my option
351
		 */
352
		Object getOption();
353
354
		/**
355
		 * <p>
356
		 * Queries whether the specified option is a tag, meaning that it adorns
357
		 * a transaction with client-specific information but that it does not
358
		 * otherwise affect the semantics (or behaviour) of the transaction.
359
		 * </p>
360
		 * <p>
361
		 * Unrecognized options are assumed to be tags, because a transaction
362
		 * would not be able to interpret their meaning.
363
		 * </p>
364
		 * 
365
		 * @return <code>true</code> if the option key is a tag option or if it
366
		 *         is not recognized by this meta-data instance;
367
		 *         <code>false</code> if it is recognized and is known not to be
368
		 *         a tag
369
		 */
370
		boolean isTag();
371
372
		/**
373
		 * <p>
374
		 * Queries whether the specified option is inherited by nested
375
		 * transactions.
376
		 * </p>
377
		 * <p>
378
		 * Unrecognized options are assumed to be inherited.
379
		 * </p>
380
		 * 
381
		 * @return <code>true</code> if the option is inherited or if it is not
382
		 *         recognized; <code>false</code> if it is not inherited
383
		 */
384
		boolean isHereditary();
385
386
		/**
387
		 * <p>
388
		 * Obtains the type value of an option.
389
		 * </p>
390
		 * <p>
391
		 * The type of an unrecognized option is assumed to be {@link Object}.
392
		 * </p>
393
		 * 
394
		 * @return the default value of the option, or <code>Object</code> if it
395
		 *         is not known
396
		 */
397
		Class<?> getType();
398
399
		/**
400
		 * <p>
401
		 * Obtains the default value of an option.
402
		 * </p>
403
		 * <p>
404
		 * The default value of an unrecognized option is assumed to be
405
		 * <code>null</code>.
406
		 * </p>
407
		 * 
408
		 * @return the default value of the option, or <code>null</code> if it
409
		 *         is not known
410
		 */
411
		Object getDefaultValue();
412
413
		/**
414
		 * Gets the value (implicit/default or explicit) of my option in the
415
		 * specified map.
416
		 * 
417
		 * @param options
418
		 *            an options map
419
		 * 
420
		 * @return my value in the map
421
		 */
422
		Object getValue(Map<?, ?> options);
423
		
424
		/**
425
		 * Queries whether the specified map has a setting for my option.
426
		 * 
427
		 * @param options
428
		 *            an options map
429
		 * @return whether it has a setting for my option
430
		 */
431
		boolean isSet(Map<?, ?> options);
432
433
		/**
434
		 * Queries whether the specified options maps have the same value of my
435
		 * option, whether that be implicit or explicit. That is, this method
436
		 * accounts for default values and such complex cases as the
437
		 * {@link Transaction#OPTION_VALIDATE_EDIT} in which values of two
438
		 * different types may mean the same thing.
439
		 * 
440
		 * @param options1
441
		 *            an options map
442
		 * @param options2
443
		 *            another options map
444
		 * 
445
		 * @return whether the two maps have the same setting of my option
446
		 */
447
		boolean sameSetting(Map<?, ?> options1, Map<?, ?> options2);
448
449
		/**
450
		 * Updates the options map of a child transaction to inherit the setting
451
		 * in a parent transaction, if it is a hereditary option and the child
452
		 * does not already have a setting for it.
453
		 * 
454
		 * @param parentOptions
455
		 *            the options map to inherit a value from. It is conceivable
456
		 *            that inheritance of an option may depend on more than one
457
		 *            option in this parent map
458
		 * @param childOptions
459
		 *            the map that is to inherit the option setting
460
		 * @param force
461
		 *            whether to inherit the option anyway despite that it is
462
		 *            not hereditary. This is used for application of default
463
		 *            options, and can be ignored by the implementor if
464
		 *            necessary. Also, clients must not use this parameter to
465
		 *            attempt to override an existing child setting; a
466
		 *            well-behaved option will not do that
467
		 */
468
		void inherit(Map<?, ?> parentOptions, Map<Object, Object> childOptions,
469
				boolean force);
470
		
471
		/**
472
		 * <p>
473
		 * A registry of metadata describing transaction options.  The default
474
		 * implementation of the {@link TransactionalEditingDomain} interface
475
		 * provides a transaction option registry as an adapter.
476
		 * </p>
477
		 * <p>
478
		 * This interface is not intended to be implemented by clients.
479
		 * </p>
480
		 * 
481
		 * @noimplement This interface is not intended to be implemented by
482
		 *              clients.
483
		 * @author Christian W. Damus (cdamus)
484
		 * 
485
		 * @since 1.3
486
		 */
487
		interface Registry {
488
489
			/**
490
			 * The shared transaction option metadata registry.
491
			 */
492
			Registry INSTANCE = new BasicTransactionOptionMetadataRegistry(null) {
493
494
				private static final long serialVersionUID = 1L;
495
496
				{
497
					// the options that we know
498
					register(BasicTransactionOptionMetadata.newBoolean(
499
						Transaction.OPTION_NO_NOTIFICATIONS, false));
500
					register(BasicTransactionOptionMetadata.newBoolean(
501
						Transaction.OPTION_NO_TRIGGERS, false));
502
					register(BasicTransactionOptionMetadata.newBoolean(
503
						Transaction.OPTION_NO_VALIDATION, false));
504
					register(BasicTransactionOptionMetadata.newBoolean(
505
						Transaction.OPTION_NO_UNDO, false));
506
					register(BasicTransactionOptionMetadata.newBoolean(
507
						Transaction.OPTION_UNPROTECTED, false));
508
					register(BasicTransactionOptionMetadata.newBoolean(
509
						Transaction.OPTION_IS_UNDO_REDO_TRANSACTION, false));
510
511
					register(new ValidateEditOption());
512
					register(new BasicTransactionOptionMetadata(
513
						Transaction.OPTION_VALIDATE_EDIT_CONTEXT));
514
515
					register(BasicTransactionOptionMetadata.newBoolean(
516
						TransactionImpl.OPTION_IS_TRIGGER_TRANSACTION, false));
517
					register(new AllowChangePropagationBlockingOption());
518
					register(new BlockChangePropagationOption());
519
				}
520
			};
521
522
			/**
523
			 * Obtains a metadata object describing the specified transaction
524
			 * option. For unrecognized options, a default meta-data is provided
525
			 * that gives reasonable answers.
526
			 * 
527
			 * @param option
528
			 *            an option key
529
			 * @return the option meta-data (never <code>null</code>)
530
			 */
531
			Transaction.OptionMetadata getOptionMetadata(Object option);
532
		}
533
534
	}
313
}
535
}
(-)src/org/eclipse/emf/transaction/internal/AllowChangePropagationBlockingOption.java (+56 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.emf.transaction.internal;
19
20
import java.util.Map;
21
22
import org.eclipse.emf.transaction.impl.TransactionImpl;
23
import org.eclipse.emf.transaction.util.BasicTransactionOptionMetadata;
24
25
26
/**
27
 * Metadata implementation for the non-trivial complexity of the
28
 * {@link TransactionImpl#ALLOW_CHANGE_PROPAGATION_BLOCKING} transaction option.
29
 * 
30
 * @author Christian W. Damus (cdamus)
31
 * 
32
 * @since 1.3
33
 */
34
public class AllowChangePropagationBlockingOption
35
		extends BasicTransactionOptionMetadata {
36
37
	/**
38
	 * Initializes me.
39
	 */
40
	public AllowChangePropagationBlockingOption() {
41
		super(TransactionImpl.ALLOW_CHANGE_PROPAGATION_BLOCKING, false, true,
42
			Boolean.class, Boolean.FALSE);
43
	}
44
45
	@Override
46
	public void inherit(Map<?, ?> parentOptions,
47
			Map<Object, Object> childOptions, boolean force) {
48
49
        // do not inherit the allow block option if the block option is
50
        // already applied
51
        if (!childOptions.containsKey(TransactionImpl.BLOCK_CHANGE_PROPAGATION)) {
52
            childOptions.put(getOption(), getValue(parentOptions));
53
        }
54
	}
55
56
}
(-)src/org/eclipse/emf/transaction/util/BasicTransactionOptionMetadata.java (+157 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.emf.transaction.util;
19
20
import java.util.Map;
21
22
import org.eclipse.emf.transaction.Transaction;
23
24
/**
25
 * A simple implementation of the {@link Transaction.OptionMetadata} interface.
26
 * 
27
 * @author Christian W. Damus (cdamus)
28
 * 
29
 * @since 1.3
30
 */
31
public class BasicTransactionOptionMetadata
32
		implements Transaction.OptionMetadata {
33
34
	private final Object option;
35
36
	private boolean isTag;
37
38
	private boolean isHereditary;
39
40
	private Class<?> type;
41
42
	private Object defaultValue;
43
44
	/**
45
	 * Initializes me with my option key.
46
	 * 
47
	 * @param option
48
	 *            my option key
49
	 */
50
	public BasicTransactionOptionMetadata(Object option) {
51
		this(option, true, true, Object.class, null);
52
	}
53
54
	/**
55
	 * Initializes me with my option key and other details.
56
	 * 
57
	 * @param option
58
	 *            my option key
59
	 * @param isTag
60
	 *            whether the option is a tag
61
	 * @param isHereditary
62
	 *            whether the option is inherited
63
	 * @param type
64
	 *            the option type
65
	 * @param defaultValue
66
	 *            the option's defaul value
67
	 */
68
	public BasicTransactionOptionMetadata(Object option, boolean isTag,
69
			boolean isHereditary, Class<?> type, Object defaultValue) {
70
		this.option = option;
71
		this.isTag = isTag;
72
		this.isHereditary = isHereditary;
73
		this.type = type;
74
		this.defaultValue = defaultValue;
75
	}
76
77
	public Object getDefaultValue() {
78
		return defaultValue;
79
	}
80
81
	public final Object getOption() {
82
		return option;
83
	}
84
85
	public Class<?> getType() {
86
		return type;
87
	}
88
89
	public boolean isHereditary() {
90
		return isHereditary;
91
	}
92
93
	public boolean isTag() {
94
		return isTag;
95
	}
96
	
97
	public Object getValue(Map<?, ?> options) {
98
		return options.containsKey(option)
99
			? options.get(option)
100
			: getDefaultValue();
101
	}
102
	
103
	public boolean isSet(Map<?, ?> options) {
104
		return options.containsKey(option);
105
	}
106
	
107
	public boolean sameSetting(Map<?, ?> options1, Map<?, ?> options2) {
108
		return safeEquals(getValue(options1), getValue(options2));
109
	}
110
	
111
	public void inherit(Map<?, ?> parentOptions,
112
			Map<Object, Object> childOptions, boolean force) {
113
114
		if ((force || isHereditary()) && !isSet(childOptions)) {
115
			childOptions.put(option, getValue(parentOptions));
116
		}
117
	}
118
	
119
	protected boolean safeEquals(Object a, Object b) {
120
		return (a == null)
121
			? b == null
122
			: a.equals(b);
123
	}
124
	
125
	protected Class<?> safeClass(Object o) {
126
		return (o == null)
127
			? Void.class
128
			: o.getClass();
129
	}
130
	
131
	/**
132
	 * Creates a new transaction option meta-data for an heritary, non-tag,
133
	 * boolean-valued option.
134
	 * 
135
	 * @param option
136
	 *            the option key
137
	 * @param defaultValue
138
	 *            the option's default value
139
	 * 
140
	 * @return the option meta-data
141
	 */
142
	public static Transaction.OptionMetadata newBoolean(Object option,
143
			boolean defaultValue) {
144
		
145
		return new BasicTransactionOptionMetadata(option, false, true,
146
			Boolean.class, Boolean.valueOf(defaultValue));
147
	}
148
	
149
	@Override
150
	public String toString() {
151
		return "Option[key=" + getOption() //$NON-NLS-1$
152
			+ ", isTag=" + isTag() //$NON-NLS-1$
153
			+ ", isHereditary=" + isHereditary() //$NON-NLS-1$
154
			+ ", type=" + getType().getName() //$NON-NLS-1$
155
			+ ", default=" + getDefaultValue() + ']'; //$NON-NLS-1$
156
	}
157
}
(-)src/org/eclipse/emf/transaction/internal/BlockChangePropagationOption.java (+52 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.emf.transaction.internal;
19
20
import java.util.Map;
21
22
import org.eclipse.emf.transaction.impl.TransactionImpl;
23
import org.eclipse.emf.transaction.util.BasicTransactionOptionMetadata;
24
25
26
/**
27
 * Metadata implementation for the non-trivial complexity of the
28
 * {@link TransactionImpl#BLOCK_CHANGE_PROPAGATION} transaction option.
29
 * 
30
 * @author Christian W. Damus (cdamus)
31
 * 
32
 * @since 1.3
33
 */
34
public class BlockChangePropagationOption
35
		extends BasicTransactionOptionMetadata {
36
37
	/**
38
	 * Initializes me.
39
	 */
40
	public BlockChangePropagationOption() {
41
		super(TransactionImpl.BLOCK_CHANGE_PROPAGATION, false, false,
42
			Boolean.class, Boolean.FALSE);
43
	}
44
45
	@Override
46
	public void inherit(Map<?, ?> parentOptions,
47
			Map<Object, Object> childOptions, boolean force) {
48
49
        // never inherit this option, even when requested to force
50
	}
51
52
}
(-)src/org/eclipse/emf/transaction/util/BasicTransactionOptionMetadataRegistry.java (+91 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.emf.transaction.util;
19
20
import org.eclipse.emf.transaction.Transaction;
21
22
/**
23
 * A simple implementation of the transaction option metadata registry API.
24
 * 
25
 * @author Christian W. Damus (cdamus)
26
 * 
27
 * @since 1.3
28
 */
29
public class BasicTransactionOptionMetadataRegistry
30
		extends java.util.HashMap<Object, Transaction.OptionMetadata>
31
		implements Transaction.OptionMetadata.Registry {
32
33
	private static final long serialVersionUID = 1L;
34
35
	private final Transaction.OptionMetadata.Registry delegate;
36
37
	/**
38
	 * Initializes me with the shared registry instance as my delegate.
39
	 */
40
	public BasicTransactionOptionMetadataRegistry() {
41
		this(Transaction.OptionMetadata.Registry.INSTANCE);
42
	}
43
44
	/**
45
	 * Initializes me with a registry to which I delegate options that I do not
46
	 * provide for.
47
	 * 
48
	 * @param delegate
49
	 *            my delegate
50
	 */
51
	protected BasicTransactionOptionMetadataRegistry(
52
			Transaction.OptionMetadata.Registry delegate) {
53
		this.delegate = delegate;
54
	}
55
56
	public Transaction.OptionMetadata getOptionMetadata(Object option) {
57
		Transaction.OptionMetadata result = get(option);
58
59
		if (result == null) {
60
			result = delegatedGetOptionMetadata(option);
61
		}
62
		
63
		if (result == null) {
64
			// create an ephemeral default metadata
65
			result = new BasicTransactionOptionMetadata(option);
66
		}
67
68
		return result;
69
	}
70
71
	protected Transaction.OptionMetadata delegatedGetOptionMetadata(
72
			Object option) {
73
		
74
		return (delegate == null)
75
			? null
76
			: delegate.getOptionMetadata(option);
77
	}
78
79
	/**
80
	 * Registers an option metadata descriptor.
81
	 * 
82
	 * @param metadata
83
	 *            the option metadata to register
84
	 * @return the metadata displaced by the new object, if previously we had a
85
	 *         descriptor for the same option, otherwise <code>null</code>
86
	 */
87
	public Transaction.OptionMetadata register(
88
			Transaction.OptionMetadata metadata) {
89
		return put(metadata.getOption(), metadata);
90
	}
91
}
(-)src/org/eclipse/emf/transaction/internal/ValidateEditOption.java (+72 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.emf.transaction.internal;
19
20
import java.util.Map;
21
22
import org.eclipse.emf.transaction.Transaction;
23
import org.eclipse.emf.transaction.util.BasicTransactionOptionMetadata;
24
import org.eclipse.emf.transaction.util.ValidateEditSupport;
25
26
/**
27
 * Metadata implementation for the non-trivial complexity of the
28
 * {@link Transaction#OPTION_VALIDATE_EDIT} transaction option.
29
 * 
30
 * @author Christian W. Damus (cdamus)
31
 * 
32
 * @since 1.3
33
 */
34
public class ValidateEditOption
35
		extends BasicTransactionOptionMetadata {
36
37
	/**
38
	 * Initializes me.
39
	 */
40
	public ValidateEditOption() {
41
		super(Transaction.OPTION_VALIDATE_EDIT, true, false, Object.class,
42
			Boolean.FALSE);
43
	}
44
45
	@Override
46
	public boolean sameSetting(Map<?, ?> options1, Map<?, ?> options2) {
47
48
		Object value1 = getValue(options1);
49
		Object value2 = getValue(options2);
50
		boolean result = safeEquals(value1, value2);
51
52
		if (!result) {
53
			// they may, yet, be equivalent
54
55
			final Class<?> vesd = ValidateEditSupport.Default.class;
56
57
			if (value1 instanceof Boolean) {
58
				if ((Boolean) value1) {
59
					// TRUE === new
60
					// ValidateEditSupport.Default
61
					result = safeClass(value2) == vesd;
62
				}
63
			} else if (safeClass(value1) == vesd) {
64
				result = Boolean.TRUE.equals(value2)
65
					|| (safeClass(value2) == vesd);
66
			}
67
		}
68
69
		return result;
70
	}
71
72
}
(-)src/org/eclipse/emf/workspace/WorkspaceEditingDomainFactory.java (-4 / +17 lines)
Lines 1-7 Link Here
1
/**
1
/**
2
 * <copyright>
2
 * <copyright>
3
 *
3
 *
4
 * Copyright (c) 2005, 2008 IBM Corporation, Zeligoft Inc., 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-15 Link Here
9
 *
9
 *
10
 * Contributors:
10
 * Contributors:
11
 *   IBM - Initial API and implementation
11
 *   IBM - Initial API and implementation
12
 *   Zeligsoft - Bug 240775
12
 *   Zeligsoft - Bugs 240775, 245446
13
 *
13
 *
14
 * </copyright>
14
 * </copyright>
15
 *
15
 *
Lines 18-29 Link Here
18
package org.eclipse.emf.workspace;
18
package org.eclipse.emf.workspace;
19
19
20
import org.eclipse.core.commands.operations.IOperationHistory;
20
import org.eclipse.core.commands.operations.IOperationHistory;
21
import org.eclipse.core.commands.operations.IUndoableOperation;
21
import org.eclipse.core.commands.operations.OperationHistoryFactory;
22
import org.eclipse.core.commands.operations.OperationHistoryFactory;
22
import org.eclipse.emf.ecore.resource.ResourceSet;
23
import org.eclipse.emf.ecore.resource.ResourceSet;
23
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
24
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
25
import org.eclipse.emf.transaction.Transaction;
24
import org.eclipse.emf.transaction.TransactionalEditingDomain;
26
import org.eclipse.emf.transaction.TransactionalEditingDomain;
25
import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl;
27
import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl;
28
import org.eclipse.emf.transaction.util.BasicTransactionOptionMetadata;
29
import org.eclipse.emf.transaction.util.BasicTransactionOptionMetadataRegistry;
26
import org.eclipse.emf.workspace.impl.WorkspaceCommandStackImpl;
30
import org.eclipse.emf.workspace.impl.WorkspaceCommandStackImpl;
31
import org.eclipse.emf.workspace.internal.EMFWorkspacePlugin;
27
32
28
/**
33
/**
29
 * <p>
34
 * <p>
Lines 47-52 Link Here
47
	public static final WorkspaceEditingDomainFactory INSTANCE =
52
	public static final WorkspaceEditingDomainFactory INSTANCE =
48
		new WorkspaceEditingDomainFactory();
53
		new WorkspaceEditingDomainFactory();
49
	
54
	
55
	static {
56
		BasicTransactionOptionMetadataRegistry reg = (BasicTransactionOptionMetadataRegistry) Transaction.OptionMetadata.Registry.INSTANCE;
57
58
		reg.register(new BasicTransactionOptionMetadata(
59
			EMFWorkspacePlugin.OPTION_OWNING_OPERATION, true, true,
60
			IUndoableOperation.class, null));
61
	}
62
	
50
	/**
63
	/**
51
	 * Initializes me.
64
	 * Initializes me.
52
	 */
65
	 */
Lines 88-94 Link Here
88
	 * 
101
	 * 
89
	 * @return the new editing domain
102
	 * @return the new editing domain
90
	 */
103
	 */
91
	public TransactionalEditingDomain createEditingDomain(IOperationHistory history) {
104
	public synchronized TransactionalEditingDomain createEditingDomain(IOperationHistory history) {
92
		WorkspaceCommandStackImpl stack = new WorkspaceCommandStackImpl(history);
105
		WorkspaceCommandStackImpl stack = new WorkspaceCommandStackImpl(history);
93
		stack.setResourceUndoContextPolicy(getResourceUndoContextPolicy());
106
		stack.setResourceUndoContextPolicy(getResourceUndoContextPolicy());
94
		
107
		
Lines 111-117 Link Here
111
	 * 
124
	 * 
112
	 * @return the new editing domain
125
	 * @return the new editing domain
113
	 */
126
	 */
114
	public TransactionalEditingDomain createEditingDomain(ResourceSet rset, IOperationHistory history) {
127
	public synchronized TransactionalEditingDomain createEditingDomain(ResourceSet rset, IOperationHistory history) {
115
		WorkspaceCommandStackImpl stack = new WorkspaceCommandStackImpl(history);
128
		WorkspaceCommandStackImpl stack = new WorkspaceCommandStackImpl(history);
116
		stack.setResourceUndoContextPolicy(getResourceUndoContextPolicy());
129
		stack.setResourceUndoContextPolicy(getResourceUndoContextPolicy());
117
		
130
		
(-)src/org/eclipse/emf/workspace/AbstractEMFOperation.java (-5 / +30 lines)
Lines 203-215 Link Here
203
	 */
203
	 */
204
	private boolean optionsDiffer(Map<?, ?> options) {
204
	private boolean optionsDiffer(Map<?, ?> options) {
205
		boolean result = true;
205
		boolean result = true;
206
		
206
207
		Transaction active =
207
		Transaction active = ((InternalTransactionalEditingDomain) getEditingDomain())
208
			((InternalTransactionalEditingDomain) getEditingDomain()).getActiveTransaction();
208
			.getActiveTransaction();
209
		if ((active != null) && !active.isReadOnly()) {
209
		if ((active != null) && !active.isReadOnly()) {
210
			result = !active.getOptions().equals(options);
210
			Transaction.OptionMetadata.Registry reg = TransactionUtil
211
				.getTransactionOptionRegistry(getEditingDomain());
212
213
			result = false; // let's look for a difference
214
			Map<?, ?> activeOptions = active.getOptions();
215
216
			// iterate the options passed in that would be applied to the
217
			// nested transaction, because if the active (to-be parent)
218
			// specifies more options, then they would be inherited, anyway
219
			for (Map.Entry<?, ?> next : options.entrySet()) {
220
				Object option = next.getKey();
221
222
				Transaction.OptionMetadata metadata = reg
223
					.getOptionMetadata(option);
224
225
				// tags don't force child transactions. Clients would have
226
				// to disable nesting if it really matters to them, or else
227
				// override the option meta-data in their editing domain's
228
				// local registry
229
				if (!metadata.isTag()
230
					&& !metadata.sameSetting(options, activeOptions)) {
231
232
					result = true;
233
					break;
234
				}
235
			}
211
		}
236
		}
212
		
237
213
		return result;
238
		return result;
214
	}
239
	}
215
    
240
    

Return to bug 245446