Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
acdc
repository-extension-services
Commits
2736421a
Commit
2736421a
authored
Sep 18, 2015
by
acoburn
Browse files
working implementation of id-mapping service
parent
34d2a63e
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
83 additions
and
20 deletions
+83
-20
acrepo-idiomatic/README.md
acrepo-idiomatic/README.md
+10
-0
acrepo-idiomatic/src/main/cfg/edu.amherst.acdc.idiomatic.cfg
acrepo-idiomatic/src/main/cfg/edu.amherst.acdc.idiomatic.cfg
+5
-0
acrepo-idiomatic/src/main/java/edu/amherst/acdc/idiomatic/EventRouter.java
...src/main/java/edu/amherst/acdc/idiomatic/EventRouter.java
+31
-19
acrepo-idiomatic/src/main/java/edu/amherst/acdc/idiomatic/IdiomaticHeaders.java
...ain/java/edu/amherst/acdc/idiomatic/IdiomaticHeaders.java
+30
-0
acrepo-idiomatic/src/main/resources/OSGI-INF/blueprint/blueprint.xml
...matic/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+2
-1
acrepo-idiomatic/src/test/java/edu/amherst/idiomatic/RouteTest.java
...omatic/src/test/java/edu/amherst/idiomatic/RouteTest.java
+5
-0
No files found.
acrepo-idiomatic/README.md
View file @
2736421a
...
...
@@ -3,6 +3,16 @@ Amherst College ID Mapping Service
This service implements a way to map external IDs to internal fedora URIs.
Database Structure
------------------
The backing database is assumed to be accessed via SQL. It follows a very simple
format, using a single table (
`uris`
) with two columns (
`public`
and
`fedora`
):
CREATE TABLE uris (
public VARCHAR(1024) CONSTRAINT publicid PRIMARY KEY,
fedora VARCHAR(1024) CONSTRAINT fedoraid NOT NULL);
Building
--------
...
...
acrepo-idiomatic/src/main/cfg/edu.amherst.acdc.idiomatic.cfg
View file @
2736421a
...
...
@@ -15,3 +15,8 @@ id.property=dc:identifier
# The full namespace of the above property
id.namespace=http://purl.org/dc/elements/1.1/
# An external identifier may have a standard prefix, as it is stored
# in fedora. By setting this value, that prefix will be removed from
# the id-mapping layer (e.g. http://example.org/)
id.prefix=
acrepo-idiomatic/src/main/java/edu/amherst/acdc/idiomatic/EventRouter.java
View file @
2736421a
...
...
@@ -14,9 +14,12 @@
package
edu.amherst.acdc.idiomatic
;
import
static
org
.
apache
.
camel
.
builder
.
PredicateBuilder
.
not
;
import
static
edu
.
amherst
.
acdc
.
idiomatic
.
IdiomaticHeaders
.
FEDORA
;
import
static
edu
.
amherst
.
acdc
.
idiomatic
.
IdiomaticHeaders
.
ID
;
import
org.apache.camel.Exchange
;
import
org.apache.camel.LoggingLevel
;
import
org.apache.camel.Processor
;
import
org.apache.camel.PropertyInject
;
import
org.apache.camel.RuntimeCamelException
;
import
org.apache.camel.builder.RouteBuilder
;
...
...
@@ -29,10 +32,6 @@ import org.apache.camel.builder.xml.Namespaces;
*/
public
class
EventRouter
extends
RouteBuilder
{
private
static
final
String
CQL_INSERT
=
"insert into uris(fedora, public) values (?, ?)"
;
private
static
final
String
CQL_GET
=
""
;
private
static
final
String
CQL_DELETE
=
""
;
@PropertyInject
(
value
=
"rest.port"
,
defaultValue
=
"9081"
)
private
String
port
;
...
...
@@ -41,9 +40,11 @@ public class EventRouter extends RouteBuilder {
*/
public
void
configure
()
throws
Exception
{
final
String
idPrefix
;
final
Namespaces
ns
=
new
Namespaces
(
"rdf"
,
"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
);
try
{
idPrefix
=
getContext
().
resolvePropertyPlaceholders
(
"{{id.prefix}}"
);
final
String
property
=
getContext
().
resolvePropertyPlaceholders
(
"{{id.property}}"
);
final
String
namespace
=
getContext
().
resolvePropertyPlaceholders
(
"{{id.namespace}}"
);
final
String
prefix
=
property
.
substring
(
0
,
property
.
indexOf
(
":"
));
...
...
@@ -69,44 +70,55 @@ public class EventRouter extends RouteBuilder {
from
(
"direct:event"
)
.
routeId
(
"IdMappingEventRouter"
)
.
log
(
LoggingLevel
.
INFO
,
"edu.amherst.acdc.idiomatic"
,
"IdMapping Event: ${headers[org.fcrepo.jms.identifier]}"
)
.
log
(
LoggingLevel
.
INFO
,
"IdMapping Event: ${headers[org.fcrepo.jms.identifier]}"
)
.
to
(
"fcrepo:{{fcrepo.baseUrl}}?preferOmit=PreferContainment"
)
.
split
().
xtokenize
(
"//{{id.property}}"
,
'i'
,
ns
)
.
transform
().
xpath
(
"/{{id.property}}/@rdf:resource | /{{id.property}}/text()"
,
String
.
class
,
ns
)
.
process
(
new
IdProcessor
())
.
setHeader
(
ID
).
xpath
(
"/{{id.property}}/@rdf:resource | /{{id.property}}/text()"
,
String
.
class
,
ns
)
.
process
(
new
Processor
()
{
public
void
process
(
final
Exchange
ex
)
throws
Exception
{
ex
.
getIn
().
setHeader
(
ID
,
ex
.
getIn
().
getHeader
(
ID
,
String
.
class
).
replaceAll
(
"^"
+
idPrefix
,
""
));
}})
.
transform
().
simple
(
"${header[org.fcrepo.jms.identifier]}"
)
.
to
(
"direct:update"
);
/**
* REST routing
*/
rest
(
"{{rest.prefix}}"
)
.
get
(
"/{
id
}"
).
to
(
"direct:get"
)
.
get
(
"/{
"
+
ID
+
"
}"
).
to
(
"direct:get"
)
.
post
(
"/"
).
to
(
"direct:minter"
)
.
put
(
"/{
id
}"
).
to
(
"direct:update"
)
.
delete
(
"/{
id
}"
).
to
(
"direct:delete"
);
.
put
(
"/{
"
+
ID
+
"
}"
).
to
(
"direct:update"
)
.
delete
(
"/{
"
+
ID
+
"
}"
).
to
(
"direct:delete"
);
/**
* Handle CRUD operations
*/
from
(
"direct:update"
)
.
routeId
(
"IdMappingUpdateRouter"
)
.
to
(
"sql:UPDATE uris SET fedora=:#fedora WHERE public=:#public"
)
.
setHeader
(
Exchange
.
HTTP_RESPONSE_CODE
).
constant
(
204
)
.
filter
(
simple
(
"${body} == 0"
))
.
to
(
"sql:INSERT INTO uris (fedora, public) VALUES (:#fedora, :#public)"
);
.
setHeader
(
FEDORA
).
simple
(
"${body}"
)
.
setHeader
(
Exchange
.
HTTP_RESPONSE_CODE
).
constant
(
400
)
.
filter
(
header
(
FEDORA
))
.
log
(
LoggingLevel
.
INFO
,
"Updating ${headers["
+
ID
+
"]} with ${headers["
+
FEDORA
+
"]}"
)
.
to
(
"sql:UPDATE uris SET fedora=:#"
+
FEDORA
+
" WHERE public=:#"
+
ID
)
.
setHeader
(
Exchange
.
HTTP_RESPONSE_CODE
).
constant
(
204
)
.
choice
()
.
when
(
header
(
"CamelSqlUpdateCount"
).
isEqualTo
(
"0"
))
.
to
(
"sql:INSERT INTO uris (fedora, public) VALUES (:#"
+
FEDORA
+
", :#"
+
ID
+
")"
).
end
()
.
removeHeader
(
ID
)
.
removeHeader
(
FEDORA
);
from
(
"direct:get"
)
.
routeId
(
"IdMappingFetchRouter"
)
.
to
(
"sql:SELECT fedora FROM uris WHERE public=:#
id
?outputType=SelectOne"
)
.
removeHeader
(
"id"
)
.
to
(
"sql:SELECT fedora FROM uris WHERE public=:#
"
+
ID
+
"
?outputType=SelectOne"
)
.
removeHeader
(
ID
)
.
filter
(
not
(
header
(
"CamelSqlRowCount"
).
isEqualTo
(
1
)))
.
setHeader
(
Exchange
.
HTTP_RESPONSE_CODE
).
constant
(
404
);
from
(
"direct:delete"
)
.
routeId
(
"IdMappingDeleteRouter"
)
.
to
(
"sql:DELETE FROM uris WHERE public=:#id"
)
.
removeHeader
(
"id"
)
.
log
(
LoggingLevel
.
INFO
,
"Deleting ${headers["
+
ID
+
"]}"
)
.
to
(
"sql:DELETE FROM uris WHERE public=:#"
+
ID
)
.
removeHeader
(
ID
)
.
setHeader
(
Exchange
.
HTTP_RESPONSE_CODE
).
constant
(
204
);
}
...
...
acrepo-idiomatic/src/main/java/edu/amherst/acdc/idiomatic/Id
Processor
.java
→
acrepo-idiomatic/src/main/java/edu/amherst/acdc/idiomatic/Id
iomaticHeaders
.java
View file @
2736421a
/**
* Copyright 2015 DuraSpace, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
...
...
@@ -15,35 +13,18 @@
*/
package
edu.amherst.acdc.idiomatic
;
import
static
org
.
fcrepo
.
camel
.
JmsHeaders
.
IDENTIFIER
;
import
java.util.Arrays
;
import
java.util.List
;
import
org.apache.camel.Exchange
;
import
org.apache.camel.Message
;
import
org.apache.camel.Processor
;
/**
* @author Aaron Coburn
* Common Headers for this set of routes
*
* @author acoburn
*/
public
final
class
IdiomaticHeaders
{
public
class
IdProcessor
implements
Processor
{
public
static
final
String
ID
=
"CamelIdiomaticId"
;
/**
* Define how a message should be processed.
*
* @param exchange the current camel message exchange */
public
void
process
(
final
Exchange
exchange
)
throws
Exception
{
final
Message
in
=
exchange
.
getIn
();
final
String
id
=
in
.
getBody
(
String
.
class
);
public
static
final
String
FEDORA
=
"CamelIdiomaticFedora"
;
// update exchange
final
List
<
String
>
data
=
Arrays
.
asList
(
in
.
getHeader
(
IDENTIFIER
,
String
.
class
),
id
);
if
(
data
.
size
()
==
2
)
{
in
.
setBody
(
data
);
}
else
{
in
.
setBody
(
null
);
}
private
IdiomaticHeaders
()
{
// prevent instantiation
}
}
acrepo-idiomatic/src/main/resources/OSGI-INF/blueprint/blueprint.xml
View file @
2736421a
...
...
@@ -17,6 +17,7 @@
<cm:property
name=
"rest.port"
value=
"9080"
/>
<cm:property
name=
"id.property"
value=
"dc:identifier"
/>
<cm:property
name=
"id.namespace"
value=
"http://purl.org/dc/elements/1.1/"
/>
<cm:property
name=
"id.prefix"
value=
""
/>
<cm:property
name=
"fcrepo.baseUrl"
value=
"localhost:8080/fcrepo/rest"
/>
</cm:default-properties>
</cm:property-placeholder>
...
...
@@ -38,7 +39,7 @@
<package>
edu.amherst.acdc.idiomatic
</package>
<restConfiguration
bindingMode=
"auto"
component=
"restlet"
port=
"{{rest.port}}"
/>
<restConfiguration
component=
"restlet"
port=
"{{rest.port}}"
/>
<route
id=
"MinterRoute"
>
<description>
Create a freshly minted ID
</description>
...
...
acrepo-idiomatic/src/test/java/edu/amherst/idiomatic/RouteTest.java
View file @
2736421a
...
...
@@ -13,6 +13,7 @@
*/
package
edu.amherst.acdc.idiomatic
;
import
static
edu
.
amherst
.
acdc
.
idiomatic
.
IdiomaticHeaders
.
ID
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
...
...
@@ -71,6 +72,7 @@ public class RouteTest extends CamelBlueprintTestSupport {
final
Properties
props
=
new
Properties
();
props
.
put
(
"input.stream"
,
"seda:foo"
);
props
.
put
(
"rest.port"
,
"9999"
);
props
.
put
(
"id.prefix"
,
"http://example.org/object/"
);
return
props
;
}
...
...
@@ -125,6 +127,7 @@ public class RouteTest extends CamelBlueprintTestSupport {
@Override
public
void
configure
()
throws
Exception
{
mockEndpointsAndSkip
(
"fcrepo*"
);
mockEndpoints
(
"direct:update"
);
}
});
...
...
@@ -140,6 +143,8 @@ public class RouteTest extends CamelBlueprintTestSupport {
context
.
start
();
resultEndpoint
.
expectedMessageCount
(
2
);
getMockEndpoint
(
"mock:direct:update"
).
expectedBodiesReceived
(
"/foo/bar"
,
"/foo/bar"
);
getMockEndpoint
(
"mock:direct:update"
).
expectedHeaderValuesReceivedInAnyOrder
(
ID
,
"1"
,
"2"
);
final
Map
<
String
,
Object
>
headers
=
new
HashMap
<>();
headers
.
put
(
JmsHeaders
.
IDENTIFIER
,
"/foo/bar"
);
template
.
sendBodyAndHeaders
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment