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 249496 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/emf/validation/internal/service/ClientContextManager.java (-34 / +37 lines)
Lines 1-12 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2005, 2007 IBM Corporation and others.
2
 * Copyright (c) 2005, 2008 IBM Corporation, Zeligsoft Inc., and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *    IBM Corporation - initial API and implementation 
9
 *    IBM Corporation - initial API and implementation
10
 *    Zeligsoft - Bug 249496
10
 ****************************************************************************/
11
 ****************************************************************************/
11
12
12
package org.eclipse.emf.validation.internal.service;
13
package org.eclipse.emf.validation.internal.service;
Lines 45-52 Link Here
45
	private static final String E_BINDING = "binding"; //$NON-NLS-1$
46
	private static final String E_BINDING = "binding"; //$NON-NLS-1$
46
	private static final String A_CONTEXT = "context"; //$NON-NLS-1$
47
	private static final String A_CONTEXT = "context"; //$NON-NLS-1$
47
	
48
	
48
	private static final String A_CONSTRAINT = "constraint"; //$NON-NLS-1$
49
	private static final String E_CONSTRAINT = "constraint"; //$NON-NLS-1$
49
	private static final String A_CATEGORY = "category"; //$NON-NLS-1$
50
	private static final String E_CATEGORY = "category"; //$NON-NLS-1$
51
	private static final String E_EXCLUDE_CONSTRAINT = "excludeConstraint"; //$NON-NLS-1$
52
	private static final String E_EXCLUDE_CATEGORY = "excludeCategory"; //$NON-NLS-1$
50
	private static final String A_REF = "ref"; //$NON-NLS-1$
53
	private static final String A_REF = "ref"; //$NON-NLS-1$
51
	
54
	
52
	private static final ClientContextManager INSTANCE = new ClientContextManager();
55
	private static final ClientContextManager INSTANCE = new ClientContextManager();
Lines 299-305 Link Here
299
			// add the constraint to all default contexts so that we don't do
302
			// add the constraint to all default contexts so that we don't do
300
			//   this computation again
303
			//   this computation again
301
			for (ClientContext next : defaultContexts) {
304
			for (ClientContext next : defaultContexts) {
302
				next.bindConstraint(id);
305
				next.includeConstraint(id);
303
			}
306
			}
304
		}
307
		}
305
		
308
		
Lines 400-446 Link Here
400
	 * @param config a particular <code>&lt;binding&gt;</config> element
403
	 * @param config a particular <code>&lt;binding&gt;</config> element
401
	 */
404
	 */
402
	private void configureBindings(ClientContext context, IConfigurationElement config) {
405
	private void configureBindings(ClientContext context, IConfigurationElement config) {
403
		String id = config.getAttribute(A_CONSTRAINT);
406
		String id = config.getAttribute(E_CONSTRAINT);
404
		
407
		
405
		if (id != null) {
408
		if (id != null) {
406
			context.bindConstraint(id);
409
			context.includeConstraint(id);
407
		}
410
		}
408
		
411
		
409
		id = config.getAttribute(A_CATEGORY);
412
		id = config.getAttribute(E_CATEGORY);
410
		
413
		
411
		if (id != null) {
414
		if (id != null) {
412
			context.bindCategory(id);
415
			context.includeCategory(id);
413
		}
416
		}
414
		
417
		
415
		IConfigurationElement[] children = config.getChildren(A_CONSTRAINT);
418
		IConfigurationElement[] children = config.getChildren();
416
		for (IConfigurationElement element : children) {
419
		for (IConfigurationElement element : children) {
420
			final String name = element.getName();
417
			final String ref = element.getAttribute(A_REF);
421
			final String ref = element.getAttribute(A_REF);
418
			
422
			
419
			if (ref == null) {
423
			if (ref == null) {
420
				Log.warningMessage(
424
				if (E_CONSTRAINT.equals(name) || E_EXCLUDE_CONSTRAINT.equals(name)) {
421
					EMFModelValidationStatusCodes.BINDING_NO_CONSTRAINT,
425
					Log.warningMessage(
422
					ValidationMessages.binding_noConstraintRef_WARN_,
426
						EMFModelValidationStatusCodes.BINDING_NO_CONSTRAINT,
423
					new Object[] {
427
						ValidationMessages.binding_noConstraintRef_WARN_,
424
						context.getId(),
428
						new Object[] {
425
						config.getDeclaringExtension().getNamespaceIdentifier()});
429
							context.getId(),
426
			} else {
430
							config.getDeclaringExtension().getNamespaceIdentifier()});
427
				context.bindConstraint(ref);
431
				} else {
428
			}
432
					Log.errorMessage(
429
		}
433
						EMFModelValidationStatusCodes.BINDING_NO_CATEGORY,
430
		
434
						ValidationMessages.binding_noCategoryRef_WARN_,
431
		children = config.getChildren(A_CATEGORY);
435
						new Object[] {
432
		for (IConfigurationElement element : children) {
436
							context.getId(),
433
			final String ref = element.getAttribute(A_REF);
437
							config.getDeclaringExtension().getNamespaceIdentifier()});
434
			
438
				}
435
			if (ref == null) {
439
			} else if (E_CONSTRAINT.equals(name)) {
436
				Log.errorMessage(
440
				context.includeConstraint(ref);
437
					EMFModelValidationStatusCodes.BINDING_NO_CATEGORY,
441
			} else if (E_CATEGORY.equals(name)) {
438
					ValidationMessages.binding_noCategoryRef_WARN_,
442
				context.includeCategory(ref);
439
					new Object[] {
443
			} else if (E_EXCLUDE_CONSTRAINT.equals(name)) {
440
						context.getId(),
444
				context.excludeConstraint(ref);
441
						config.getDeclaringExtension().getNamespaceIdentifier()});
445
			} else if (E_EXCLUDE_CATEGORY.equals(name)) {
442
			} else {
446
				context.excludeCategory(ref);
443
				context.bindCategory(ref);
444
			}
447
			}
445
		}
448
		}
446
	}
449
	}
(-)src/org/eclipse/emf/validation/internal/service/ClientContext.java (-57 / +332 lines)
Lines 1-25 Link Here
1
/******************************************************************************
1
/******************************************************************************
2
 * Copyright (c) 2005, 2007 IBM Corporation and others.
2
 * Copyright (c) 2005, 2008 IBM Corporation, Zeligsoft Inc., and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *    IBM Corporation - initial API and implementation 
9
 *    IBM Corporation - initial API and implementation
10
 *    Zeligsoft - Bug 249496
10
 ****************************************************************************/
11
 ****************************************************************************/
11
12
12
package org.eclipse.emf.validation.internal.service;
13
package org.eclipse.emf.validation.internal.service;
13
14
14
import java.util.Collection;
15
import java.util.Collection;
15
import java.util.Iterator;
16
import java.util.Map;
16
import java.util.Set;
17
import java.util.Set;
17
18
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.core.runtime.IConfigurationElement;
20
import org.eclipse.core.runtime.IConfigurationElement;
20
import org.eclipse.core.runtime.IStatus;
21
import org.eclipse.core.runtime.IStatus;
21
import org.eclipse.core.runtime.Status;
22
import org.eclipse.core.runtime.Status;
22
23
import org.eclipse.emf.validation.internal.EMFModelValidationPlugin;
23
import org.eclipse.emf.validation.internal.EMFModelValidationPlugin;
24
import org.eclipse.emf.validation.internal.EMFModelValidationStatusCodes;
24
import org.eclipse.emf.validation.internal.EMFModelValidationStatusCodes;
25
import org.eclipse.emf.validation.internal.l10n.ValidationMessages;
25
import org.eclipse.emf.validation.internal.l10n.ValidationMessages;
Lines 52-62 Link Here
52
	private final IClientSelector selector;
52
	private final IClientSelector selector;
53
	private final boolean isDefault;
53
	private final boolean isDefault;
54
	
54
	
55
	// set of String constraint IDs that are bound to me
55
	// map of String constraint IDs that are bound to me, the boolean value
56
	private final Set<String> constraintBindings = new java.util.HashSet<String>();
56
	// indicating absolute inclusion or exclusion.  Absence of a value means
57
	// that we still need to compute
58
	private final Map<String, Boolean> constraintBindings = new java.util.HashMap<String, Boolean>();
57
	
59
	
58
	// set of String category IDs that are bound to me
60
	// set of String category IDs that are bound to me
59
	private final Set<String> categoryBindings = new java.util.HashSet<String>();
61
	private BindingFilter filter = BindingFilter.NULL;
60
	
62
	
61
	/**
63
	/**
62
	 * Initializes me with my XML configuration.
64
	 * Initializes me with my XML configuration.
Lines 235-255 Link Here
235
	}
237
	}
236
238
237
	public boolean includes(IModelConstraint constraint) {
239
	public boolean includes(IModelConstraint constraint) {
238
		boolean result = false;
240
		Boolean result;
239
		
241
		
240
		IConstraintDescriptor descriptor = constraint.getDescriptor();
242
		IConstraintDescriptor descriptor = constraint.getDescriptor();
241
		
243
		
242
		if (descriptor != null) {
244
		if (descriptor == null) {
243
			result = constraintBindings.contains(descriptor.getId());
245
			result = Boolean.FALSE;
246
		} else {
247
			result = constraintBindings.get(descriptor.getId());
244
			
248
			
245
			if (!result && !categoryBindings.isEmpty()) {
249
			if (result == null) {
246
				// look for a bound category
250
				// cache the result for this constraint
247
				result = hasCategoryBinding(descriptor.getCategories());
251
				result = filter.getBinding(descriptor);
248
				
252
				constraintBindings.put(descriptor.getId(), result);
249
				if (result) {
250
					// cache the result for this constraint
251
					bindConstraint(descriptor.getId());
252
				}
253
			}
253
			}
254
		}
254
		}
255
		
255
		
Lines 257-314 Link Here
257
	}
257
	}
258
	
258
	
259
	/**
259
	/**
260
	 * Determines whether any of the specified <code>categories</code> is bound
260
	 * Adds a constraint inclusion binding to me.
261
	 * to me.
262
	 * 
261
	 * 
263
	 * @param categories a collection of categories (usually from a constraint)
262
	 * @param constraintId the ID of a constraint that is to be included in me
264
	 * @return <code>true</code> if any of the <code>categories</code> is bound,
265
	 *     or if any of their ancestors is bound; <code>false</code>, otherwise
266
	 */
263
	 */
267
	private boolean hasCategoryBinding(Collection<Category> categories) {
264
	void includeConstraint(String constraintId) {
268
		boolean result = false;
265
		filter = filter.includeConstraint(constraintId);
269
		
266
	}
270
		for (Iterator<Category> iter = categories.iterator(); !result && iter.hasNext();) {
267
271
			Category category = iter.next();
268
	/**
272
			
269
	 * Adds a constraint exclusion binding to me.
273
			result = categoryBindings.contains(category.getPath());
270
	 * 
274
			
271
	 * @param constraintId the ID of a constraint that is to be excluded from me
275
			if (!result) {
272
	 */
276
				// search the ancestors
273
	void excludeConstraint(String constraintId) {
277
				Category ancestor = category.getParent();
274
		filter = filter.excludeConstraint(constraintId);
278
				
279
				while ((ancestor != null) && !result) {
280
					result = categoryBindings.contains(ancestor.getPath());
281
					ancestor = ancestor.getParent();
282
				}
283
				
284
				if (result) {
285
					// cache the original category for quicker results on the
286
					//    next constraint that it includes
287
					bindCategory(category.getPath());
288
				}
289
			}
290
		}
291
		
292
		return result;
293
	}
275
	}
294
276
295
	/**
277
	/**
296
	 * Binds a constraint to me.
278
	 * Adds a constraint category inclusion to me.
297
	 * 
279
	 * 
298
	 * @param constraintId the ID of a constraint that is to be bound to me
280
	 * @param categoryId the qualified ID (path) of a constraint category that
281
	 *     is to be included in me
299
	 */
282
	 */
300
	void bindConstraint(String constraintId) {
283
	void includeCategory(String categoryId) {
301
		constraintBindings.add(constraintId);
284
		filter = filter.includeCategory(categoryId);
302
	}
285
	}
303
286
304
	/**
287
	/**
305
	 * Binds a constraint category to me.
288
	 * Adds a constraint category exclusion to me.
306
	 * 
289
	 * 
307
	 * @param categoryId the qualified ID (path) of a constraint category that
290
	 * @param categoryId the qualified ID (path) of a constraint category that
308
	 *     is to be bound to me
291
	 *     is to be excluded from me
309
	 */
292
	 */
310
	void bindCategory(String categoryId) {
293
	void excludeCategory(String categoryId) {
311
		categoryBindings.add(categoryId);
294
		filter = filter.excludeCategory(categoryId);
312
	}
295
	}
313
296
314
	/**
297
	/**
Lines 332-335 Link Here
332
	public String toString() {
315
	public String toString() {
333
		return "ClientContext[" + getId() + ']'; //$NON-NLS-1$
316
		return "ClientContext[" + getId() + ']'; //$NON-NLS-1$
334
	}
317
	}
318
	
319
	
320
	/**
321
	 * A chain-structured constraint-binding filter.  Filters are chained in
322
	 * the order in which they are parsed from the extension point.  The head of
323
	 * the filter chain applies its filter and, if it doesn't find any match,
324
	 * delegates down the chain.  The chain is terminated by the {@link #NULL}
325
	 * filter, which always excludes the constraint.
326
	 * 
327
	 * @author Christian W. Damus (cdamus)
328
	 */
329
	private static class BindingFilter {
330
		private BindingFilter next;
331
		
332
		/** A filter that excludes every constraint. */
333
		static final BindingFilter NULL = new BindingFilter() {
334
			boolean getBinding(IConstraintDescriptor constraint) {return false;}
335
		};
336
		
337
		/**
338
		 * Queries whether the specified constraint is definitely included
339
		 * (<code>true</code>) or excluded (<code>false</code>) from the client
340
		 * context.  If I don't have definitive knowledge of this constraint,
341
		 * I delegate to the next in the chain.
342
		 * 
343
		 * @param constraint a constraint descriptor
344
		 * @return whether the constraint is included
345
		 */
346
		boolean getBinding(IConstraintDescriptor constraint) {
347
			return isExcluded(constraint)
348
				? false
349
				: isIncluded(constraint)
350
					? true
351
					: next().getBinding(constraint);
352
		}
353
		
354
		/**
355
		 * Queries whether I know that a constraint is included.
356
		 * 
357
		 * @param constraint a constraint descriptor
358
		 * @return <code>true</code> if the constraint is included, or
359
		 *     <code>false</code> if I do not know
360
		 */
361
		boolean isExcluded(IConstraintDescriptor constraint) {
362
			return false;
363
		}
364
		
365
		/**
366
		 * Queries whether I know that a constraint is excluded.
367
		 * 
368
		 * @param constraint a constraint descriptor
369
		 * @return <code>true</code> if the constraint is excluded, or
370
		 *     <code>false</code> if I do not know
371
		 */
372
		boolean isIncluded(IConstraintDescriptor constraint) {
373
			return false;
374
		}
375
		
376
		/**
377
		 * Obtains the next filter in my chain.
378
		 * 
379
		 * @return my next, or <code>null</code> if I am the end of the chain
380
		 */
381
		BindingFilter next() {
382
			return next;
383
		}
384
		
385
		/**
386
		 * Assigns my next filter.
387
		 * 
388
		 * @param next my new next
389
		 */
390
		void setNext(BindingFilter next) {
391
			this.next = next;
392
		}
393
		
394
		/**
395
		 * Obtains a filter, chaining me, that definitively includes the
396
		 * specified category and all of its constraints and sub-categories. The
397
		 * result may be optimized to be myself augmented with this category, if
398
		 * I am a filter of the appropriate kind. Or, the result may be a new
399
		 * filter chain.
400
		 * 
401
		 * @param category
402
		 *            a category to include
403
		 * 
404
		 * @return a filter that includes the category
405
		 */
406
		BindingFilter includeCategory(String category) {
407
			CategoryInclusion result = new CategoryInclusion(category);
408
			result.setNext(this);
409
			return result;
410
		}
411
		
412
		/**
413
		 * Obtains a filter, chaining me, that definitively excludes the
414
		 * specified category and all of its constraints and sub-categories. The
415
		 * result may be optimized to be myself augmented with this category, if
416
		 * I am a filter of the appropriate kind. Or, the result may be a new
417
		 * filter chain.
418
		 * 
419
		 * @param category
420
		 *            a category to exclude
421
		 * 
422
		 * @return a filter that excludes the category
423
		 */
424
		BindingFilter excludeCategory(String category) {
425
			CategoryExclusion result = new CategoryExclusion(category);
426
			result.setNext(this);
427
			return result;
428
		}
429
430
		/**
431
		 * Obtains a filter, chaining me, that definitively includes the
432
		 * specified constraint. The result may be optimized to be myself
433
		 * augmented with this category, if I am a filter of the appropriate
434
		 * kind. Or, the result may be a new filter chain.
435
		 * 
436
		 * @param constraint
437
		 *            a constraint to include
438
		 * 
439
		 * @return a filter that includes the constraint
440
		 */
441
		BindingFilter includeConstraint(String constraint) {
442
			ConstraintInclusion result = new ConstraintInclusion(constraint);
443
			result.setNext(this);
444
			return result;
445
		}
446
		
447
		/**
448
		 * Obtains a filter, chaining me, that definitively excludes the
449
		 * specified constraint. The result may be optimized to be myself
450
		 * augmented with this category, if I am a filter of the appropriate
451
		 * kind. Or, the result may be a new filter chain.
452
		 * 
453
		 * @param constraint
454
		 *            a constraint to exclude
455
		 * 
456
		 * @return a filter that excludes the constraint
457
		 */
458
		BindingFilter excludeConstraint(String constraint) {
459
			ConstraintExclusion result = new ConstraintExclusion(constraint);
460
			result.setNext(this);
461
			return result;
462
		}
463
	}
464
	
465
	/**
466
	 * A binding filter that definitively includes one or more constraints.
467
	 * 
468
	 * @author Christian W. Damus (cdamus)
469
	 */
470
	private static class ConstraintInclusion extends BindingFilter {
471
		private final Set<String> constraints = new java.util.HashSet<String>();
472
		
473
		ConstraintInclusion(String constraint) {
474
			constraints.add(constraint);
475
		}
476
		
477
		@Override
478
		boolean isIncluded(IConstraintDescriptor constraint) {
479
			return constraints.contains(constraint.getId());
480
		}
481
		
482
		@Override
483
		BindingFilter includeConstraint(String constraint) {
484
			constraints.add(constraint);
485
			return this;
486
		}
487
	}
488
	
489
	/**
490
	 * A binding filter that definitively excludes one or more constraints.
491
	 * 
492
	 * @author Christian W. Damus (cdamus)
493
	 */
494
	private static class ConstraintExclusion extends BindingFilter {
495
		private final Set<String> constraints = new java.util.HashSet<String>();
496
		
497
		ConstraintExclusion(String constraint) {
498
			constraints.add(constraint);
499
		}
500
		
501
		@Override
502
		boolean isExcluded(IConstraintDescriptor constraint) {
503
			return constraints.contains(constraint.getId());
504
		}
505
		
506
		@Override
507
		BindingFilter excludeConstraint(String constraint) {
508
			constraints.add(constraint);
509
			return this;
510
		}
511
	}
512
	
513
	/**
514
	 * A binding filter that definitively includes one or more categories.
515
	 * 
516
	 * @author Christian W. Damus (cdamus)
517
	 */
518
	private static class CategoryInclusion extends BindingFilter {
519
		private final CategorySet categories;
520
		
521
		CategoryInclusion(String category) {
522
			categories = new CategorySet(category);
523
		}
524
		
525
		@Override
526
		boolean isIncluded(IConstraintDescriptor constraint) {
527
			return categories.containsAny(constraint.getCategories());
528
		}
529
		
530
		@Override
531
		BindingFilter includeCategory(String category) {
532
			categories.add(category);
533
			return this;
534
		}
535
	}
536
	
537
	/**
538
	 * A binding filter that definitively excludes one or more categories.
539
	 * 
540
	 * @author Christian W. Damus (cdamus)
541
	 */
542
	private static class CategoryExclusion extends BindingFilter {
543
		private final CategorySet categories;
544
		
545
		CategoryExclusion(String category) {
546
			categories = new CategorySet(category);
547
		}
548
		
549
		@Override
550
		boolean isExcluded(IConstraintDescriptor constraint) {
551
			return categories.containsAny(constraint.getCategories());
552
		}
553
		
554
		@Override
555
		BindingFilter excludeCategory(String category) {
556
			categories.add(category);
557
			return this;
558
		}
559
	}
560
	
561
	private static final class CategorySet {
562
		private final Set<String> categories = new java.util.HashSet<String>();
563
		
564
		CategorySet(String category) {
565
			categories.add(category);
566
		}
567
		
568
		boolean containsAny(Collection<? extends Category> categories) {
569
			boolean result = false;
570
			
571
			for (Category next : categories) {
572
				if (contains(next)) {
573
					result = true;
574
					break;
575
				}
576
			}
577
			
578
			return result;
579
		}
580
		
581
		boolean contains(Category category) {
582
			boolean result = false;
583
			
584
			String path = category.getPath();
585
			result = categories.contains(path);
586
			
587
			if (!result) {
588
				// search the ancestors
589
				Category ancestor = category.getParent();
590
				
591
				while ((ancestor != null) && !result) {
592
					result = categories.contains(ancestor.getPath());
593
					ancestor = ancestor.getParent();
594
				}
595
				
596
				if (result) {
597
					// cache the original category for quicker results on the
598
					// next category that it contains
599
					add(path);
600
				}
601
			}
602
			
603
			return result;
604
		}
605
		
606
		void add(String category) {
607
			categories.add(category);
608
		}
609
	}
335
}
610
}
(-)schema/constraintBindings.exsd (-40 / +80 lines)
Lines 1-10 Link Here
1
<?xml version='1.0' encoding='UTF-8'?>
1
<?xml version='1.0' encoding='UTF-8'?>
2
<!-- Schema file written by PDE -->
2
<!-- Schema file written by PDE -->
3
<schema targetNamespace="org.eclipse.emf.validation">
3
<schema targetNamespace="org.eclipse.emf.validation" xmlns="http://www.w3.org/2001/XMLSchema">
4
<annotation>
4
<annotation>
5
      <appInfo>
5
      <appinfo>
6
         <meta.schema plugin="org.eclipse.emf.validation" id="constraintBindings" name="EMF Validation Constraint Bindings"/>
6
         <meta.schema plugin="org.eclipse.emf.validation" id="constraintBindings" name="EMF Validation Constraint Bindings"/>
7
      </appInfo>
7
      </appinfo>
8
      <documentation>
8
      <documentation>
9
         This extension point allows clients of the EMF Validation
9
         This extension point allows clients of the EMF Validation
10
framework to define &quot;client contexts&quot; that describe the
10
framework to define &quot;client contexts&quot; that describe the
Lines 17-22 Link Here
17
   <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
17
   <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
18
18
19
   <element name="extension">
19
   <element name="extension">
20
      <annotation>
21
         <appinfo>
22
            <meta.element />
23
         </appinfo>
24
      </annotation>
20
      <complexType>
25
      <complexType>
21
         <sequence>
26
         <sequence>
22
            <element ref="clientContext" minOccurs="0" maxOccurs="unbounded"/>
27
            <element ref="clientContext" minOccurs="0" maxOccurs="unbounded"/>
Lines 41-49 Link Here
41
               <documentation>
46
               <documentation>
42
                  
47
                  
43
               </documentation>
48
               </documentation>
44
               <appInfo>
49
               <appinfo>
45
                  <meta.attribute translatable="true"/>
50
                  <meta.attribute translatable="true"/>
46
               </appInfo>
51
               </appinfo>
47
            </annotation>
52
            </annotation>
48
         </attribute>
53
         </attribute>
49
      </complexType>
54
      </complexType>
Lines 51-59 Link Here
51
56
52
   <element name="clientContext">
57
   <element name="clientContext">
53
      <annotation>
58
      <annotation>
54
         <appInfo>
59
         <appinfo>
55
            <meta.element labelAttribute="id"/>
60
            <meta.element labelAttribute="id"/>
56
         </appInfo>
61
         </appinfo>
57
         <documentation>
62
         <documentation>
58
            &lt;p&gt;
63
            &lt;p&gt;
59
Definition of a client context, representing a class of
64
Definition of a client context, representing a class of
Lines 110-118 Link Here
110
                  Identifies a class implementing the &lt;code&gt;org.eclipse.emf.validation.internal.model.IClientSelector&lt;/code&gt;
115
                  Identifies a class implementing the &lt;code&gt;org.eclipse.emf.validation.internal.model.IClientSelector&lt;/code&gt;
111
internal API interface.
116
internal API interface.
112
               </documentation>
117
               </documentation>
113
               <appInfo>
118
               <appinfo>
114
                  <meta.attribute kind="java" basedOn="org.eclipse.emf.validation.internal.model.IClientSelector"/>
119
                  <meta.attribute kind="java" basedOn="org.eclipse.emf.validation.internal.model.IClientSelector"/>
115
               </appInfo>
120
               </appinfo>
116
            </annotation>
121
            </annotation>
117
         </attribute>
122
         </attribute>
118
      </complexType>
123
      </complexType>
Lines 120-128 Link Here
120
125
121
   <element name="binding">
126
   <element name="binding">
122
      <annotation>
127
      <annotation>
123
         <appInfo>
128
         <appinfo>
124
            <meta.element labelAttribute="context"/>
129
            <meta.element labelAttribute="context"/>
125
         </appInfo>
130
         </appinfo>
126
         <documentation>
131
         <documentation>
127
            &lt;p&gt;
132
            &lt;p&gt;
128
Declares a binding between a client context and one or more
133
Declares a binding between a client context and one or more
Lines 131-136 Link Here
131
&lt;/p&gt;
136
&lt;/p&gt;
132
&lt;p&gt;
137
&lt;p&gt;
133
The constraints to be bound may be specified by either:
138
The constraints to be bound may be specified by either:
139
&lt;/p&gt;
134
&lt;ul&gt;
140
&lt;ul&gt;
135
  &lt;li&gt;the &lt;code&gt;constraint&lt;/code&gt; attribute, to reference
141
  &lt;li&gt;the &lt;code&gt;constraint&lt;/code&gt; attribute, to reference
136
      a single constraint&lt;/li&gt;
142
      a single constraint&lt;/li&gt;
Lines 141-153 Link Here
141
      and/or &lt;code&gt;&amp;lt;category&amp;gt;&lt;/code&gt; elements to
147
      and/or &lt;code&gt;&amp;lt;category&amp;gt;&lt;/code&gt; elements to
142
      reference multiple constraints and/or categories&lt;/li&gt;
148
      reference multiple constraints and/or categories&lt;/li&gt;
143
&lt;/ul&gt;
149
&lt;/ul&gt;
150
&lt;p&gt;
151
Since the 1.3 release, selective exclusion of constraints and sub-categories that are contained by included categories is supported.  Within a &lt;code&gt;&amp;lt;binding&amp;gt;&lt;/code&gt; element, ordering of inclusion and exclusion elements is significant:  they are processed in the order in which they are declared in the extension.  However, the order of inclusions and exclusions in separate bindings for the same context is undefined.
144
&lt;/p&gt;
152
&lt;/p&gt;
145
         </documentation>
153
         </documentation>
146
      </annotation>
154
      </annotation>
147
      <complexType>
155
      <complexType>
148
         <sequence>
156
         <sequence>
149
            <element ref="constraint" minOccurs="0" maxOccurs="unbounded"/>
157
            <choice minOccurs="0" maxOccurs="unbounded">
150
            <element ref="category" minOccurs="0" maxOccurs="unbounded"/>
158
               <element ref="category"/>
159
               <element ref="constraint"/>
160
               <element ref="excludeCategory"/>
161
               <element ref="excludeConstraint"/>
162
            </choice>
151
         </sequence>
163
         </sequence>
152
         <attribute name="context" type="string" use="required">
164
         <attribute name="context" type="string" use="required">
153
            <annotation>
165
            <annotation>
Lines 185-193 Link Here
185
197
186
   <element name="constraint">
198
   <element name="constraint">
187
      <annotation>
199
      <annotation>
188
         <appInfo>
200
         <appinfo>
189
            <meta.element labelAttribute="ref"/>
201
            <meta.element labelAttribute="ref"/>
190
         </appInfo>
202
         </appinfo>
191
         <documentation>
203
         <documentation>
192
            Includes a constraint in a client context
204
            Includes a constraint in a client context
193
&lt;code&gt;&amp;lt;binding&amp;gt;&lt;/code&gt;.
205
&lt;code&gt;&amp;lt;binding&amp;gt;&lt;/code&gt;.
Lines 209-217 Link Here
209
221
210
   <element name="category">
222
   <element name="category">
211
      <annotation>
223
      <annotation>
212
         <appInfo>
224
         <appinfo>
213
            <meta.element labelAttribute="ref"/>
225
            <meta.element labelAttribute="ref"/>
214
         </appInfo>
226
         </appinfo>
215
         <documentation>
227
         <documentation>
216
            Includes a constraint category in a client context
228
            Includes a constraint category in a client context
217
&lt;code&gt;&amp;lt;binding&amp;gt;&lt;/code&gt;.  All of the referenced
229
&lt;code&gt;&amp;lt;binding&amp;gt;&lt;/code&gt;.  All of the referenced
Lines 233-251 Link Here
233
      </complexType>
245
      </complexType>
234
   </element>
246
   </element>
235
247
248
   <element name="excludeCategory">
249
      <annotation>
250
         <documentation>
251
            Since 1.3.  Excludes a constraint category from a client context
252
&lt;code&gt;&amp;lt;binding&amp;gt;&lt;/code&gt;.  All of the referenced
253
category&apos;s constraints and those of any sub-categories
254
(recursively) are excluded.  This is useful when including some parent category, to filter out selective sub-categories.  Not only is it simpler than explicitly including all of the desired sub-categories, but it ensures that sub-categories that are added later will be included implicitly.
255
         </documentation>
256
      </annotation>
257
      <complexType>
258
         <attribute name="ref" type="string" use="required">
259
            <annotation>
260
               <documentation>
261
                  References the fully-qualified ID of a constraint category to
262
exclude from the client context. The category ID does not
263
necessarily include its contributing plug-in ID, but is a
264
path reflecting the hierarchical structure of categories.
265
               </documentation>
266
            </annotation>
267
         </attribute>
268
      </complexType>
269
   </element>
270
271
   <element name="excludeConstraint">
272
      <annotation>
273
         <documentation>
274
            Since 1.3.  Excludes a constraint from a client context
275
&lt;code&gt;&amp;lt;binding&amp;gt;&lt;/code&gt;. This is useful when including some parent category, to filter out selective constraints cointained within it.  Not only is it simpler than explicitly including all of the desired constraints and sub-categories, but it ensures that constraints and sub-categories that are added later will be included implicitly.
276
         </documentation>
277
      </annotation>
278
      <complexType>
279
         <attribute name="ref" type="string" use="required">
280
            <annotation>
281
               <documentation>
282
                  References the fully-qualified ID of a constraint to exclude
283
from the client context.  The ID includes the constraint&apos;s
284
contributing plug-in ID, if it is not explicit in the XML
285
definition of the constraint.
286
               </documentation>
287
            </annotation>
288
         </attribute>
289
      </complexType>
290
   </element>
291
236
   <annotation>
292
   <annotation>
237
      <appInfo>
293
      <appinfo>
238
         <meta.section type="since"/>
294
         <meta.section type="since"/>
239
      </appInfo>
295
      </appinfo>
240
      <documentation>
296
      <documentation>
241
         1.0
297
         1.0
242
      </documentation>
298
      </documentation>
243
   </annotation>
299
   </annotation>
244
300
245
   <annotation>
301
   <annotation>
246
      <appInfo>
302
      <appinfo>
247
         <meta.section type="examples"/>
303
         <meta.section type="examples"/>
248
      </appInfo>
304
      </appinfo>
249
      <documentation>
305
      <documentation>
250
         &lt;p&gt;
306
         &lt;p&gt;
251
Example of a context which includes &lt;code&gt;EObjects&lt;/code&gt; in *.library resources only, not
307
Example of a context which includes &lt;code&gt;EObjects&lt;/code&gt; in *.library resources only, not
Lines 291-320 Link Here
291
      </documentation>
347
      </documentation>
292
   </annotation>
348
   </annotation>
293
349
294
   <annotation>
295
      <appInfo>
296
         <meta.section type="apiInfo"/>
297
      </appInfo>
298
      <documentation>
299
         
300
      </documentation>
301
   </annotation>
302
350
303
   <annotation>
304
      <appInfo>
305
         <meta.section type="implementation"/>
306
      </appInfo>
307
      <documentation>
308
         
309
      </documentation>
310
   </annotation>
311
351
312
   <annotation>
352
   <annotation>
313
      <appInfo>
353
      <appinfo>
314
         <meta.section type="copyright"/>
354
         <meta.section type="copyright"/>
315
      </appInfo>
355
      </appinfo>
316
      <documentation>
356
      <documentation>
317
         Copyright (c) 2005  IBM Corporation and others.&lt;br&gt;
357
         Copyright (c) 2005, 2008  IBM Corporation, Zeligsoft Inc., and others.&lt;br&gt;
318
 All rights reserved. This program and the accompanying materials 
358
 All rights reserved. This program and the accompanying materials 
319
 are made available under the terms of the Eclipse Public License v1.0 
359
 are made available under the terms of the Eclipse Public License v1.0 
