Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstract classes in MM #564

Merged
merged 3 commits into from
Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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