Skip to content

Commit

Permalink
Merge pull request #564 from moosetechnology/importer-improvements
Browse files Browse the repository at this point in the history
Abstract classes in MM
  • Loading branch information
ClotildeToullec authored Mar 8, 2023
2 parents 9e6f6d9 + 33794c1 commit 4fdd56a
Show file tree
Hide file tree
Showing 30 changed files with 402 additions and 183 deletions.
7 changes: 7 additions & 0 deletions src/Famix-Java-Entities/FamixJavaEntity.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ FamixJavaEntity class >> annotation [
^self
]

{ #category : #testing }
FamixJavaEntity class >> isAbstract [

<generated>
^ self == FamixJavaEntity
]

{ #category : #meta }
FamixJavaEntity class >> metamodel [

Expand Down
26 changes: 25 additions & 1 deletion src/Famix-MetamodelBuilder-Core/FamixMetamodelBuilder.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,18 @@ FamixMetamodelBuilder >> configuration: anObject [
configuration := anObject
]

{ #category : #initialization }
FamixMetamodelBuilder >> ensureAbstractClassNamed: aString [

^ self classes
detect: [ :each | each name = aString ]
ifFound: [ :aClass |
aClass
isAbstractClass: true;
yourself ]
ifNone: [ self newAbstractClassNamed: aString ]
]

{ #category : #initialization }
FamixMetamodelBuilder >> ensureClassNamed: aString [

Expand All @@ -148,7 +160,7 @@ FamixMetamodelBuilder >> ensureEntityClassIsTheCommonSuperclass [
self classes iterator | #isRoot selectIt
| #isMetamodelClassGroup rejectIt | #isModelClass rejectIt
| [ :class | class name = #Entity ] rejectIt
| [ :class | class --|> (self ensureClassNamed: #Entity) ] doIt
| [ :class | class --|> (self ensureAbstractClassNamed: #Entity) ] doIt
> NullAddableObject
]

Expand Down Expand Up @@ -398,6 +410,18 @@ FamixMetamodelBuilder >> model [
^ aClass
]

{ #category : #initialization }
FamixMetamodelBuilder >> newAbstractClassNamed: aClassName [

(self classes select: [ :each | each name = aClassName ])
ifNotEmpty: [ FmxMBEntityAlreadyExists signal ].

^ self newClass
name: aClassName;
isAbstractClass: true;
yourself
]

{ #category : #initialization }
FamixMetamodelBuilder >> newClass [

Expand Down
2 changes: 1 addition & 1 deletion src/Famix-MetamodelBuilder-Core/FmxMBBehavior.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ FmxMBBehavior >> generalization: anObject [
ifFalse: [ anObject isMetamodelTrait ifTrue: [ self addTraitGeneralization: anObject ] ifFalse: [ self classGeneralization: anObject ] ]
]

{ #category : #accessing }
{ #category : #generating }
FmxMBBehavior >> generate [
^ self subclassResponsibility
]
Expand Down
61 changes: 46 additions & 15 deletions src/Famix-MetamodelBuilder-Core/FmxMBClass.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ Class {
#name : #FmxMBClass,
#superclass : #FmxMBBehavior,
#instVars : [
'classGeneralization'
'classGeneralization',
'isAbstractClass'
],
#category : #'Famix-MetamodelBuilder-Core-Implementation'
}
Expand Down Expand Up @@ -47,35 +48,53 @@ FmxMBClass >> classGeneralization: anObject [
FmxMBClass >> generate [

| aClass aSuperclass aClassName |

self willGenerate ifFalse: [ ^ self ].

aClassName := self fullName.

aSuperclass := self classGeneralization
ifNil: [ self defaultSuperclass ]
ifNotNil: [ self classGeneralization realClass ].

aClass := self builder environment createClassNamed: aClassName asSymbol superclass: aSuperclass traitNames: self allTraitNames slots: self slotDefinitions in: self packageName overwrite: true.


aSuperclass := self classGeneralization
ifNil: [ self defaultSuperclass ]
ifNotNil: [ self classGeneralization realClass ].

aClass := self builder environment
createClassNamed: aClassName asSymbol
superclass: aSuperclass
traitNames: self allTraitNames
slots: self slotDefinitions
in: self packageName
overwrite: true.

aClass tagWith: self tag.
self builder environment setComment: self comment for: aClass.

self realClass: aClass.

self generateAccessors.
self generateAnnotationIn: aClass as: self name superclass: nil.

self generateIsAbstractMethodIfNecessaryIn: aClass.

self generateTestingMethodsIn: aClass.
self generateRootMetamodelMethodIn: aClass.

self generateMethodsToRemoveFromTraitCompositionFor: aClass.
self generatePrecedenceInTraitComposition: aClass.

self generateNavigationGroupsFor: aClass.
self generateAddToCollectionFor: aClass
]

{ #category : #generating }
FmxMBClass >> generateIsAbstractMethodIfNecessaryIn: aClass [

self isAbstractClass ifTrue: [
aClass classSide
compile: ('isAbstract
<generated>
^ self == {1}' format: { aClass name asString })
classified: 'testing' ]
]

{ #category : #generating }
FmxMBClass >> generateRemotes [
| aClass aClassName |
Expand Down Expand Up @@ -119,6 +138,18 @@ FmxMBClass >> generateTestingMethodsIn: aClass [
super generateTestingMethodsIn: aClass
]

{ #category : #testing }
FmxMBClass >> isAbstractClass [

^ isAbstractClass ifNil: [ false ]
]

{ #category : #accessing }
FmxMBClass >> isAbstractClass: aBoolean [

isAbstractClass := aBoolean
]

{ #category : #testing }
FmxMBClass >> isMetamodelClass [

Expand All @@ -130,7 +161,7 @@ FmxMBClass >> isRoot [
^ self classGeneralization isNil
]

{ #category : #generating }
{ #category : #generalization }
FmxMBClass >> subclassOf: aClass [

self generalization: aClass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,81 +4,106 @@ Class {
#category : #'Famix-MetamodelBuilder-Core-Implementation'
}

{ #category : #printing }
{ #category : #generation }
FmxMBNonRemoteRelationSideGenerationStrategy >> generateGetterCoreIn: aClassOrTrait on: aStream for: aRelationSide [

aStream
tab;
nextPutAll: ('<FMProperty: #{1} type: #{2} opposite: #{3}>' format: {aRelationSide name . aRelationSide oppositeType . aRelationSide oppositeName});
nextPutAll:
('<FMProperty: #{1} type: #{2} opposite: #{3}>' format: {
aRelationSide name.
aRelationSide oppositeType.
aRelationSide oppositeName });
cr.

aRelationSide
remoteBuilderDo: [ :aRemoteBuilder |
aStream
tab;
nextPutAll: ('<package: #''{1}''>' format: {aRemoteBuilder generator packageName});
cr ].
aRelationSide remoteBuilderDo: [ :aRemoteBuilder |
aStream
tab;
nextPutAll: ('<package: #''{1}''>' format:
{ aRemoteBuilder generator packageName });
cr ].

aStream
tab;
nextPutAll: '^ self attributeAt: #';
nextPutAll: aRelationSide name.

aRelationSide isOne ifTrue: [ aStream nextPutAll: ' ifAbsent: [ nil ]' ].
aRelationSide isOne ifTrue: [
aStream nextPutAll: ' ifAbsent: [ nil ]' ].

(aRelationSide otherSide isOne and: [ aRelationSide isMany ])
ifTrue: [ aStream nextPutAll: (' ifAbsentPut: [ FMMultivalueLink on: self opposite: #{1}: ]' format: {aRelationSide otherSide name}) ].
(aRelationSide otherSide isOne and: [ aRelationSide isMany ])
ifTrue: [
aStream nextPutAll:
(' ifAbsentPut: [ FMMultivalueLink on: self opposite: #{1}: ]'
format: { aRelationSide otherSide name }) ].

(aRelationSide isMany and: [ aRelationSide otherSide isMany ])
ifTrue: [ aStream nextPutAll: (' ifAbsentPut: [ FMMultiMultivalueLink on: self opposite: #{1} ]' format: {aRelationSide otherSide name}) ]
(aRelationSide isMany and: [ aRelationSide otherSide isMany ])
ifTrue: [
aStream nextPutAll:
(' ifAbsentPut: [ FMMultiMultivalueLink on: self opposite: #{1} ]'
format: { aRelationSide otherSide name }) ]
]

{ #category : #printing }
{ #category : #generation }
FmxMBNonRemoteRelationSideGenerationStrategy >> generateSetterCoreIn: aClassOrTrait on: aStream for: aRelationSide [
(aRelationSide isOne and: [ aRelationSide otherSide isOne ])
ifTrue: [ aStream
tab;
nextPutAll: ('(self attributeAt: #{1} ifAbsentPut: [nil]) == anObject ifTrue: [ ^ anObject ].' format: {aRelationSide name});
cr;
tab;
nextPutAll: 'anObject ifNil: [ | otherSide |';
cr;
tab;
tab;
nextPutAll: ('otherSide := self {1}.' format: {aRelationSide name});
cr;
tab;
tab;
nextPutAll: ('self attributeAt: #{1} put: anObject.' format: {aRelationSide name});
cr;
tab;
tab;
nextPutAll: ('otherSide {1}: nil ]' format: {aRelationSide otherSide name});
cr;
tab;
nextPutAll: ('ifNotNil: [ ' format: {aRelationSide otherSide name});
cr;
tab;
tab;
nextPutAll: ('self attributeAt: #{1} put: anObject.' format: {aRelationSide name});
cr;
tab;
tab;
nextPutAll: ('anObject {1}: self ]' format: {aRelationSide otherSide name}) ].

aRelationSide isMany
ifTrue: [ aStream
tab;
nextPutAll: ('self {1} value: anObject' format: {aRelationSide name}) ].
(aRelationSide isOne and: [ aRelationSide otherSide isOne ]) ifTrue: [
aStream
tab;
nextPutAll:
('(self attributeAt: #{1} ifAbsentPut: [nil]) == anObject ifTrue: [ ^ anObject ].'
format: { aRelationSide name });
cr;
tab;
nextPutAll: 'anObject ifNil: [ | otherSide |';
cr;
tab;
tab;
nextPutAll:
('otherSide := self {1}.' format: { aRelationSide name });
cr;
tab;
tab;
nextPutAll: ('self attributeAt: #{1} put: anObject.' format:
{ aRelationSide name });
cr;
tab;
tab;
nextPutAll:
('otherSide {1}: nil ]' format: { aRelationSide otherSide name });
cr;
tab;
nextPutAll:
('ifNotNil: [ ' format: { aRelationSide otherSide name });
cr;
tab;
tab;
nextPutAll: ('self attributeAt: #{1} put: anObject.' format:
{ aRelationSide name });
cr;
tab;
tab;
nextPutAll:
('anObject {1}: self ]' format: { aRelationSide otherSide name }) ].

(aRelationSide otherSide isMany and: [ aRelationSide isOne ])
ifTrue: [ aStream
aRelationSide isMany ifTrue: [
aStream
tab;
nextPutAll:
('self {1} value: anObject' format: { aRelationSide name }) ].

(aRelationSide otherSide isMany and: [ aRelationSide isOne ])
ifTrue: [
aStream
tab;
nextPutAll:
('self attributeAt: #{1} put: (FMMultivalueLink on: self update: #{2} from: self {1} to: anObject).'
format: {aRelationSide name . aRelationSide otherSide name}) ]
('self attributeAt: #{1} put: (FMMultivalueLink on: self update: #{2} from: self {1} to: anObject).'
format: {
aRelationSide name.
aRelationSide otherSide name }) ]
]

{ #category : #printing }
{ #category : #testing }
FmxMBNonRemoteRelationSideGenerationStrategy >> producesSlot [

^ false
Expand Down
Loading

0 comments on commit 4fdd56a

Please sign in to comment.