-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from mkllnk/setter
Allow to provide a setter for each property
- Loading branch information
Showing
6 changed files
with
328 additions
and
169 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
--require spec_helper | ||
--require virtual_assembly/semantizer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
# Copyright © 2023 Maxime Lecoq, <[email protected]> | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software | ||
|
@@ -23,153 +25,142 @@ | |
# A semanticObject holds semantic properties (SemanticProperty) | ||
# that refers to linked data concepts. | ||
# | ||
# For example, a Person object including this module could register | ||
# For example, a Person object including this module could register | ||
# in its initializer method a semantic property for its name like: | ||
# Person.registerSemanticProperty("http://xmlns.com/foaf/0.1/name") {self.name} | ||
module VirtualAssembly::Semantizer::SemanticObject | ||
|
||
# The semantic ID implements the concept of linked data ID. | ||
# | ||
# This ID is an uri pointing to the location of the object | ||
# on the web like "https://mywebsite/myobject" for instance. | ||
# | ||
# If a SemanticObject doesn't define its ID, it | ||
# will be considered as a blank node. | ||
# | ||
# This should be a String or nil. | ||
attr_accessor :semanticId | ||
|
||
# The semantic type implements the concept of linked data type | ||
# (also called class). | ||
# | ||
# This type is an uri pointing to the location of the linked | ||
# data concept on the web like "http://xmlns.com/foaf/0.1/Person" | ||
# for instance. | ||
# | ||
# This should be a String or nil. | ||
attr_accessor :semanticType | ||
|
||
# This Array stores the semantic properties of the object. | ||
# To append a SemanticProperty, use the dedicated | ||
# registerSemanticProperty method. You should pass the value | ||
# of the property as a block (callback) like so: | ||
# registerSemanticProperty("http://xmlns.com/foaf/0.1/name") {self.name}. | ||
attr_reader :semanticProperties | ||
|
||
# If the semanticId is nil, the object will be treated as a blank node. | ||
def initialize(semanticId = nil, semanticType = nil) | ||
@semanticProperties = Array.new | ||
|
||
# This Hash allows us to find a property using its name. | ||
# | ||
# Hash<String, Integer> | ||
# | ||
# The key store the name of a property (String). | ||
# The value store the index of the property in the | ||
# semanticProperties array (Integer). | ||
@semanticPropertiesNameIndex = Hash.new | ||
module VirtualAssembly | ||
module Semantizer | ||
module SemanticObject | ||
# The semantic ID implements the concept of linked data ID. | ||
# | ||
# This ID is an uri pointing to the location of the object | ||
# on the web like "https://mywebsite/myobject" for instance. | ||
# | ||
# If a SemanticObject doesn't define its ID, it | ||
# will be considered as a blank node. | ||
# | ||
# This should be a String or nil. | ||
attr_accessor :semanticId | ||
|
||
# The semantic type implements the concept of linked data type | ||
# (also called class). | ||
# | ||
# This type is an uri pointing to the location of the linked | ||
# data concept on the web like "http://xmlns.com/foaf/0.1/Person" | ||
# for instance. | ||
# | ||
# This should be a String or nil. | ||
attr_accessor :semanticType | ||
|
||
# If the semanticId is nil, the object will be treated as a blank node. | ||
def initialize(semanticId = nil, semanticType = nil) | ||
@semanticPropertiesMap = {} | ||
|
||
# Ensure to call the setter methods | ||
self.semanticId = semanticId | ||
self.semanticType = semanticType | ||
end | ||
|
||
def hasSemanticProperty?(name) | ||
return @semanticPropertiesNameIndex.include?(name) | ||
end | ||
|
||
def isBlankNode? | ||
return @semanticId == nil || @semanticId == "" | ||
end | ||
|
||
# Given the name of the property, it returns the value | ||
# associated to a property of this object. | ||
def semanticPropertyValue(name) | ||
index = @semanticPropertiesNameIndex.fetch(name, nil) | ||
return index != nil ? @semanticProperties[index].value : nil; | ||
end | ||
|
||
# Use this method to append a semantic property to this object. | ||
# The value of the property should be passed as a block so its | ||
# value would be up to date when we will access it. | ||
def registerSemanticProperty(name, &valueGetter) | ||
end | ||
|
||
# This Array stores the semantic properties of the object. | ||
# To append a SemanticProperty, use the dedicated | ||
# registerSemanticProperty method. You should pass the value | ||
# of the property as a block (callback) like so: | ||
# registerSemanticProperty("http://xmlns.com/foaf/0.1/name") {self.name}. | ||
def semanticProperties | ||
@semanticPropertiesMap.values | ||
end | ||
|
||
def hasSemanticProperty?(name) | ||
@semanticPropertiesMap.key?(name) | ||
end | ||
|
||
def isBlankNode? | ||
@semanticId.nil? || @semanticId == '' | ||
end | ||
|
||
# Given the name of the property, it returns the value | ||
# associated to a property of this object. | ||
def semanticPropertyValue(name) | ||
semanticProperty(name)&.value | ||
end | ||
|
||
# Given its name, returns the corresponding SemanticProperty | ||
# stored by this object or nil if the property does not exist. | ||
def semanticProperty(name) | ||
@semanticPropertiesMap[name] | ||
end | ||
|
||
# Use this method to append a semantic property to this object. | ||
# The value of the property should be passed as a block so its | ||
# value would be up to date when we will access it. | ||
def registerSemanticProperty(name, &valueGetter) | ||
createOrUpdateSemanticProperty(name, valueGetter) | ||
end | ||
|
||
# Sets the semantic id of the object and registers the | ||
# corresponding semantic property. | ||
# | ||
# The semantic ID implements the concept of linked data ID. | ||
# | ||
# This ID is an uri pointing to the location of the object | ||
# on the web like "https://mywebsite/myobject" for instance. | ||
# | ||
# If a SemanticObject doesn't define its ID, it | ||
# will be considered as a blank node. | ||
# | ||
# This should be a String or nil. | ||
def semanticId=(uri) | ||
end | ||
|
||
# Sets the semantic id of the object and registers the | ||
# corresponding semantic property. | ||
# | ||
# The semantic ID implements the concept of linked data ID. | ||
# | ||
# This ID is an uri pointing to the location of the object | ||
# on the web like "https://mywebsite/myobject" for instance. | ||
# | ||
# If a SemanticObject doesn't define its ID, it | ||
# will be considered as a blank node. | ||
# | ||
# This should be a String or nil. | ||
def semanticId=(uri) | ||
@semanticId = uri | ||
registerSemanticProperty("@id") {self.semanticId} | ||
end | ||
|
||
# Sets the semantic type of the object and registers the | ||
# corresponding semantic property. | ||
# | ||
# The semantic type implements the concept of linked data type | ||
# (also called class). | ||
# | ||
# This type is an uri pointing to the location of the linked | ||
# data concept on the web like "http://xmlns.com/foaf/0.1/Person" | ||
# for instance. | ||
# | ||
# This should be a String or nil. | ||
def semanticType=(type) | ||
property = registerSemanticProperty('@id') { semanticId } | ||
property.valueSetter = ->(value) { @semanticId = value } | ||
end | ||
|
||
# Sets the semantic type of the object and registers the | ||
# corresponding semantic property. | ||
# | ||
# The semantic type implements the concept of linked data type | ||
# (also called class). | ||
# | ||
# This type is an uri pointing to the location of the linked | ||
# data concept on the web like "http://xmlns.com/foaf/0.1/Person" | ||
# for instance. | ||
# | ||
# This should be a String or nil. | ||
def semanticType=(type) | ||
@semanticType = type | ||
registerSemanticProperty("@type") {self.semanticType} | ||
end | ||
|
||
# Serialize all the semantic properties of this object | ||
# to an output format. | ||
# | ||
# You could use the HashSerializer to export as a Hash. | ||
# This Hash should be then exported to JSON for instance. | ||
def serialize(serializer) | ||
return serializer.process(self) | ||
end | ||
|
||
protected | ||
|
||
# If the semantic property already exist in this object, this | ||
# method will simply update the valueGetter of the property. | ||
# | ||
# If this object does not holds the property, the new property | ||
# will be added into the semanticProperties Array of this object. | ||
def createOrUpdateSemanticProperty(name, valueGetter) | ||
# Update | ||
if (hasSemanticProperty?(name)) | ||
semanticProperty = findSemanticProperty(name) | ||
if (semanticProperty != nil) | ||
semanticProperty.valueGetter = valueGetter | ||
end | ||
|
||
# Create | ||
else | ||
@semanticProperties.push(VirtualAssembly::Semantizer::SemanticProperty.new(name, &valueGetter)) | ||
index = @semanticProperties.count - 1 | ||
@semanticPropertiesNameIndex.store(name, index); | ||
end | ||
end | ||
|
||
# Given its name, returns the corresponding SemanticProperty | ||
# stored by this object or nil if the property does not exist. | ||
def findSemanticProperty(name) | ||
begin | ||
index = @semanticPropertiesNameIndex.fetch(name) | ||
return @semanticProperties.at(index) | ||
rescue | ||
return nil | ||
end | ||
property = registerSemanticProperty('@type') { semanticType } | ||
property.valueSetter = ->(value) { @semanticType = value } | ||
end | ||
|
||
# Serialize all the semantic properties of this object | ||
# to an output format. | ||
# | ||
# You could use the HashSerializer to export as a Hash. | ||
# This Hash should be then exported to JSON for instance. | ||
def serialize(serializer) | ||
serializer.process(self) | ||
end | ||
|
||
protected | ||
|
||
# If the semantic property already exist in this object, this | ||
# method will simply update the valueGetter of the property. | ||
# | ||
# If this object does not holds the property, the new property | ||
# will be added into the semanticProperties Array of this object. | ||
def createOrUpdateSemanticProperty(name, valueGetter) | ||
# Update | ||
if hasSemanticProperty?(name) | ||
property = semanticProperty(name) | ||
property&.valueGetter = valueGetter | ||
|
||
# Create | ||
else | ||
property = VirtualAssembly::Semantizer::SemanticProperty.new(name, &valueGetter) | ||
@semanticPropertiesMap[name] = property | ||
end | ||
|
||
end | ||
property | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
# Copyright © 2023 Maxime Lecoq, <[email protected]> | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software | ||
|
@@ -15,49 +17,61 @@ | |
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
|
||
# The SemanticPropety class is designed to turn properties of | ||
# The SemanticPropety class is designed to turn properties of | ||
# objects into linked data. | ||
# | ||
# A SemanticProperty has a name and a corresponding value that | ||
# can be fetched later (so its value would be up to date). | ||
# | ||
# This class is intented to be used through the SemanticObject | ||
# This class is intented to be used through the SemanticObject | ||
# class. | ||
# | ||
# | ||
# For instance, we can tell that the name of a Person object refers | ||
# to the linked data concept "name" from the FOAF project. The name | ||
# of the property would be the uri of the FOAF:name property while the | ||
# value would be the attribute reader of the name of the Person object. | ||
# | ||
# You should use a block to pass the value like so: | ||
# SemanticProperty.new("http://xmlns.com/foaf/0.1/name") {self.name} | ||
class VirtualAssembly::Semantizer::SemanticProperty | ||
|
||
# The name of the property. It generally points to an uri | ||
# like "http://xmlns.com/foaf/0.1/name" or it is used to | ||
# define a reserved linked data property like "@id". | ||
# | ||
# This should be a String. | ||
attr_accessor :name | ||
|
||
# The function to call when the value is requested. | ||
# | ||
# This should be a Proc passed as a Block. | ||
attr_accessor :valueGetter | ||
|
||
# @param name The name of the property, like | ||
# "http://xmlns.com/foaf/0.1/name" or "@id" for instance. | ||
# | ||
# @param valueGetter A Proc used to retrieve the value of the | ||
# property when requested. | ||
def initialize(name, &valueGetter) | ||
module VirtualAssembly | ||
module Semantizer | ||
class SemanticProperty | ||
# The name of the property. It generally points to an uri | ||
# like "http://xmlns.com/foaf/0.1/name" or it is used to | ||
# define a reserved linked data property like "@id". | ||
# | ||
# This should be a String. | ||
attr_accessor :name | ||
|
||
# The function to call when the value is requested. | ||
# | ||
# This should be a Proc passed as a Block. | ||
attr_accessor :valueGetter | ||
|
||
# The function to call to store a new value. | ||
# | ||
# This should be a Proc | ||
attr_accessor :valueSetter | ||
|
||
# @param name The name of the property, like | ||
# "http://xmlns.com/foaf/0.1/name" or "@id" for instance. | ||
# | ||
# @param valueGetter A Proc used to retrieve the value of the | ||
# property when requested. | ||
def initialize(name, &valueGetter) | ||
@name = name | ||
@valueGetter = valueGetter | ||
end | ||
end | ||
|
||
# Fetch and returns the value associated to this property. | ||
def value | ||
return @valueGetter.call | ||
end | ||
# Fetch and returns the value associated to this property. | ||
def value | ||
@valueGetter.call | ||
end | ||
|
||
end | ||
# Stores a new value for this property. | ||
def value=(new_value) | ||
@valueSetter.call(new_value) | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.