Skip to content
Open
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
8 changes: 7 additions & 1 deletion src/main/kotlin/org/openmbee/flexo/mms/routes/Diffs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ fun Route.crudDiffs() {
}

// create a new diff
post {
post { slug ->
// set diff id on context so the diff is minted at {repo}/diffs/{slug}
diffId = slug

createDiff()
}

// method not allowed
otherwiseNotAllowed("diffs")
}
}
67 changes: 55 additions & 12 deletions src/main/kotlin/org/openmbee/flexo/mms/routes/Model.kt
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ fun AnyLayer1Context.genCommitUpdate(delete: String="", insert: String="", where
/**
* Used by ModelLoad to get difference between current staging graph and newly loaded graph in the form of delete/insert graphs
*/
fun AnyLayer1Context.genDiffUpdate(diffTriples: String="", conditions: ConditionsGroup?=null, rawWhere: String?=null): String {
fun AnyLayer1Context.genDiffUpdate(diffTriples: String="", conditions: ConditionsGroup?=null, rawWhere: String?=null, explicitDiffIri: String?=null): String {
return buildSparqlUpdate {
insert {
subtxn("diff", mapOf(
Expand All @@ -304,40 +304,49 @@ fun AnyLayer1Context.genDiffUpdate(diffTriples: String="", conditions: Condition

raw("""
graph ?insGraph {
?ins_s ?ins_p ?ins_o .
?ins_s ?ins_p ?ins_o .
}

graph ?delGraph {
?del_s ?del_p ?del_o .
}

graph mor-graph:Metadata {
?diff a mms:Diff ;
mms:id ?diffId ;
mms:etag ?diffId ;
mms:createdBy mu: ;
mms:srcCommit ?srcCommit ;
mms:dstCommit ?dstCommit ;
mms:insGraph ?insGraph ;
mms:delGraph ?delGraph .

$diffTriples
}
""")
}
where {
raw("""
${conditions?.requiredPatterns()?.joinToString("\n") ?: ""}

${rawWhere?: ""}

bind(
sha256(
concat(str(?dstCommit), "\n", str(?srcCommit))
) as ?diffId
)

bind(
iri(
concat(str(?dstCommit), "/diffs/", ?diffId)
) as ?diff
)


${if(explicitDiffIri != null) """
bind(<$explicitDiffIri> as ?diff)
""" else """
bind(
iri(
concat(str(?dstCommit), "/diffs/", ?diffId)
) as ?diff
)
"""}

bind(
iri(
concat(str(mor-graph:), "Diff.Ins.", ?diffId)
Expand Down Expand Up @@ -467,6 +476,40 @@ suspend fun AnyLayer1Context.diffAndFinalizeCommit(dstGraphIri: String, srcGraph
val deleteModel = parseModelStripPrefixes(RdfContentTypes.Turtle, deleteDataResponseText)
// empty delta (no changes)
if (insertModel.isEmpty && deleteModel.isEmpty) {
// remove the diff metadata and auto-created policy inserted by the diff update above;
// the commit this diff describes will never be created, so leaving them would accrete a
// dangling mms:Diff and an orphaned policy on every no-op update
executeSparqlUpdate("""
delete {
graph mor-graph:Metadata {
?diff ?diff_p ?diff_o .
}
graph m-graph:AccessControl.Policies {
?createdPolicy ?createdPolicy_p ?createdPolicy_o .
}
graph m-graph:Transactions {
mt: mms:createdPolicy ?createdPolicy .
}
}
where {
graph mor-graph:Metadata {
?diff a mms:Diff ;
mms:dstCommit morc: ;
?diff_p ?diff_o .
}
optional {
graph m-graph:Transactions {
mt: mms:createdPolicy ?createdPolicy .
}
graph m-graph:AccessControl.Policies {
?createdPolicy ?createdPolicy_p ?createdPolicy_o .
}
}
}
""") {
prefixes(prefixes)
}

// locate branch node
val branchNode = diffConstructModel.createResource(prefixes["morb"])
// get its etag value
Expand Down
46 changes: 20 additions & 26 deletions src/main/kotlin/org/openmbee/flexo/mms/routes/ldp/DiffCreate.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import io.ktor.server.response.*
import org.openmbee.flexo.mms.*
import org.openmbee.flexo.mms.server.LdpDcLayer1Context
import org.openmbee.flexo.mms.server.LdpPostResponse
import org.openmbee.flexo.mms.routes.sparql.deleteTransaction
import org.openmbee.flexo.mms.routes.sparql.genDiffUpdate
import java.security.MessageDigest


// default starting conditions for any calls to create a lock
private val DEFAULT_CONDITIONS = COMMIT_CRUD_CONDITIONS.append {
// default starting conditions for any calls to create a diff. the repo must exist; the src and
// dst refs are validated by appendSrcRef()/appendDstRef() (a diff request has no commit in its
// path, so commit-level conditions do not apply here)
private val DEFAULT_CONDITIONS = REPO_CRUD_CONDITIONS.append {
// require that the user has the ability to create diffs on a repo-level scope
permit(Permission.CREATE_DIFF, Scope.REPO)

Expand Down Expand Up @@ -46,7 +49,7 @@ suspend fun LdpDcLayer1Context<LdpPostResponse>.createDiff() {
var createDiffUserDataTriples = ""

// process RDF body from user about this new diff
filterIncomingStatements("morl") {
filterIncomingStatements("mord") {
// relative to this diff node
diffNode().apply {
// assert cardinality for src and dst refs
Expand All @@ -73,26 +76,26 @@ suspend fun LdpDcLayer1Context<LdpPostResponse>.createDiff() {
// extend the default conditions with requirements for user-specified src and dst refs
val localConditions = DEFAULT_CONDITIONS.appendSrcRef().appendDstRef()

// prep SPARQL UPDATE string
// prep SPARQL UPDATE string; the diff is minted at the repo-addressed IRI from the request
val updateString = genDiffUpdate(createDiffUserDataTriples, localConditions, """
graph mor-graph:Metadata {
# select the commit pointed to by the source ref
?srcRef mms:commit ?srcCommit .

# locate its corresponding snapshot and model graph
?srcCommit ^mms:commit/mms:snapshot ?srcSnapshot .
?srcSnapshot a mms:Model ;
?srcSnapshot a mms:Model ;
mms:graph ?srcGraph .
# select the commit pointed to by the destination ref

# select the commit pointed to by the destination ref
?dstRef mms:commit ?dstCommit .

# locate its corresponding snapshot and model graph
?dstCommit ^mms:commit/mms:snapshot ?dstSnapshot .
?dstSnapshot a mms:Model ;
?dstSnapshot a mms:Model ;
mms:graph ?dstGraph .
}
""")
""", explicitDiffIri=prefixes["mord"]!!)

// execute update
executeSparqlUpdate(updateString) {
Expand Down Expand Up @@ -141,21 +144,12 @@ suspend fun LdpDcLayer1Context<LdpPostResponse>.createDiff() {
// check that the user-supplied HTTP preconditions were met
handleEtagAndPreconditions(constructModel, prefixes["mord"])

// provide location of new resource
call.response.header(HttpHeaders.Location, prefixes["mord"]!!)

// respond
call.respondText(constructResponseText, RdfContentTypes.Turtle)

// delete transaction
run {
// submit update
val dropResponseText = executeSparqlUpdate("""
delete where {
graph m-graph:Transactions {
mt: ?p ?o .
}
}
""")
call.respondText(constructResponseText, RdfContentTypes.Turtle, HttpStatusCode.Created)

// log response
log.info(dropResponseText)
}
// delete transaction (including the mt:diff subtransaction created by the diff update)
deleteTransaction()
}
Loading