Skip to content

Commit

Permalink
Merge pull request #70 from moosetechnology/69-Make-FMMultivalueLink-…
Browse files Browse the repository at this point in the history
…inherit-OrderedCollection

Close #69: FMMultivalueLink inherits from OrderedCollection
  • Loading branch information
Gabriel-Darbord committed Dec 22, 2023
2 parents 48a7d50 + 8df51fe commit ad77571
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 154 deletions.
42 changes: 17 additions & 25 deletions src/Fame-Core/FMMultiMultivalueLink.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -25,58 +25,50 @@ Class {
}

{ #category : #adding }
FMMultiMultivalueLink >> add: anElement [
(anElement perform: opposite) unsafeAdd: owner.
(values includes: anElement) ifFalse: [ values add: anElement ].
^ anElement
]
FMMultiMultivalueLink >> addOpposite: anElement [

{ #category : #removing }
FMMultiMultivalueLink >> remove: anElement ifAbsent: exceptionBlock [

values remove: anElement ifAbsent: [ ^exceptionBlock value ].
(anElement perform: opposite) unsafeRemove: owner.
^anElement
(anElement perform: opposite) unsafeAdd: owner
]

{ #category : #removing }
FMMultiMultivalueLink >> removeAll [
values reversed
do: [ :anElement | (anElement perform: opposite) remove: owner ]
FMMultiMultivalueLink >> removeOpposite: anElement [

(anElement perform: opposite) unsafeRemove: owner
]

{ #category : #'private - adding' }
FMMultiMultivalueLink >> uncheckAdd: anElement [
FMMultiMultivalueLink >> uncheckAdd: anElement [

(anElement perform: opposite) uncheckUnsafeAdd: owner.
values add: anElement.
self uncheckUnsafeAdd: anElement.
^ anElement
]

{ #category : #'private - adding' }
FMMultiMultivalueLink >> uncheckAddAll: aCollection [
FMMultiMultivalueLink >> uncheckAddAll: aCollection [
"Include all the elements of aCollection as the receiver's elements. Answer
aCollection. Actually, any object responding to #do: can be used as argument."

aCollection do: [ :each | self uncheckAdd: each ].
^ aCollection
]

{ #category : #'private - adding' }
FMMultiMultivalueLink >> uncheckUnsafeAdd: element [
values add: element
]

{ #category : #adding }
FMMultiMultivalueLink >> value: aCollection [

^ self
removeAll: values copy;
uncheckAddAll: aCollection asOrderedCollection removeDuplicates
removeAll;
"We want unique elements and to keep the order, but `removeDuplicates` is really slow."
uncheckAddAll: (aCollection
collect: [ :element | element -> nil ]
as: OrderedDictionary) keys
]

{ #category : #private }
FMMultiMultivalueLink >> with: element opposite: oppositeSelector [

self assert: oppositeSelector numArgs = 0.
values := OrderedCollection new.
self setContents: #( ).
owner := element.
opposite := oppositeSelector
]
174 changes: 45 additions & 129 deletions src/Fame-Core/FMMultivalueLink.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ that refers to it are updated accordingly.
"
Class {
#name : #FMMultivalueLink,
#superclass : #Collection,
#superclass : #OrderedCollection,
#instVars : [
'values',
'owner',
'opposite'
],
Expand All @@ -58,116 +57,47 @@ FMMultivalueLink class >> on: element update: selector from: old to: new [
^ new
]

{ #category : #copying }
FMMultivalueLink >> , aCollection [
^ self asOrderedCollection , aCollection
]

{ #category : #comparing }
FMMultivalueLink >> = otherCollection [
"Answer true if the receiver is equivalent to the otherCollection.
First test for identity, then rule out different species and sizes of
collections. As a last resort, examine each element of the receiver
and the otherCollection."

self == otherCollection ifTrue: [^ true].
self species == otherCollection species ifFalse: [^ false].
^ values hasEqualElements: otherCollection asOrderedCollection
]

{ #category : #adding }
FMMultivalueLink >> add: anElement [
anElement perform: opposite with: owner.
FMMultivalueLink >> addLast: anElement [

self addOpposite: anElement.
self unsafeAdd: anElement.
^ anElement
]

{ #category : #accessing }
FMMultivalueLink >> at: index [
{ #category : #adding }
FMMultivalueLink >> addOpposite: anElement [

^values at: index
anElement perform: opposite with: owner
]

{ #category : #iterators }
FMMultivalueLink >> basicIterator [
^ values basicIterator
{ #category : #converting }
FMMultivalueLink >> asOrderedCollection [

^ OrderedCollection newFrom: self
]

{ #category : #accessing }
FMMultivalueLink >> byName: name [

^ self byName: name ifAbsent: [ self errorNotFound: name ]
]

{ #category : #accessing }
FMMultivalueLink >> byName: name ifAbsent: exceptionBlock [
^ values
detect: [ :each | each name asString = name asString ]
ifNone: exceptionBlock

^ self
detect: [ :each | each name asString = name asString ]
ifNone: exceptionBlock
]

{ #category : #accessing }
FMMultivalueLink >> byName: name ifPresent: aBlock ifAbsent: exceptionBlock [
^ values
detect: [ :each | each name asString = name asString ]
ifFound: aBlock
ifNone: exceptionBlock
]

{ #category : #enumerating }
FMMultivalueLink >> do: aBlock [

values do: aBlock
]

{ #category : #'accessing-computed' }
FMMultivalueLink >> eighth [
^ self at: 8
]

{ #category : #'accessing-computed' }
FMMultivalueLink >> fifth [
^ self at: 5
]

{ #category : #'accessing-computed' }
FMMultivalueLink >> first [
^ self at: 1
]

{ #category : #'accessing-computed' }
FMMultivalueLink >> fourth [
^ self at: 4
]

{ #category : #comparing }
FMMultivalueLink >> hash [
"From sequenceable collection"
| hash |
hash := self species hash.
1 to: self size do: [ :i | hash := (hash + (self at: i) hash) hashMultiply ].
^ hash
]

{ #category : #iterators }
FMMultivalueLink >> iterator [
^ values iterator
]

{ #category : #'accessing-computed' }
FMMultivalueLink >> last [
^ values last
]

{ #category : #'accessing-computed' }
FMMultivalueLink >> ninth [
^ self at: 9
]

{ #category : #copying }
FMMultivalueLink >> postCopy [

super postCopy.
values := values copy.
^ self
detect: [ :each | each name asString = name asString ]
ifFound: aBlock
ifNone: exceptionBlock
]

{ #category : #printing }
Expand All @@ -177,79 +107,65 @@ FMMultivalueLink >> printOn: aStream [
]

{ #category : #removing }
FMMultivalueLink >> remove: anElement ifAbsent: exceptionBlock [
values remove: anElement ifAbsent: [ ^exceptionBlock value ].
anElement perform: opposite with: nil.
^anElement
FMMultivalueLink >> remove: anElement ifAbsent: exceptionBlock [

super remove: anElement ifAbsent: [ ^ exceptionBlock value ].
self removeOpposite: anElement.
^ anElement
]

{ #category : #removing }
FMMultivalueLink >> removeAll [
values reversed
do: [ :anElement | anElement perform: opposite with: nil ]
]
"The collection is reversed to make a copy, to avoid trying to remove while iterating,
and to remove items from last to first, which is faster."

{ #category : #'accessing-computed' }
FMMultivalueLink >> second [
^ self at: 2
self reversed do: [ :anElement | self remove: anElement ]
]

{ #category : #'accessing-computed' }
FMMultivalueLink >> seventh [
^ self at: 7
]

{ #category : #'accessing-computed' }
FMMultivalueLink >> sixth [
^ self at: 6
]

{ #category : #accessing }
FMMultivalueLink >> size [
{ #category : #removing }
FMMultivalueLink >> removeOpposite: anElement [

^values size
anElement perform: opposite with: nil
]

{ #category : #private }
FMMultivalueLink >> species [

^OrderedCollection
^ OrderedCollection
]

{ #category : #'accessing-computed' }
FMMultivalueLink >> third [
^ self at: 3
{ #category : #private }
FMMultivalueLink >> uncheckUnsafeAdd: element [
"Calls the implementation in OrderedCollection."

super addLast: element
]

{ #category : #private }
FMMultivalueLink >> unsafeAdd: element [
(values includes: element)
ifFalse: [ values add: element ]

(self includes: element) ifFalse: [ super addLast: element ]
]

{ #category : #private }
FMMultivalueLink >> unsafeRemove: element [

values remove: element ifAbsent: nil
super remove: element ifAbsent: nil
]

{ #category : #adding }
FMMultivalueLink >> value: aCollection [

^self removeAll: values copy; addAll: aCollection
^ self
removeAll;
addAll: aCollection
]

{ #category : #private }
FMMultivalueLink >> with: element opposite: oppositeSelector [

self assert: oppositeSelector numArgs = 1.
values := OrderedCollection new.
self setContents: #( ).
owner := element.
opposite := oppositeSelector
]

{ #category : #enumerating }
FMMultivalueLink >> withIndexDo: aBlock [

values withIndexDo: aBlock
]
Loading

0 comments on commit ad77571

Please sign in to comment.