Commit ebade411 authored by Günter Hipler's avatar Günter Hipler
Browse files

implementation of usage rights with detailed explanaitons

parent 26e2f701
Pipeline #24064 failed with stages
in 3 minutes and 14 seconds
......@@ -35,11 +35,7 @@ object Extractors {
Try {
jsonGraph.value.collectFirst {
case res
if (res.obj
.contains("type") && res.obj("type").str == resourceType) ||
(res.obj.contains("@type") && res
.obj("@type")
.str == resourceType) =>
if (res.obj.contains("type") && res.obj("type").str == resourceType) =>
res.obj.value
}.get
}
......@@ -488,6 +484,97 @@ object Extractors {
}.toList
/*
alternative Schreibweise
def alternativeSchreibweise(graph:JArr, dO:mutable.LinkedHashMap[String, JValue]):List[String] = {
getAllBlankNodeContent(graph)(dO)("regulatedBy")
.collect {
case res if res.obj("type").str == "usage" =>
res.obj("name").str
}.toList
}
also: hier sind die Parameter schön als Inputparameter mit einem Namen aufgeführt, den ich im Body verweden kann
Man kann sehr schnell sagen: Ja warum machen wir es nicht generell so, ist doch einfacher zu lesen!
Ja, hat aber Nachteile, da man diese Form nicht so ohne weiteres als Paramter an andere Funktionen weiterreichen kann
Wenn Du anföngst zu lesen, nennen das die Hipsters "function as a value"
In Scala 3 (wird nächsten Monat publiziert) verschwimmen die Grenzen, glaube ich, mehr
Glaubst Du den scala hipstern, wird mit Scala 3 die Welt dann zu einem Paradies...
*/
val usageRegulationDigitalObject
//hier zuerst wieder der Typ des identifiers usageRegulationDigitalObject
//das rico Objekt als Graph und wir möchten gerne das Objekt in der Json - Struktir des Graphen zurück,
//die ein digitales Objekt repräsentiert
:JArr => mutable.LinkedHashMap[String, JValue] => List[String] = {
//Ok, nach dem Gleichheitszeichen beginnt die Implementierung der Funktion
// wieder daran denken, dass alles eine Expression, ein Wert ist (symbolisiert mit dem Gleichheitszeichen
//in Java, PHP und Co. findest Du i.d.R. return statements. etwas was in Scala verpönt ist....
graph =>
digitalObject =>
//graph und digital Object ist letztendlich nur Syntax-sugar von scala
//schau oben in die "klassische" Funktionsschreibweise
//def alternativeSchreibweise
//das ist das was Du eher kennst. Ich bin eine gewisse Zeit an diesem tollen Syntax-sugar (von dem es noch viel
//mehr gibt) verzweifeifelt....
//aber das ist sicherlich eine schöne Diskussion zusammen mit Sebastian....
getAllBlankNodeContent(graph)(digitalObject)("regulatedBy")
//gehe wieder mit der Maus auf getAllBlankNodeContent. Dann bekommst Du wieder die Funktionssignatur angezeigt
//Neben den drei Parametern, auf die die Funktion angwendet wird (auch so eine Sprechweise, die ich mir etwas angewöhnen
//musste (ich sage sonst häufig "man gibt der Funktion Parameter mit" - wenn man darüber nachdenkt und andere
// Sprachkonstrukte vor Augen hat wie partially applied functions macht die Spachweise "ich wende eine Funktion
// auf Parameter an Sinn - Du brauchst dafür einfach ein wenig Zeit)
//Also: Wert von getAllBlanNodeContent ist
//ArrayBuffer[mutable.LinkedHashMap[String, Value]
//also: wieder eine Form von Liste, deren Elemente ich durchlaufen kann
.collect {
//das was wir auf die Liste anwenden ist die Funktion collect
//gehe wieder mit dem Mauszeiger auf collect und drücke ctrl+Leertaste
//collect benötigt einen Eingabeparameter. Dieser ist wieder vom Typ function, genauer gesagt
//PartialFunktion[mutable.linkedHashMap[String, Value],B]
//Rückgabewert von collect ist ArrayBuffer[B]
//Was eine PartialFunction genau ist besprechen wir später. Hier würde ich mir das so vorstellen:
//sie symbolisiert die Möglichkeit, dass die Funktion keinen Wert zurückliefert - hier einen Wert für den wir
//einfach B setzen, falls sie einen Wert gibt.
//also: collect nutzt unsere mitgegebene Funktion um Elemente zu sammeln und gibt alle gesammelten Werte
//als ArrayBuffer[B] also Elemente vom Typ B (was B ist wird durch unsere Implementierung festgelegt)
//hier noch dieses komische
//case res if ....
//die Scala Hipster bezeichnen das als "Pattern Matching on anonymous functions" verbunden mit
//speziellem Scala Zucker für Partial Functions
//vergiss das im Moment, wenn Du in die Scala Hipster Sprache ein wenig und über eine gewisse Zeit
//hineingetaucht bist, wirst Du auch so eine Jüngerin.... - topp, die Wette gilt!
//noch etwas: Scala ist für mich nicht das Evangelium (dafür bin ich viel zu katholisch, zumindest so
//aufgewachsen). Aber es gibt Dir eine Denkschulung für Konzepte, die Du auf ganz viele andere Dinge
//anwenden kannst, die in Bereichen, in denen mit Daten umgegangen wird, sehr sinnvoll sind)
//auch wenn Du in anderen Kontexten Python einsetzen möchtest
//Denkweisen die man sich in Java, PHP und Co. angwöhnt hat sind da eher hinderlich (ich spreche
//aus leidvoller Erfahrung)
case res if res.obj.contains("type") && res.obj("type").str == "usage" &&
res.obj.contains("sameAs") => res.obj("sameAs").str
//also: stell Dir vor, mit diesem "case res" sitzen wir im body in der von uns erstellten PartialFunction
//und der Identifier (die Variable) ist das digitale Objekt, welches uns interessiert und mit
//getAllBlankNodeContent gesammelt wurde. Wir entscheiden nun:
//gibt es in diesem digitalen Objekt eine property "type" und enthält diese den Wert usage
//und gint es die property sameAs
//wenn das so ist, liefern wir als Funktionswert
// => res.obj("sameAs").str zurück
//hier wieder "der Pfeil" auf dessen rechten Seite ein Funktionswert stehen muss.
//wir wollen keinen ArrayBuffer (pfui etwas veränderbares - die Scala Hipster lieben
//immutable (unveränderliche) Werte. Also noch schnell ein
//.toList nachgeschoben
//damit erfüllen wir die Signatur unserer Funktion getAllBlankNodeContent
//:JArr => mutable.LinkedHashMap[String, JValue] => List[String]
}.toList
}
val license: JArr => mutable.LinkedHashMap[String, JValue] => Option[String] =
graph =>
digitalObject =>
......
......@@ -26,6 +26,9 @@ import ch.memobase.rico2edm.rdf.writer.RdfXmlWriter
import org.eclipse.rdf4j.rio.Rio
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
import ujson.Value
import scala.collection.mutable.ArrayBuffer
class ExtractorSpecWebResource extends AnyFunSuite with Matchers {
......@@ -33,6 +36,8 @@ class ExtractorSpecWebResource extends AnyFunSuite with Matchers {
private lazy val rawErroneousFile = loadFile("src/test/resources/raw1LError.json")
private lazy val rawRicoIndent = loadFile("src/test/resources/rawIndent.json")
private lazy val rawEdmRights = loadFile("src/test/resources/rico.certainty.json")
private lazy val graph = Extractors.jsonGraph(rawRico).get
test ("get digital object") {
......@@ -61,7 +66,42 @@ class ExtractorSpecWebResource extends AnyFunSuite with Matchers {
Rio.write(webresource.get.getModel, rdfWriter)
}
}
test ("edm:rights property") {
/*
Warum jsonGraph(...).get?
Signatur von Extractors.jsonGraph (Mauszeiger auf jsonGraph und ctrl+Leertaste): String => Try[Value.Value]
d.h. eine Funktion mit einem Parameter vom Typ String (der gesamte rico Graph, der als event vom Kafka topic kommt
oder aber der Testgraph in unseren unitTest
Rückgabewert ist Try[Value.Value]
Für den Beginn würde ich mir folgendes vorstellen:
- anders als in Java, PHP,... ist in Scala fast alles ein Typ mit einem Wert (Expression). Du kannst übliche Typen
wie Int (mit dem Wert Zahl) oder String (Zeichenkette) haben. Try steht für einen Typ,
der das Ergebnis einet Berechnung repräsentiert. Diese hat entweder den Wert erfolgreich oder fehlerhaft
Wenn ErgebnisvonTry.get schreibst, bist Du dir sicher, dass die Berechnung (Funktionsergebnis) erfolreich war.
Wenn das nicht der Fall ist, stürzt Dir das Programm ab
*/
val graphGet: Value = Extractors.jsonGraph(rawEdmRights).get
/*
graphGet.arr wandelt die Typen um. Macht also aus Value.Value einen ArrayBuffer[Value]. Also
eine Collection mit besonderen Eigenschaften (Eigenschaften von Array)
gehe hier wieder mit der Maus auf graphGet oder graphGet.arr und drücke ctrl+Leertaste. Dann werden die Typen angezeigt
Wenn Du den Mauszeiger auf digitalObject setzt und auch dort ctrl+Leertaste drückst, wird Dir die Signatur
Arr => Try[mutable.LinkedHashMap[String,Value.Value] angezeigt
Also: wir geben graphGet als Array mit und erhalten einen Wert Try[das digitale Objekt] zurück.
Try kann auch hier wieder erfolgreich oder fehlerhaft sein
in unserem Fall bei der Suche nach Regulationsregeln für das digitale Objekt, gehen wir davon aus, dass wir
ein digitales Objekt gefunden haben. Deswegen dObj.get
*/
val dObj = Extractors.digitalObject(graphGet.arr)
val usage = Extractors.usageRegulationDigitalObject(graphGet.arr)(dObj.get)
println(usage)
//List(http://rightsstatements.org/vocab/CNE/1.0/)
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment