001/* 002 * Copyright 2016 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 private static final String RESOURCE_DELETION = "http://fedora.info/definitions/v4/event#ResourceDeletion"; 046 047 /** 048 * Configure the message route workflow. 049 */ 050 public void configure() throws Exception { 051 052 final Namespaces ns = new Namespaces("rdf", RDF); 053 ns.add("indexing", INDEXING); 054 055 final XPathBuilder indexable = new XPathBuilder( 056 String.format("/rdf:RDF/rdf:Description/rdf:type[@rdf:resource='%s']", INDEXING + "Indexable")); 057 indexable.namespaces(ns); 058 059 /** 060 * A generic error handler (specific to this RouteBuilder) 061 */ 062 onException(Exception.class) 063 .maximumRedeliveries("{{error.maxRedeliveries}}") 064 .log("Index Routing Error: ${routeId}"); 065 066 /** 067 * route a message to the proper queue, based on whether 068 * it is a DELETE or UPDATE operation. 069 */ 070 from("{{input.stream}}") 071 .routeId("FcrepoTriplestoreRouter") 072 .choice() 073 // this clause supports Fedora 4.5.1 and earlier but may be removed in a future release 074 .when(header(EVENT_TYPE).isEqualTo(REPOSITORY + "NODE_REMOVED")) 075 .to("direct:delete.triplestore") 076 .when(header(EVENT_TYPE).isEqualTo(RESOURCE_DELETION)) 077 .to("direct:delete.triplestore") 078 .otherwise() 079 .to("direct:index.triplestore"); 080 081 /** 082 * Handle re-index events 083 */ 084 from("{{triplestore.reindex.stream}}") 085 .routeId("FcrepoTriplestoreReindex") 086 .to("direct:index.triplestore"); 087 088 /** 089 * Based on an item's metadata, determine if it is indexable. 090 */ 091 from("direct:index.triplestore") 092 .routeId("FcrepoTriplestoreIndexer") 093 .filter(not(or(header(IDENTIFIER).startsWith(simple("{{audit.container}}/")), 094 header(IDENTIFIER).isEqualTo(simple("{{audit.container}}"))))) 095 .removeHeaders("CamelHttp*") 096 .to("fcrepo:{{fcrepo.baseUrl}}?preferInclude=PreferMinimalContainer&accept=application/rdf+xml") 097 .choice() 098 .when(or(simple("{{indexing.predicate}} != 'true'"), indexable)) 099 .to("direct:update.triplestore") 100 .otherwise() 101 .to("direct:delete.triplestore"); 102 103 /** 104 * Remove an item from the triplestore index. 105 */ 106 from("direct:delete.triplestore") 107 .routeId("FcrepoTriplestoreDeleter") 108 .process(new SparqlDeleteProcessor()) 109 .log(LoggingLevel.INFO, logger, 110 "Deleting Triplestore Object ${headers[CamelFcrepoIdentifier]} " + 111 "${headers[org.fcrepo.jms.identifier]}") 112 .to("{{triplestore.baseUrl}}?useSystemProperties=true"); 113 114 /** 115 * Perform the sparql update. 116 */ 117 from("direct:update.triplestore") 118 .routeId("FcrepoTriplestoreUpdater") 119 .setHeader(FCREPO_NAMED_GRAPH) 120 .simple("{{triplestore.namedGraph}}") 121 .to("fcrepo:{{fcrepo.baseUrl}}?accept=application/n-triples" + 122 "&preferOmit={{prefer.omit}}&preferInclude={{prefer.include}}") 123 .process(new SparqlUpdateProcessor()) 124 .log(LoggingLevel.INFO, logger, 125 "Indexing Triplestore Object ${headers[CamelFcrepoIdentifier]} " + 126 "${headers[org.fcrepo.jms.identifier]}") 127 .to("{{triplestore.baseUrl}}?useSystemProperties=true"); 128 } 129}