Closed fkleedorfer closed 7 years ago
As for the design:
I think for the workflow it might be faster to prefill the "default address" and allow the user to change the location, e.g. by picking one of the previously entered addresses (extractable from ownNeeds
) or searching for a new address.
As of a64b50b5c211c3f6c19eb707232db6eb21a571dd the component queries nominatim after text-input – allowing selection among the results – as well as following a click directly on the map. Also it can display an alternative transport-focussed layer. Thus the following TODOs are still open:
As of f3a6914fdb06dd11a96516879af56286c13333ca current location works, markers get placed, the input veriefied and posted to the server. The following TODOs are open:
The location information of owned needs doesn't show up in the state, but is in the rdfstore. The culprit is the sparql-query for needs in the linkeddata-service-won.js
. It assumes a flat-ish structure, where the location information is actually nested.
A need example:
need:946717029499422700
a won:Need ;
won:hasBasicNeedType won:DoTogether ;
won:hasContent [ a won:NeedContent ;
dc:title "play Tennis" ;
won:hasContentDescription [ a won:NeedModality ;
won:hasBoundsNorthWest [ a geo:Point ;
geo:latitude "32.534779" ;
geo:longitude "-117.309805"
] ;
won:hasBoundsSouthEast [ a geo:Point ;
geo:latitude "33.114249" ;
geo:longitude "-116.905722"
] ;
won:hasLocation [ a geo:Point ;
won:hasAddress "San Diego, San Diego County, Kalifornien, Vereinigte Staaten von Amerika" ;
geo:latitude "32.717421" ;
geo:longitude "-117.162771"
]
]
] ;
won:hasFacet won:OwnerFacet ;
cert:key [ cert:PublicKey [ a woncrypt:ECCPublicKey ;
woncrypt:ecc_algorithm "EC" ;
woncrypt:ecc_curveId "secp384r1" ;
woncrypt:ecc_qx "841becab91d1ab2daddad922068fa60a0ef8dac216c670531a23f9c693b599abba0acabbc5136df95aa2768c852e31f8" ;
woncrypt:ecc_qy "7b94ff8b10bb216a1279be37566abc020292a0f04a9c8e57a4b4818146da230a9388d6b2d137b6b089a8ffe99973fb6a"
] ] .
}
The following query pulls the correct triples for the need by selecting everything attached to the content-node. However it returns a list of triples that aren't fit for use by the app yet.
var need = "<https://satsrv04.researchstudio.at:8889/won/resource/need/9064553301577927000>";
var query =
`
prefix won: <http://purl.org/webofneeds/model#>
construct {${need} ?b ?c. ?c ?d ?e. ?e ?f ?g. ?g ?h ?i} where {
{
${need} won:hasBasicNeedType ?c.
${need} ?b ?c
}
UNION
{
${need} won:hasContent ?c.
${need} ?b ?c
}
UNION
{
${need} won:hasContent ?c.
?c ?d ?e.
}
UNION
{
${need} won:hasContent ?c.
?c ?d ?e.
?e ?f ?g.
}
UNION
{
${need} won:hasContent ?c.
?c ?d ?e.
?e ?f ?g.
?g ?h ?i.
}
}
`
store4dbg.execute(query, (s, rs) => {
console.log(rs);
rs.triples.map(t => console.log(t.subject.nominalValue, t.predicate.nominalValue, t.object.nominalValue))
})
So we could either use that query and write a custom triple2json
-converter-function or take an entirely different route and use rdfstore.getNode(<uri>)
recursively on the content-node.
For transforming the result of this query, a naive approach – that assumes an acyclic content-node subgraph – would be:
function triples2json(rootUri, triples) {
const resultJson = {};
const rootTriples = triples.filter(t => t.subject.nominalValue === rootUri);
for(var t of rootTriples) {
const predicate = won.getLocalName(t.predicate.nominalValue);
switch(t.object.interfaceName) {
case "Literal":
// This is the simple case. we can just add it to our result object
var literal = t.object.nominalValue;
resultJson[predicate] = literal;
break;
case "NamedNode":
var namedNodeUri = t.object.nominalValue;
var isUsedAsSubject = (triples.filter(t_ => t_.subject.nominalValue === namedNodeUri).length > 0);
if(isUsedAsSubject) {
// treat like blank node
resultJson[predicate] = triples2json(namedNodeUri, triples);
} else {
// treat like literal node
resultJson[predicate] = namedNodeUri;
}
break;
case "BlankNode":
var blankNodeUri = t.object.nominalValue;
resultJson[predicate] = triples2json(blankNodeUri, triples);
break;
default:
throw new Exception("Encountered triple with object of unknown type: "
+ t.object.interfaceName + "\n" +
t.subject.nominalValue + " " +
t.predicate.nominalValue + " " +
t.object.nominalValue + " "
);
}
}
return resultJson;
}
A more stable and refined variant would transform the query results to jsonld and then frame along the lines of:
{
"@context": {
"won" : "http://purl.org/webofneeds/model#"
},
"@type": "won:Need",
"won:hasContent": {
"@type": "won:NeedContent"
}
}
This gives us properties with prefixes however (which is good as it avoids name-clashes, see #712) and thus require a lot of refactoring to go from the current, flattened version to the framed version.
Before (=current):
{
"uri": "https://satsrv04.researchstudio.at:8889/won/resource/need/9064553301577927000",
"basicNeedType": "http://purl.org/webofneeds/model#DoTogether",
"title": "program together",
"tags": null,
"textDescription": null,
"creationDate": "2016-08-02T10:57:04.62Z",
"state": "http://purl.org/webofneeds/model#Active",
"hasConnections": [
"https://satsrv04.researchstudio.at:8889/won/resource/connection/ado1r5wo3n72wb56473j",
"https://satsrv04.researchstudio.at:8889/won/resource/connection/uk4nbty32nsvgy5a8e9m"
]
}
After:
{
"@context": {
"msg": "http://purl.org/webofneeds/message#",
"conn": "https://satsrv04.researchstudio.at:8889/won/resource/connection/",
"woncrypt": "http://purl.org/webofneeds/woncrypt#",
"signature": "http://icp.it-risk.iwvi.uni-koblenz.de/ontologies/signature.owl#",
"need": "https://satsrv04.researchstudio.at:8889/won/resource/need/",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"cert": "http://www.w3.org/ns/auth/cert#",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
"local": "https://satsrv04.researchstudio.at:8889/won/resource/",
"geo": "http://www.w3.org/2003/01/geo/wgs84_pos#",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"won": "http://purl.org/webofneeds/model#",
"ldp": "http://www.w3.org/ns/ldp#",
"event": "https://satsrv04.researchstudio.at:8889/won/resource/event/",
"sioc": "http://rdfs.org/sioc/ns#",
"dc": "http://purl.org/dc/elements/1.1/"
},
"@graph": [
{
"@id": "need:9064553301577927000",
"@type": "won:Need",
"http://purl.org/dc/terms/created": {
"@type": "xsd:dateTime",
"@value": "2016-08-02T10:57:04.62Z"
},
"won:hasBasicNeedType": {
"@id": "won:DoTogether"
},
"won:hasConnections": {
"@id": "need:9064553301577927000/connections/"
},
"won:hasContent": {
"@id": "_:b4",
"@type": "won:NeedContent",
"dc:title": "program together",
"won:hasContentDescription": {
"@id": "_:b5",
"@type": "won:NeedModality",
"won:hasBoundsNorthWest": {
"@id": "_:b6",
"@type": "geo:Point",
"geo:latitude": "48.213814",
"geo:longitude": "16.340870"
},
"won:hasBoundsSouthEast": {
"@id": "_:b2",
"@type": "geo:Point",
"geo:latitude": "48.236309",
"geo:longitude": "16.370149"
},
"won:hasLocation": {
"@id": "_:b7",
"@type": "geo:Point",
"won:hasAddress": "Alsergrund, Wien, 1090, Österreich",
"geo:latitude": "48.225073",
"geo:longitude": "16.358398"
}
}
},
"won:hasEventContainer": {
"@id": "need:9064553301577927000#events",
"@type": "won:EventContainer",
"rdfs:member": [
{
"@id": "event:3223454307305560000"
},
{
"@id": "event:dywdp7fjnl4ngqvhe7e5"
}
]
},
"won:hasFacet": {
"@id": "won:OwnerFacet"
},
"won:hasWonNode": {
"@id": "https://satsrv04.researchstudio.at:8889/won/resource"
},
"won:isInState": {
"@id": "won:Active"
},
"cert:key": {
"@id": "_:b3",
"cert:PublicKey": {
"@id": "_:b1",
"@type": "woncrypt:ECCPublicKey",
"woncrypt:ecc_algorithm": "EC",
"woncrypt:ecc_curveId": "secp384r1",
"woncrypt:ecc_qx": "37f9b7cc083266e0cb7345d9a62619a2cf406503740395d2d69c617ac1e54b90c98e15501fab76739ce4a5bc5a680e48",
"woncrypt:ecc_qy": "46d802a5e187523f23ac08e4be5217536b230313ab7ad48db543b1bcb4b3307635a719e1d6895c13f6c5864fbe5ccd60"
}
}
}
]
}
Generated with the frame:
{
"@context": {
"msg" : "http://purl.org/webofneeds/message#",
"conn" : "https://satsrv04.researchstudio.at:8889/won/resource/connection/",
"woncrypt" : "http://purl.org/webofneeds/woncrypt#",
"signature" : "http://icp.it-risk.iwvi.uni-koblenz.de/ontologies/signature.owl#",
"need" : "https://satsrv04.researchstudio.at:8889/won/resource/need/",
"xsd" : "http://www.w3.org/2001/XMLSchema#",
"cert" : "http://www.w3.org/ns/auth/cert#",
"rdfs" : "http://www.w3.org/2000/01/rdf-schema#",
"local" : "https://satsrv04.researchstudio.at:8889/won/resource/",
"geo" : "http://www.w3.org/2003/01/geo/wgs84_pos#",
"rdf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"won" : "http://purl.org/webofneeds/model#",
"ldp" : "http://www.w3.org/ns/ldp#",
"event" : "https://satsrv04.researchstudio.at:8889/won/resource/event/",
"sioc" : "http://rdfs.org/sioc/ns#",
"dc" : "http://purl.org/dc/elements/1.1/"
},
"@type": "won:Need",
"won:hasContent": {
"@type": "won:NeedContent"
}
}
Note: The sparql-query needs to be limited in a way, that it includes the event containers but excludes the content of the events themselves. The depth of the query above accidentally does that, but should it change it might cause bugs. We need the list of eventUris along with the need but not the events themselves (that will be stored elsewhere in the state).
We could also filter out other stuff we don't need (e.g. the crypto-info) in the app that way to make the stored state smaller.
To go from the triples we get to jsonld, the function jsonld.promises.fromRdf
should be helpful.
Rdfstorejs probably registers a parser (like the this one) with jsonld.js somewhere that translates between their triple structures, so they can handle jsonld.
Apparently there's a far simpler geo ontology we can use, that also looks to be more of a standard.
An even easier option for transformation to jsonld would be to create and pass them in the 'normalized' format, e.g.:
_:c14n0 <http://schema.org/latitude> "40.75"^^<http://www.w3.org/2001/XMLSchema#float> .
_:c14n0 <http://schema.org/longitude> "73.98"^^<http://www.w3.org/2001/XMLSchema#float> .
_:c14n1 <http://schema.org/description> "The Empire State Building is a 102-story landmark in New York City." .
_:c14n1 <http://schema.org/geo> _:c14n0 .
_:c14n1 <http://schema.org/image> <http://www.civil.usherbrooke.ca/cours/gci215a/empire-state-building.jpg> .
_:c14n1 <http://schema.org/name> "The Empire State Building" .
rdfstorejs translates from it here
To delay a lot of refactoring due to added prefixes, we can use the 'compact' jsonld-form like in the first example here and define aliases for all predicates that are already in use.
Using a need like the one above, jsonld.toRDF
produced the following n-quad structure:
@default : Array[0]
https://satsrv04.researchstudio.at:8889/won/resource/event/4801209644582595000#envelope-sig : Array[11]
0 : Object
object : Object
type : "IRI"
value : "http://icp.it-risk.iwvi.uni-koblenz.de/ontologies/signature.owl#GraphSigningMethod"
__proto__ : Object
predicate : Object
type : "IRI"
value : "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
__proto__ : Object
subject : Object
type : "blank node"
value : "_:b0"
__proto__ : Object
__proto__ : Object
1 : Object
object : Object
predicate : Object
subject : Object
__proto__ : Object
2 : Object
3 : Object
4 : Object
5 : Object
6 : Object
7 : Object
8 : Object
9 : Object
10 : Object
length : 11
__proto__ : Array[0]
https://satsrv04.researchstudio.at:8889/won/resource/event/4801209644582595000#need : Array[28]
https://satsrv04.researchstudio.at:8889/won/resource/event/4801209644582595000#need-sig : Array[11]
https://satsrv04.researchstudio.at:8889/won/resource/need/2348825695750928400#sysinfo : Array[11]
that can then be fed into jsonld.fromRDF( … jsonld.frame( … ))
with an intermediate result of:
[Object, Object, Object, Object]
0 : Object
@graph : Array[2]
0 : Object
@id : "_:b0"
@type : Array[1]
http://icp.it-risk.iwvi.uni-koblenz.de/ontologies/signature.owl#hasDigestMethod : Array[1]
0 : Object
@id : "http://icp.it-risk.iwvi.uni-koblenz.de/ontologies/signature.owl#dm-sha-256"
__proto__ : Object
length : 1
__proto__ : Array[0]
http://icp.it-risk.iwvi.uni-koblenz.de/ontologies/signature.owl#hasGraphCanonicalizationMethod : Array[1]
http://icp.it-risk.iwvi.uni-koblenz.de/ontologies/signature.owl#hasGraphDigestMethod : Array[1]
http://icp.it-risk.iwvi.uni-koblenz.de/ontologies/signature.owl#hasGraphSerializationMethod : Array[1]
http://icp.it-risk.iwvi.uni-koblenz.de/ontologies/signature.owl#hasSignatureMethod : Array[1]
__proto__ : Object
1 : Object
length : 2
__proto__ : Array[0]
@id : "https://satsrv04.researchstudio.at:8889/won/resource/event/4801209644582595000#envelope-sig"
__proto__ : Object
1 : Object
2 : Object
3 : Object
length : 4
and final framed result of:
Object {@context: Object, @graph: Array[1]}
@context : Object
@graph : Array[1]
0 : Object
@id : "need:2348825695750928400"
@type : "won:Need"
cert:key : Object
http://purl.org/dc/terms/created : Object
won:hasBasicNeedType : Object
won:hasConnections : Object
won:hasContent : Object
won:hasEventContainer : Object
@id : "need:2348825695750928400#events"
@type : "won:EventContainer"
rdfs:member : Array[4]
__proto__ : Object
won:hasFacet : Object
won:hasWonNode : Object
won:isInState : Object
__proto__ : Object
length : 1
__proto__ : Array[0]
__proto__ : Object
All of the above were generated using the following snippet:
//context.compactArrays=true //for compact
//context.useNativeTypes=true //for fromRDF
//console.log('original: ', doc)
jsonld.toRDF(doc, {}, (err, triples) => {
console.log('triples: ', triples);
jsonld.fromRDF(triples, context, (err, complexJsonLd) => {
console.log('complexJsonLd: ', complexJsonLd);
//jsonld.compact(complexJsonLd, context, (err, compacted) => console.log('compacted: ', compacted));
jsonld.frame(complexJsonLd, frame, (err, framed) => console.log('framed: ', framed));
})
})
Open TODOs as of 418ccde87bccea1ab25c620f93e6dc3d81d1ba4b :
navigator.geolocation
's accuracy to a leaflet zoom-level / bounding-boxDownranking this item. There are more pressing things to do
comparing map tools:
Result: Leaflet (as we don't need the features offered by open-layers.)