Skip to content

Commit

Permalink
Implement jacksonImporter for Pharo
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiovandewaeter committed Apr 29, 2024
1 parent 25cc359 commit 495f3c2
Show file tree
Hide file tree
Showing 14 changed files with 313 additions and 9 deletions.
22 changes: 14 additions & 8 deletions src/Famix-Value-Exporter/FamixValue2PharoVisitor.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,16 @@ FamixValue2PharoVisitor >> visitDictionary: dictionary [
selector: #newFrom:
arguments:
{ (RBArrayNode statements: (dictionary value collect: [ :assoc |
RBMessageNode
receiver: (self ensureVisited: assoc key)
selector: #'->'
arguments: { (self ensureVisited: assoc value) } ])) }
self visitDictionaryAssociation: assoc ])) }
]

{ #category : #visiting }
FamixValue2PharoVisitor >> visitDictionaryAssociation: association [

^ RBMessageNode
receiver: (self ensureVisited: association key)
selector: #'->'
arguments: { (self ensureVisited: association value) }
]

{ #category : #visiting }
Expand All @@ -74,10 +80,10 @@ FamixValue2PharoVisitor >> visitObject: object [
objectNode := RBMessageNode
receiver: (RBVariableNode named: object type name)
selector: #new.
attributeNodes := object value
collect: [ :attribute |
self visitObjectAttribute: attribute ]
thenReject: #isNil.
attributeNodes := (object value
collect: [ :attribute |
self visitObjectAttribute: attribute ]
as: OrderedCollection) reject: #isNil.
attributeNodes ifEmpty: [ ^ objectNode ].
attributeNodes first receiver: objectNode.
attributeNodes add:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Extension { #name : #FamixValueOfDictionaryAssociation }
{ #category : #'*Famix-Value-Exporter' }
FamixValueOfDictionaryAssociation >> accept: visitor [

self shouldNotImplement
^ visitor visitDictionaryAssociation: self
]

{ #category : #'*Famix-Value-Exporter' }
Expand Down
6 changes: 6 additions & 0 deletions src/Famix-Value-Importer/Association.extension.st
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
Extension { #name : #Association }

{ #category : #'*Famix-Value-Importer' }
Association >> asPharoJacksonValueOn: importer [

^ importer importAssociation: self
]

{ #category : #'*Famix-Value-Importer' }
Association >> asPharoSTONValueOn: importer [

Expand Down
6 changes: 6 additions & 0 deletions src/Famix-Value-Importer/Character.extension.st
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
Extension { #name : #Character }

{ #category : #'*Famix-Value-Importer' }
Character >> asPharoJacksonValueOn: importer [

^ importer importPrimitive: self of: self className
]

{ #category : #'*Famix-Value-Importer' }
Character >> asPharoSTONValueOn: importer [

Expand Down
8 changes: 8 additions & 0 deletions src/Famix-Value-Importer/Collection.extension.st
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ Collection >> asJavaJacksonValueOn: importer [
^ importer importValueFromList: self of: importer loadType
]

{ #category : #'*Famix-Value-Importer' }
Collection >> asPharoJacksonValueOn: importer [

^ importer
importCollection: self
of: (importer loadTypeNamed: self className)
]

{ #category : #'*Famix-Value-Importer' }
Collection >> asPharoSTONValueOn: importer [

Expand Down
20 changes: 20 additions & 0 deletions src/Famix-Value-Importer/Dictionary.extension.st
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
Extension { #name : #Dictionary }

{ #category : #'*Famix-Value-Importer' }
Dictionary >> asPharoJacksonValueOn: importer [

^ (self removeKey: importer typeKey ifAbsent: nil)
ifNotNil: [ :className | "object of an unloaded class"
importer
importObject: self
of: (importer loadTypeNamed: className) ]
ifNil: [ "species of dictionary"
(self removeKey: importer refKey ifAbsent: nil)
ifNotNil: [ :refId | "if @ref"
importer
getObjectFromIdentity: refId
ifAbsent: [ Error signal: 'unknown id' ] ]
ifNil: [ "if Dictionary there only is @id"
importer
importDictionary: self
of: (importer loadTypeNamed: self className) ] ]
]

{ #category : #'*Famix-Value-Importer' }
Dictionary >> asPharoSTONValueOn: importer [

Expand Down
7 changes: 7 additions & 0 deletions src/Famix-Value-Importer/FamixStMethod.extension.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Extension { #name : #FamixStMethod }

{ #category : #'*Famix-Value-Importer' }
FamixStMethod >> isProcedure [

^ false
]
209 changes: 209 additions & 0 deletions src/Famix-Value-Importer/FamixValuePharoJacksonImporter.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
Class {
#name : #FamixValuePharoJacksonImporter,
#superclass : #FamixValueAbstractImporter,
#instVars : [
'typeKey',
'idKey',
'refKey',
'specialTypes'
],
#category : #'Famix-Value-Importer'
}

{ #category : #importing }
FamixValuePharoJacksonImporter >> getDefaultUnknownType [

^ self getUnknownTypeNamed: 'Object'
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> getObjectIdentity: rawObject [
"Keep track of objects by using the id given by Jackson.
References to previously seen objects are serialized by using this id."

^ rawObject removeKey: self idKey ifAbsent: nil
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> idKey [

^ idKey ifNil: [ idKey := '@id' ]
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> idKey: aString [

idKey := aString
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> importAssociation: rawValue of: type [

| association |
association := self model newOfDictionaryAssociation type: type.
objectDict at: (self getObjectIdentity: rawValue) put: association.
association key: (self importValue: (rawValue at: 'key')).
association value: (self importValue: (rawValue at: 'value')).
^ association
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> importCharacter: value of: type [

^ self importPrimitive: (value at: 'value') asCharacter of: type name
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> importClassReference: rawValue of: type [
"The type has already been loaded during the inference.
The raw value contains the fully qualified name of the referenced class."

^ self model newOfClassReference
value: (self loadTypeNamed: rawValue);
type: type
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> importDictionary: rawValue of: type [
"infer from type arguments, e.g. Map<String, MyClass>"

| dictionary assoc |
dictionary := self model newOfDictionary type: type.
objectDict at: (self getObjectIdentity: rawValue) put: dictionary.
rawValue associationsDo: [ :rawAssoc |
assoc := self model newOfDictionaryAssociation dictionary:
dictionary.
assoc key: (self importValue: rawAssoc key).
assoc value: (self importValue: rawAssoc value) ].
^ dictionary
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> importObject: rawObject of: type [


self specialTypes
at: type name
ifPresent: [ :block | ^ block value: rawObject value: type ].
^ super importObject: rawObject of: type
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> importObjectAttribute: rawValue of: type named: name [

| attribute |
(attribute := type findAttributeNamed: name).
^ self
withTypeInference:
(attribute ifNotNil: [ attribute declaredType ])
do: [
self model newOfObjectAttribute
value: (self importValue: rawValue);
attribute: attribute ]
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> importSpecialObject: rawValue of: type [
"Some objects have special rules for serialization.
They should have a corresponding type wrapper that knows how to handle them."

self specialTypes
at: type mooseNameWithDots
ifPresent: [ :typeWrapper |
^ typeWrapper import: rawValue wrapping: type on: self ].
^ nil
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> importValue: rawValue [

^ rawValue asPharoJacksonValueOn: self
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> importValueFromList: rawValue of: type [
"Jackson can serialize different types of values in a list, so we need to find out which it is."

rawValue isCollection ifTrue: [
^ self importCollection: rawValue of: type ].
type isUnknownType ifTrue: [
^ self model newOfUnknownType
value: rawValue;
type: type ].
(type usesFamixTrait: FamixTEnum) ifTrue: [
^ self importEnumValue: rawValue of: type ].
(self isPrimitiveType: type) ifTrue: [
^ self model newOfPrimitiveType
value: rawValue;
type: type ].
type isClass ifTrue: [ "might be a special object"
(self importSpecialObject: rawValue of: type) ifNotNil: [ :object |
^ object ] ].
self error: 'Unknown type: ' , type mooseNameWithDots
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> isPrimitiveType: type [

^ type isPrimitiveType or: [ "Classes wrapping primitives are also considered primitives."
type isPrimitiveWrapper ]
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> newReader [

^ NeoJSONReader new
]

{ #category : #parsing }
FamixValuePharoJacksonImporter >> parseList: serializedValues [
"Ignore first element which is the id of the array."

^ (super parseList: serializedValues) allButFirst
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> refKey [

^ refKey ifNil: [ refKey := '@ref' ]
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> refKey: aString [

refKey := aString
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> specialTypes [

^ specialTypes ifNil: [
specialTypes := Dictionary new.
specialTypes
at: 'Character'
put: [ :value :type | self importCharacter: value of: type ].
specialTypes
at: 'Association'
put: [ :value :type | self importAssociation: value of: type ].
specialTypes
at: 'OrderedCollection'
put: [ :value :type |
self importCollection: (value at: 'array') of: type ].
specialTypes
at: 'Set'
put: [ :value :type |
self importCollection: (value at: 'array') of: type ].
specialTypes ]
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> typeKey [

^ typeKey ifNil: [ typeKey := '@type' ]
]

{ #category : #importing }
FamixValuePharoJacksonImporter >> typeKey: aString [

typeKey := aString
]
6 changes: 6 additions & 0 deletions src/Famix-Value-Importer/Number.extension.st
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
Extension { #name : #Number }

{ #category : #'*Famix-Value-Importer' }
Number >> asPharoJacksonValueOn: importer [

^ importer importPrimitive: self of: self className
]

{ #category : #'*Famix-Value-Importer' }
Number >> asPharoSTONValueOn: importer [

Expand Down
8 changes: 8 additions & 0 deletions src/Famix-Value-Importer/Object.extension.st
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
Extension { #name : #Object }

{ #category : #'*Famix-Value-Importer' }
Object >> asPharoJacksonValueOn: importer [

^ importer
importObject: self
of: (importer loadTypeNamed: self className)
]

{ #category : #'*Famix-Value-Importer' }
Object >> asPharoSTONValueOn: importer [

Expand Down
8 changes: 8 additions & 0 deletions src/Famix-Value-Importer/RunArray.extension.st
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
Extension { #name : #RunArray }

{ #category : #'*Famix-Value-Importer' }
RunArray >> asPharoJacksonValueOn: importer [

^ importer
importObject: self
of: (importer loadTypeNamed: self className)
]

{ #category : #'*Famix-Value-Importer' }
RunArray >> asPharoSTONValueOn: importer [

Expand Down
6 changes: 6 additions & 0 deletions src/Famix-Value-Importer/String.extension.st
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ String >> asJavaJacksonValueOn: importer [
of: 'java.lang.String' ]
]

{ #category : #'*Famix-Value-Importer' }
String >> asPharoJacksonValueOn: importer [

^ importer importPrimitive: self of: self className
]

{ #category : #'*Famix-Value-Importer' }
String >> asPharoSTONValueOn: importer [

Expand Down
8 changes: 8 additions & 0 deletions src/Famix-Value-Importer/Text.extension.st
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
Extension { #name : #Text }

{ #category : #'*Famix-Value-Importer' }
Text >> asPharoJacksonValueOn: importer [

^ importer
importObject: self
of: (importer loadTypeNamed: self className)
]

{ #category : #'*Famix-Value-Importer' }
Text >> asPharoSTONValueOn: importer [

Expand Down
Loading

0 comments on commit 495f3c2

Please sign in to comment.