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