001/** 002 * Copyright 2015 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.camel.indexing.triplestore; 017 018import static org.apache.camel.builder.PredicateBuilder.not; 019import static org.apache.camel.builder.PredicateBuilder.or; 020import static org.fcrepo.camel.FcrepoHeaders.FCREPO_NAMED_GRAPH; 021import static org.fcrepo.camel.JmsHeaders.EVENT_TYPE; 022import static org.fcrepo.camel.JmsHeaders.IDENTIFIER; 023import static org.fcrepo.camel.RdfNamespaces.INDEXING; 024import static org.fcrepo.camel.RdfNamespaces.RDF; 025import static org.fcrepo.camel.RdfNamespaces.REPOSITORY; 026import static org.slf4j.LoggerFactory.getLogger; 027 028import org.apache.camel.LoggingLevel; 029import org.apache.camel.builder.RouteBuilder; 030import org.apache.camel.builder.xml.Namespaces; 031import org.apache.camel.builder.xml.XPathBuilder; 032import org.fcrepo.camel.processor.SparqlDeleteProcessor; 033import org.fcrepo.camel.processor.SparqlUpdateProcessor; 034import org.slf4j.Logger; 035 036/** 037 * A content router for handling JMS events. 038 * 039 * @author Aaron Coburn 040 */ 041public class TriplestoreRouter extends RouteBuilder { 042 043 private static final Logger logger = getLogger(TriplestoreRouter.class); 044 045 /** 046 * Configure the message route workflow. 047 */ 048 public void configure() throws Exception { 049 050 final Namespaces ns = new Namespaces("rdf", RDF); 051 ns.add("indexing", INDEXING); 052 053 final XPathBuilder indexable = new XPathBuilder( 054 String.format("/rdf:RDF/rdf:Description/rdf:type[@rdf:resource='%s']", INDEXING + "Indexable")); 055 indexable.namespaces(ns); 056 057 /** 058 * A generic error handler (specific to this RouteBuilder) 059 */ 060 onException(Exception.class) 061 .maximumRedeliveries("{{error.maxRedeliveries}}") 062 .log("Index Routing Error: ${routeId}"); 063 064 /** 065 * route a message to the proper queue, based on whether 066 * it is a DELETE or UPDATE operation. 067 */ 068 from("{{input.stream}}") 069 .routeId("FcrepoTriplestoreRouter") 070 .choice() 071 .when(header(EVENT_TYPE).isEqualTo(REPOSITORY + "NODE_REMOVED")) 072 .to("direct:delete.triplestore") 073 .otherwise() 074 .to("direct:index.triplestore"); 075 076 /** 077 * Handle re-index events 078 */ 079 from("{{triplestore.reindex.stream}}") 080 .routeId("FcrepoTriplestoreReindex") 081 .to("direct:index.triplestore"); 082 083 /** 084 * Based on an item's metadata, determine if it is indexable. 085 */ 086 from("direct:index.triplestore") 087 .routeId("FcrepoTriplestoreIndexer") 088 .filter(not(or(header(IDENTIFIER).startsWith(simple("{{audit.container}}/")), 089 header(IDENTIFIER).isEqualTo(simple("{{audit.container}}"))))) 090 .removeHeaders("CamelHttp*") 091 .to("fcrepo:{{fcrepo.baseUrl}}?preferInclude=PreferMinimalContainer&accept=application/rdf+xml") 092 .choice() 093 .when(or(simple("{{indexing.predicate}} != 'true'"), indexable)) 094 .to("direct:update.triplestore") 095 .otherwise() 096 .to("direct:delete.triplestore"); 097 098 /** 099 * Remove an item from the triplestore index. 100 */ 101 from("direct:delete.triplestore") 102 .routeId("FcrepoTriplestoreDeleter") 103 .process(new SparqlDeleteProcessor()) 104 .log(LoggingLevel.INFO, logger, 105 "Deleting Triplestore Object ${headers[CamelFcrepoIdentifier]} " + 106 "${headers[org.fcrepo.jms.identifier]}") 107 .to("http4://{{triplestore.baseUrl}}"); 108 109 /** 110 * Perform the sparql update. 111 */ 112 from("direct:update.triplestore") 113 .routeId("FcrepoTriplestoreUpdater") 114 .setHeader(FCREPO_NAMED_GRAPH) 115 .simple("{{triplestore.namedGraph}}") 116 .to("fcrepo:{{fcrepo.baseUrl}}?accept=application/n-triples" + 117 "&preferOmit={{prefer.omit}}&preferInclude={{prefer.include}}") 118 .process(new SparqlUpdateProcessor()) 119 .log(LoggingLevel.INFO, logger, 120 "Indexing Triplestore Object ${headers[CamelFcrepoIdentifier]} " + 121 "${headers[org.fcrepo.jms.identifier]}") 122 .to("http4://{{triplestore.baseUrl}}"); 123 } 124}