320
 which accompanies this distribution, and is available at 
360
 which accompanies this distribution, and is available at 
(-)src/org/eclipse/emf/validation/internal/service/impl/tests/AllTests.java (-1 / +4 lines)
Lines 1-7 Link Here
1
/**
1
/**
2
 * <copyright>
2
 * <copyright>
3
 *
3
 *
4
 * Copyright (c) 2003, 2006 IBM Corporation and others.
4
 * Copyright (c) 2003, 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 249496
12
 *
13
 *
13
 * </copyright>
14
 * </copyright>
14
 *
15
 *
Lines 43-47 Link Here
43
		
44
		
44
		addTestSuite(BatchValidatorTest.class);
45
		addTestSuite(BatchValidatorTest.class);
45
		addTestSuite(LiveValidatorTest.class);
46
		addTestSuite(LiveValidatorTest.class);
47
		
48
		addTest(ClientContextTest.suite());
46
	}
49
	}
47
}
50
}
(-)plugin.xml (+92 lines)
Lines 470-473 Link Here
470
         </eclass>
470
         </eclass>
471
      </traversalStrategy>
471
      </traversalStrategy>
472
   </extension>
472
   </extension>
473
   
474
   <!-- Constraints only used for client-context inclusion/exclusion testing -->
475
   <extension name="Contraints for client-context testing" point="org.eclipse.emf.validation.constraintProviders">
476
     <category id="clientContextTest" name="JUnit Client Context Testing Context"/>
477
     <category id="clientContextTest/one" name="First level of nesting"/>
478
     <category id="clientContextTest/one/two" name="Second level of nesting"/>
479
     <category id="clientContextTest/one/twoA" name="Second level of nesting (A)"/>
480
     <category id="clientContextTest/one/two/three" name="Third level of nesting"/>
481
     <category id="clientContextTest/one/two/threeA" name="Third level of nesting (A)"/>
482
     <constraintProvider>
483
         <package namespaceUri="http://www.eclipse.org/emf/2002/Ecore" />
484
         <constraints categories="clientContextTest/one">
485
            <constraint name="Dummy1.1" statusCode="1" lang="OCL" id="clientContext.1.1">
486
               <message>Nothing to say.</message>
487
               <target class="EAnnotation"/>
488
               true
489
            </constraint>
490
            <constraint name="Dummy1.2" statusCode="1" lang="OCL" id="clientContext.1.2">
491
               <message>Nothing to say.</message>
492
               <target class="EAnnotation"/>
493
               true
494
            </constraint>
495
         </constraints>
496
         <constraints categories="clientContextTest/one/two">
497
            <constraint name="Dummy2.1" statusCode="1" lang="OCL" id="clientContext.2.1">
498
               <message>Nothing to say.</message>
499
               <target class="EAnnotation"/>
500
               true
501
            </constraint>
502
            <constraint name="Dummy2.2" statusCode="1" lang="OCL" id="clientContext.2.2">
503
               <message>Nothing to say.</message>
504
               <target class="EAnnotation"/>
505
               true
506
            </constraint>
507
         </constraints>
508
         <constraints categories="clientContextTest/one/twoA">
509
            <constraint name="Dummy2a.1" statusCode="1" lang="OCL" id="clientContext.2a.1">
510
               <message>Nothing to say.</message>
511
               <target class="EAnnotation"/>
512
               true
513
            </constraint>
514
            <constraint name="Dummy2a.2" statusCode="1" lang="OCL" id="clientContext.2a.2">
515
               <message>Nothing to say.</message>
516
               <target class="EAnnotation"/>
517
               true
518
            </constraint>
519
         </constraints>
520
         <constraints categories="clientContextTest/one/two/three">
521
            <constraint name="Dummy3.1" statusCode="1" lang="OCL" id="clientContext.3.1">
522
               <message>Nothing to say.</message>
523
               <target class="EAnnotation"/>
524
               true
525
            </constraint>
526
            <constraint name="Dummy3.2" statusCode="1" lang="OCL" id="clientContext.3.2">
527
               <message>Nothing to say.</message>
528
               <target class="EAnnotation"/>
529
               true
530
            </constraint>
531
         </constraints>
532
         <constraints categories="clientContextTest/one/two/threeA">
533
            <constraint name="Dummy3a.1" statusCode="1" lang="OCL" id="clientContext.3a.1">
534
               <message>Nothing to say.</message>
535
               <target class="EAnnotation"/>
536
               true
537
            </constraint>
538
            <constraint name="Dummy3a.2" statusCode="1" lang="OCL" id="clientContext.3a.2">
539
               <message>Nothing to say.</message>
540
               <target class="EAnnotation"/>
541
               true
542
            </constraint>
543
         </constraints>
544
      </constraintProvider>
545
   </extension>
546
   <!-- A client-context only used for inclusion/exclusion testing -->
547
   <extension point="org.eclipse.emf.validation.constraintBindings">
548
      <clientContext
549
            id="org.eclipse.emf.validation.tests.testcontext">
550
          <!-- We are never enabled -->
551
          <enablement>
552
            <systemTest property="BOGUS_SYSTEM_PROPERTY" value="1"/>
553
         </enablement>
554
      </clientContext>
555
      <binding context="org.eclipse.emf.validation.tests.testcontext">
556
         <category ref="clientContextTest/one"/>
557
         <excludeCategory ref="clientContextTest/one/two"/>
558
         <category ref="clientContextTest/one/two/three"/>
559
         <excludeConstraint ref="org.eclipse.emf.validation.tests.clientContext.1.1"/>
560
         <excludeConstraint ref="org.eclipse.emf.validation.tests.clientContext.2a.1"/>
561
         <constraint ref="org.eclipse.emf.validation.tests.clientContext.2.2"/>
562
         <constraint ref="org.eclipse.emf.validation.tests.clientContext.3a.2"/>
563
      </binding>
564
   </extension>
473
</plugin>
565
</plugin>
(-)src/org/eclipse/emf/validation/internal/service/impl/tests/ClientContextTest.java (+156 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.validation.internal.service.impl.tests;
19
20
import junit.framework.Test;
21
import junit.framework.TestCase;
22
import junit.framework.TestSuite;
23
24
import org.eclipse.core.runtime.IStatus;
25
import org.eclipse.core.runtime.Status;
26
import org.eclipse.emf.ecore.EcoreFactory;
27
import org.eclipse.emf.validation.IValidationContext;
28
import org.eclipse.emf.validation.internal.service.ClientContext;
29
import org.eclipse.emf.validation.internal.service.ClientContextManager;
30
import org.eclipse.emf.validation.internal.service.IClientContext;
31
import org.eclipse.emf.validation.model.EvaluationMode;
32
import org.eclipse.emf.validation.model.IModelConstraint;
33
import org.eclipse.emf.validation.service.ConstraintRegistry;
34
import org.eclipse.emf.validation.service.IConstraintDescriptor;
35
import org.eclipse.emf.validation.service.ModelValidationService;
36
37
/**
38
 * Tests the {@link ClientContext} class.
39
 * 
40
 * @author Christian W. Damus (cdamus)
41
 */
