1 17 package org.eclipse.emf.ecore.util; 18 19 20 import java.lang.reflect.Array ; 21 import java.util.Iterator ; 22 import java.util.List ; 23 import java.util.ListIterator ; 24 25 import org.eclipse.emf.common.notify.Notification; 26 import org.eclipse.emf.common.notify.NotificationChain; 27 import org.eclipse.emf.common.notify.impl.NotificationImpl; 28 import org.eclipse.emf.common.notify.impl.NotifyingListImpl; 29 import org.eclipse.emf.common.util.BasicEList; 30 import org.eclipse.emf.ecore.EClass; 31 import org.eclipse.emf.ecore.EClassifier; 32 import org.eclipse.emf.ecore.EEnum; 33 import org.eclipse.emf.ecore.EObject; 34 import org.eclipse.emf.ecore.EReference; 35 import org.eclipse.emf.ecore.EStructuralFeature; 36 import org.eclipse.emf.ecore.InternalEObject; 37 import org.eclipse.emf.ecore.impl.ENotificationImpl; 38 39 40 public class EcoreEList extends NotifyingListImpl implements InternalEList.Unsettable, EStructuralFeature.Setting 41 { 42 protected final Class dataClass; 43 protected final InternalEObject owner; 44 45 public EcoreEList(Class dataClass, InternalEObject owner) 46 { 47 super(); 48 this.dataClass = dataClass; 49 this.owner = owner; 50 } 51 52 protected Object [] newData(int capacity) 53 { 54 return (Object [])Array.newInstance(dataClass, capacity); 55 } 56 57 protected Object validate(int index, Object object) 58 { 59 super.validate(index, object); 60 if (!hasInstanceClass() && object != null && !getFeatureType().isInstance(object)) 61 { 62 throw new ArrayStoreException (); 63 } 64 return object; 65 } 66 67 public Object getNotifier() 68 { 69 return owner; 70 } 71 72 public Object getFeature() 73 { 74 return getEStructuralFeature(); 75 } 76 77 public int getFeatureID() 78 { 79 return getEStructuralFeature().getFeatureID(); 80 } 81 82 public EStructuralFeature getEStructuralFeature() 83 { 84 return owner.eClass().getEStructuralFeature(getFeatureID()); 85 } 86 87 protected EClassifier getFeatureType() 88 { 89 return getEStructuralFeature().getEType(); 90 } 91 92 protected EReference getInverseEReference() 93 { 94 return ((EReference)getEStructuralFeature()).getEOpposite(); 95 } 96 97 protected int getInverseFeatureID() 98 { 99 return getInverseEReference().getFeatureID(); 100 } 101 102 protected Class getInverseFeatureClass() 103 { 104 return ((EClass)getInverseEReference().getEType()).getInstanceClass(); 105 } 106 107 protected boolean hasManyInverse() 108 { 109 return false; 110 } 111 112 protected boolean hasNavigableInverse() 113 { 114 return false; 115 } 116 117 protected boolean isEObject() 118 { 119 return true; 120 } 121 122 protected boolean isContainment() 123 { 124 return false; 125 } 126 127 protected boolean hasProxies() 128 { 129 return false; 130 } 131 132 protected boolean hasInstanceClass() 133 { 134 return true; 135 } 136 137 protected Object resolve(int index, Object object) 138 { 139 return 140 isEObject() && hasProxies() ? 141 resolve(index, (EObject)object): 142 object; 143 } 144 145 protected EObject resolve(int index, EObject eObject) 146 { 147 EObject resolved = resolveProxy(eObject); 148 if (resolved != eObject) 149 { 150 Object oldObject = data[index]; 151 assign(index, validate(index, resolved)); 152 didSet(index, resolved, oldObject); 153 154 if (isNotificationRequired()) 155 { 156 owner.eNotify(createNotification(Notification.RESOLVE, eObject, resolved, index, false)); 157 } 158 159 return resolved; 160 } 161 else 162 { 163 return eObject; 164 } 165 } 166 167 protected EObject resolveProxy(EObject eObject) 168 { 169 return eObject.eIsProxy() ? owner.eResolveProxy((InternalEObject)eObject) : eObject; 170 } 171 172 public Object [] toArray() 173 { 174 if (hasProxies()) 175 { 176 for (int i = size - 1; i >= 0; --i) 177 { 178 get(i); 179 } 180 } 181 return super.toArray(); 182 } 183 184 public Object [] toArray(Object array[]) 185 { 186 if (hasProxies()) 187 { 188 for (int i = size - 1; i >= 0; --i) 189 { 190 get(i); 191 } 192 } 193 return super.toArray(array); 194 } 195 196 protected NotificationImpl createNotification(int eventType, Object oldObject, Object newObject, int index, boolean wasSet) 197 { 198 return new ENotificationImpl(owner, eventType, getFeatureID(), oldObject, newObject, index, wasSet); 199 } 200 201 protected NotificationImpl createNotification(int eventType, boolean oldValue, boolean newValue) 202 { 203 return new ENotificationImpl(owner, eventType, getFeatureID(), oldValue, newValue); 204 } 205 206 209 protected void dispatchNotification(Notification notification) 210 { 211 owner.eNotify(notification); 212 } 213 214 public List basicList() 215 { 216 return super.basicList(); 217 } 218 219 protected boolean isNotificationRequired() 220 { 221 return owner.eNotificationRequired(); 222 } 223 224 public NotificationChain inverseAdd(Object object, NotificationChain notifications) 225 { 226 InternalEObject internalEObject = (InternalEObject) object; 227 if (hasNavigableInverse()) 228 { 229 if (!hasInstanceClass()) 230 { 231 return 232 internalEObject.eInverseAdd 233 (owner, 234 internalEObject.eClass().getFeatureID(getInverseEReference()), 235 null, 236 notifications); 237 } 238 else 239 { 240 return 241 internalEObject.eInverseAdd 242 (owner, 243 getInverseFeatureID(), 244 getInverseFeatureClass(), 245 notifications); 246 } 247 } 248 else 249 { 250 return 251 internalEObject.eInverseAdd 252 (owner, 253 InternalEObject.EOPPOSITE_FEATURE_BASE - getFeatureID(), 254 null, 255 notifications); 256 } 257 } 258 259 public NotificationChain inverseRemove(Object object, NotificationChain notifications) 260 { 261 InternalEObject internalEObject = (InternalEObject) object; 262 if (hasNavigableInverse()) 263 { 264 if (!hasInstanceClass()) 265 { 266 return 267 internalEObject.eInverseRemove 268 (owner, 269 internalEObject.eClass().getFeatureID(getInverseEReference()), 270 null, 271 notifications); 272 } 273 else 274 { 275 return 276 internalEObject.eInverseRemove 277 (owner, 278 getInverseFeatureID(), 279 getInverseFeatureClass(), 280 notifications); 281 } 282 } 283 else 284 { 285 return 286 internalEObject.eInverseRemove 287 (owner, 288 InternalEObject.EOPPOSITE_FEATURE_BASE - getFeatureID(), 289 null, 290 notifications); 291 } 292 } 293 294 297 public boolean contains(Object object) 298 { 299 if (isEObject()) 300 { 301 if (size > 4) 302 { 303 if (isContainment()) 304 { 305 if (!(object instanceof EObject)) return false; 306 InternalEObject eObject = (InternalEObject)object; 307 return 308 eObject.eContainer() == owner && 309 (hasNavigableInverse() ? 310 eObject.eBaseStructuralFeatureID(eObject.eContainerFeatureID(), dataClass) == getInverseFeatureID() : 311 InternalEObject.EOPPOSITE_FEATURE_BASE - eObject.eContainerFeatureID() == getFeatureID()); 312 } 313 else if (hasNavigableInverse() && !hasManyInverse()) 316 { 317 return object instanceof EObject && ((EObject)object).eGet(getInverseEReference()) == owner; 318 } 319 } 320 321 boolean result = super.contains(object); 322 if (hasProxies() && !result) 323 { 324 for (int i = 0; i < size; ++i) 325 { 326 EObject eObject = resolveProxy((EObject)data[i]); 327 if (eObject == object) 328 { 329 return true; 330 } 331 } 332 } 333 return result; 334 } 335 else 336 { 337 return super.contains(object); 338 } 339 } 340 341 public int indexOf(Object object) 342 { 343 int index = super.indexOf(object); 344 if (index >= 0) 345 return index; 346 347 if (isEObject()) 350 { 351 for (int i = 0; i < size; ++i) 352 { 353 EObject eObject = resolveProxy((EObject)data[i]); 354 if (eObject == object) 355 { 356 return i; 357 } 358 } 359 } 360 361 return -1; 362 } 363 364 public int lastIndexOf(Object object) 365 { 366 int result = super.lastIndexOf(object); 367 if (isEObject () && result == -1) 368 { 369 for (int i = size - 1; i >= 0; --i) 370 { 371 EObject eObject = resolveProxy((EObject)data[i]); 372 if (eObject == object) 373 { 374 return i; 375 } 376 } 377 } 378 379 return result; 380 } 381 382 public Iterator basicIterator() 383 { 384 return super.basicIterator(); 385 } 386 387 public ListIterator basicListIterator() 388 { 389 return super.basicListIterator(); 390 } 391 392 public ListIterator basicListIterator(int index) 393 { 394 return super.basicListIterator(index); 395 } 396 397 public EObject getEObject() 398 { 399 return owner; 400 } 401 402 public Object get(boolean resolve) 403 { 404 return this; 405 } 406 407 public void set(Object newValue) 408 { 409 clear(); 410 addAll((List )newValue); 411 } 412 413 public boolean isSet() 414 { 415 return !isEmpty(); 416 } 417 418 public void unset() 419 { 420 clear(); 421 } 422 423 public static class UnmodifiableEList 424 extends BasicEList.UnmodifiableEList 425 implements InternalEList.Unsettable, EStructuralFeature.Setting 426 { 427 public static class FastCompare extends EcoreEList.UnmodifiableEList 428 { 429 public FastCompare(InternalEObject owner, EStructuralFeature eStructuralFeature, int size, Object [] data) 430 { 431 super(owner, eStructuralFeature, size, data); 432 } 433 434 protected boolean useEquals() 435 { 436 return false; 437 } 438 } 439 440 protected final InternalEObject owner; 441 protected final EStructuralFeature eStructuralFeature; 442 443 public UnmodifiableEList(InternalEObject owner, EStructuralFeature eStructuralFeature, int size, Object [] data) 444 { 445 super(size, data); 446 this.owner = owner; 447 this.eStructuralFeature = eStructuralFeature; 448 } 449 450 public List basicList() 451 { 452 return super.basicList(); 453 } 454 455 public Iterator basicIterator() 456 { 457 return super.basicIterator(); 458 } 459 460 public ListIterator basicListIterator() 461 { 462 return super.basicListIterator(); 463 } 464 465 public ListIterator basicListIterator(int index) 466 { 467 return super.basicListIterator(index); 468 } 469 470 public EObject getEObject() 471 { 472 return owner; 473 } 474 475 public EStructuralFeature getEStructuralFeature() 476 { 477 return eStructuralFeature; 478 } 479 480 public Object get(boolean resolve) 481 { 482 return this; 483 } 484 485 public void set(Object newValue) 486 { 487 throw new UnsupportedOperationException (); 488 } 489 490 public boolean isSet() 491 { 492 return !isEmpty(); 493 } 494 495 public void unset() 496 { 497 throw new UnsupportedOperationException (); 498 } 499 500 public NotificationChain basicRemove(Object object, NotificationChain notifications) 501 { 502 throw new UnsupportedOperationException (); 503 } 504 505 public NotificationChain basicAdd(Object object, NotificationChain notifications) 506 { 507 throw new UnsupportedOperationException (); 508 } 509 } 510 511 public static class Generic extends EcoreEList 512 { 513 public static final int IS_SET = 0x0001; 514 public static final int IS_UNSETTABLE = 0x0002; 515 public static final int HAS_INSTANCE_CLASS = 0x0004; 516 public static final int HAS_NAVIGABLE_INVERSE = 0x0008; 517 public static final int HAS_MANY_INVERSE = 0x0010; 518 public static final int IS_CONTAINMENT = 0x0020; 519 public static final int IS_CONTAINER = 0x0040; 520 public static final int IS_UNIQUE = 0x0080; 521 public static final int IS_PRIMITIVE = 0x0100; 522 public static final int IS_ENUM = 0x0200; 523 public static final int IS_EOBJECT = 0x0400; 524 public static final int HAS_PROXIES = 0x0800; 525 526 public static Class wrapperClassFor(Class javaClass) 527 { 528 if (javaClass == null) 529 { 530 return Object .class; 531 } 532 else 533 { 534 return EcoreUtil.wrapperClassFor(javaClass); 535 } 536 } 537 538 public static int kind(EStructuralFeature eStructuralFeature) 539 { 540 int result = 0; 541 542 EClassifier eClassifier = eStructuralFeature.getEType(); 543 544 if (eClassifier.getInstanceClass() != null) 545 { 546 result |= HAS_INSTANCE_CLASS; 547 } 548 549 if (eStructuralFeature.isUnsettable()) 550 { 551 result |= IS_UNSETTABLE; 552 } 553 554 if (eStructuralFeature instanceof EReference) 555 { 556 EReference eReference = (EReference)eStructuralFeature; 557 EReference inverseEReference = eReference.getEOpposite(); 558 if (eReference.isContainment()) 559 { 560 result |= IS_CONTAINMENT; 561 } 562 563 if (inverseEReference != null) 564 { 565 inverseEReference.getEContainingClass().getFeatureCount(); 568 result |= HAS_NAVIGABLE_INVERSE; 569 if (inverseEReference.isMany()) 570 { 571 result |= HAS_MANY_INVERSE; 572 } 573 if (inverseEReference.isContainment()) 574 { 575 result |= IS_CONTAINER; 576 } 577 } 578 579 if (eReference.isResolveProxies()) 580 { 581 result |= HAS_PROXIES; 582 } 583 584 result |= IS_EOBJECT; 585 } 586 else { 588 if (eClassifier instanceof EEnum) 589 { 590 result |= IS_ENUM; 591 } 592 else 593 { 594 Class instanceClass = eClassifier.getInstanceClass(); 595 if (instanceClass != null && instanceClass.isPrimitive()) 596 { 597 result |= IS_PRIMITIVE; 598 } 599 } 600 } 601 602 if (eStructuralFeature.isUnique()) 603 { 604 result |= IS_UNIQUE; 605 } 606 607 return result; 608 } 609 610 protected int kind; 611 612 public Generic(int kind, Class dataClass, InternalEObject owner) 613 { 614 super(dataClass, owner); 615 this.kind = kind; 616 } 617 618 protected boolean useEquals() 619 { 620 return (kind & (IS_EOBJECT | IS_ENUM)) == 0; 623 } 624 625 protected boolean canContainNull() 626 { 627 return (kind & (IS_EOBJECT | IS_PRIMITIVE | IS_ENUM)) == 0; 628 } 629 630 protected boolean isUnique() 631 { 632 return (kind & IS_UNIQUE) != 0; 633 } 634 635 protected boolean hasInverse() 636 { 637 return (kind & (HAS_NAVIGABLE_INVERSE | IS_CONTAINMENT)) != 0; 638 } 639 640 protected boolean hasManyInverse() 641 { 642 return (kind & HAS_MANY_INVERSE) != 0; 643 } 644 645 protected boolean hasNavigableInverse() 646 { 647 return (kind & HAS_NAVIGABLE_INVERSE) != 0; 648 } 649 650 protected boolean isEObject() 651 { 652 return (kind & IS_EOBJECT) != 0; 653 } 654 655 protected boolean isContainment() 656 { 657 return (kind & IS_CONTAINMENT) != 0; 658 } 659 660 protected boolean hasProxies() 661 { 662 return (kind & HAS_PROXIES) != 0; 663 } 664 665 protected boolean hasInstanceClass() 666 { 667 return (kind & HAS_INSTANCE_CLASS) != 0; 668 } 669 670 protected boolean isContainer() 671 { 672 return (kind & IS_CONTAINER) != 0; 673 } 674 675 protected boolean isUnsettable() 676 { 677 return (kind & IS_UNSETTABLE) != 0; 678 } 679 680 public boolean isSet() 681 { 682 return isUnsettable() ? (kind & IS_SET) != 0 : !isEmpty(); 683 } 684 685 public void unset() 686 { 687 super.unset(); 688 if (isUnsettable()) 689 { 690 if (isNotificationRequired()) 691 { 692 boolean oldIsSet = (kind & IS_SET) != 0; 693 kind &= ~IS_SET; 694 owner.eNotify(createNotification(Notification.UNSET, oldIsSet, false)); 695 } 696 else 697 { 698 kind &= ~IS_SET; 699 } 700 } 701 } 702 703 protected void didChange() 704 { 705 kind |= IS_SET; 706 } 707 } 708 709 public static class Dynamic extends Generic 710 { 711 protected EStructuralFeature eStructuralFeature; 712 713 public Dynamic(InternalEObject owner, EStructuralFeature eStructuralFeature) 714 { 715 super(kind(eStructuralFeature), wrapperClassFor(eStructuralFeature.getEType().getInstanceClass()), owner); 716 this.eStructuralFeature = eStructuralFeature; 717 } 718 719 public Dynamic(int kind, InternalEObject owner, EStructuralFeature eStructuralFeature) 720 { 721 super(kind, wrapperClassFor(eStructuralFeature.getEType().getInstanceClass()), owner); 722 this.eStructuralFeature = eStructuralFeature; 723 } 724 725 public Dynamic(int kind, Class dataClass, InternalEObject owner, EStructuralFeature eStructuralFeature) 726 { 727 super(kind, dataClass, owner); 728 this.eStructuralFeature = eStructuralFeature; 729 } 730 731 public EStructuralFeature getEStructuralFeature() 732 { 733 return eStructuralFeature; 734 } 735 } 736 } 737 | Popular Tags |