42
@SuppressWarnings("nls")
43
public class ClientContextTest
44
		extends TestCase {
45
46
	private IModelConstraint constraint1_1;
47
48
	private IModelConstraint constraint1_2;
49
50
	private IModelConstraint constraint2_1;
51
52
	private IModelConstraint constraint2_2;
53
54
	private IModelConstraint constraint2a_1;
55
56
	private IModelConstraint constraint2a_2;
57
58
	private IModelConstraint constraint3_1;
59
60
	private IModelConstraint constraint3_2;
61
62
	private IModelConstraint constraint3a_1;
63
64
	private IModelConstraint constraint3a_2;
65
66
	private IClientContext fixture;
67
68
	/**
69
	 * Initialize me with my name.
70
	 * 
71
	 * @param name
72
	 *            my name
73
	 */
74
	public ClientContextTest(String name) {
75
		super(name);
76
	}
77
78
	public static Test suite() {
79
		return new TestSuite(ClientContextTest.class, "Client context tests");
80
	}
81
82
	public void test_includedChildOfExcludedCategory() {
83
		assertTrue("Constraint is excluded", fixture.includes(constraint3_1));
84
		assertTrue("Constraint is excluded", fixture.includes(constraint3_2));
85
	}
86
87
	public void test_constraintExcludedFromIncludedCategory() {
88
		assertFalse("Constraint is included", fixture.includes(constraint1_1));
89
		assertTrue("Constraint is excluded", fixture.includes(constraint1_2));
90
	}
91
92
	public void test_constraintIncludedInExcludedCategory() {
93
		assertFalse("Constraint is included", fixture.includes(constraint2_1));
94
		assertTrue("Constraint is excluded", fixture.includes(constraint2_2));
95
	}
96
97
	public void test_constraintExcludedFromIncludedCategory_nested() {
98
		assertFalse("Constraint is included", fixture.includes(constraint2a_1));
99
		assertTrue("Constraint is excluded", fixture.includes(constraint2a_2));
100
	}
101
102
	public void test_constraintIncludedInExcludedCategory_nested() {
103
		assertFalse("Constraint is included", fixture.includes(constraint3a_1));
104
		assertTrue("Constraint is excluded", fixture.includes(constraint3a_2));
105
	}
106
107
	//
108
	// Test framework
109
	//
110
111
	@Override
112
	protected void setUp()
113
			throws Exception {
114
115
		super.setUp();
116
117
		fixture = ClientContextManager.getInstance().getClientContext(
118
			"org.eclipse.emf.validation.tests.testcontext");
119
120
		final String prefix = "org.eclipse.emf.validation.tests.clientContext.";
121
		final ConstraintRegistry reg = ConstraintRegistry.getInstance();
122
123
		// cause our test constraints to be created
124
		ModelValidationService.getInstance().newValidator(EvaluationMode.BATCH)
125
			.validate(EcoreFactory.eINSTANCE.createEAnnotation());
126
127
		constraint1_1 = new TestConstraint(reg.getDescriptor(prefix + "1.1"));
128
		constraint1_2 = new TestConstraint(reg.getDescriptor(prefix + "1.2"));
129
		constraint2_1 = new TestConstraint(reg.getDescriptor(prefix + "2.1"));
130
		constraint2_2 = new TestConstraint(reg.getDescriptor(prefix + "2.2"));
131
		constraint2a_1 = new TestConstraint(reg.getDescriptor(prefix + "2a.1"));
132
		constraint2a_2 = new TestConstraint(reg.getDescriptor(prefix + "2a.2"));
133
		constraint3_1 = new TestConstraint(reg.getDescriptor(prefix + "3.1"));
134
		constraint3_2 = new TestConstraint(reg.getDescriptor(prefix + "3.2"));
135
		constraint3a_1 = new TestConstraint(reg.getDescriptor(prefix + "3a.1"));
136
		constraint3a_2 = new TestConstraint(reg.getDescriptor(prefix + "3a.2"));
137
	}
138
139
	private static final class TestConstraint
140
			implements IModelConstraint {
141
142
		private IConstraintDescriptor desc;
143
144
		TestConstraint(IConstraintDescriptor desc) {
145
			this.desc = desc;
146
		}
147
148
		public IStatus validate(IValidationContext c) {
149
			return Status.OK_STATUS;
150
		}
151
152
		public IConstraintDescriptor getDescriptor() {
153
			return desc;
154
		}
155
	}
156
}

Return to bug 249496