/* * #! * Ontopia Navigator * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ package net.ontopia.topicmaps.nav2.servlets; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.CharArrayReader; import java.io.CharArrayWriter; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.HashSet; import java.util.List; import java.util.ArrayList; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import net.ontopia.utils.StreamUtils; import net.ontopia.utils.StringUtils; import net.ontopia.utils.DeciderIF; import net.ontopia.utils.ObjectUtils; import net.ontopia.utils.ContainmentDecider; import net.ontopia.topicmaps.core.TopicMapStoreIF; import net.ontopia.topicmaps.core.TopicMapIF; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.core.OccurrenceIF; import net.ontopia.topicmaps.entry.TopicMaps; import net.ontopia.topicmaps.query.core.QueryProcessorIF; import net.ontopia.topicmaps.query.core.QueryResultIF; import net.ontopia.topicmaps.query.utils.QueryUtils; import net.ontopia.topicmaps.impl.basic.InMemoryTopicMapStore; import net.ontopia.topicmaps.utils.TopicStringifiers; import net.ontopia.topicmaps.utils.TopicMapSynchronizer; import net.ontopia.topicmaps.utils.IdentityUtils; import net.ontopia.topicmaps.xml.XTMTopicMapReader; import net.ontopia.infoset.core.LocatorIF; import net.ontopia.infoset.impl.basic.URILocator; import net.ontopia.topicmaps.query.core.QueryProcessorIF; import net.ontopia.topicmaps.query.core.QueryResultIF; import net.ontopia.topicmaps.query.utils.QueryUtils; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import org.w3c.dom.Document; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import java.io.File; import java.io.PrintWriter; import java.io.FileOutputStream; /** * INTERNAL: Experimental data integration servlet. */ public class DataIntegrationServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain; charset=utf-8"); // get topic map id String topicMapId = topicMapId = getInitParameter("topicMapId"); if (topicMapId == null) throw new ServletException("Topic map identifier is not specified."); // parse path String path = request.getPathInfo(); if (path == null) throw new ServletException("Path is missing."); path = path.substring(1); String[] args = StringUtils.split(path, "/"); String name = args[0]; String action = args[1]; // get topics query String topicsQuery = getInitParameter("topicsQuery"); if (topicsQuery == null) throw new ServletException("Parameter 'topicsQuery' is not specified."); // get characteristcs query String characteristicsQuery = getInitParameter("characteristicsQuery"); if (characteristicsQuery == null) throw new ServletException("Parameter 'characteristicsQuery' is not specified."); TopicMapStoreIF targetStore = TopicMaps.createStore(topicMapId, false); try { final TopicMapIF target = targetStore.getTopicMap(); // transform input document to topic map final TopicMapIF source = transformRequest(name, request.getInputStream(), targetStore.getBaseAddress()); // find topics to synchronize QueryProcessorIF qp = QueryUtils.getQueryProcessor(source); List candidates = new ArrayList(); QueryResultIF qr = qp.execute(topicsQuery); try { while (qr.next()) { // synchronize topic candidates.add(qr.getValue(0)); } } finally { qr.close(); } if (action.equals("updated") || action.equals("created")) { DeciderIF tfilter = new DeciderIF() { public boolean ok(Object o) { return true; } }; Iterator iter = candidates.iterator(); while (iter.hasNext()) { TopicIF src = (TopicIF)iter.next(); DeciderIF sfilter; if (characteristicsQuery == null) { // let everything through sfilter = tfilter; } else { // let the characteristics query decide what gets synchronized Collection characteristics = new HashSet(); QueryResultIF cqr = qp.execute(characteristicsQuery, Collections.singletonMap("topic", src)); try { while (cqr.next()) { // synchronize topic characteristics.add(cqr.getValue(0)); } } finally { cqr.close(); } sfilter = new ContainmentDecider(characteristics); } // synchronize topic TopicMapSynchronizer.update(target, src, tfilter, sfilter); } } else if (action.equals("deleted")) { Iterator iter = candidates.iterator(); while (iter.hasNext()) { TopicIF src = (TopicIF)iter.next(); Collection affectedTopics = IdentityUtils.findSameTopic(target, src); Iterator aiter = affectedTopics.iterator(); while (aiter.hasNext()) { TopicIF affectedTopic = (TopicIF)aiter.next(); affectedTopic.remove(); } } } else { throw new ServletException("Unsupported action: " + action); } targetStore.commit(); } catch (Exception e) { targetStore.abort(); throw new ServletException(e); } finally { targetStore.close(); } } public TopicMapIF transformRequest(String transformId, InputStream xmlstream, LocatorIF base) throws Exception { InputStream xsltstream = StreamUtils.getInputStream("classpath:" + transformId + ".xsl"); if (xsltstream == null) throw new ServletException("Could not find style sheet '" + transformId + ".xsl'"); // set up source and target streams // Source xmlSource = new StreamSource(xmlstream); Source xmlSource = new StreamSource(xmlstream); Source xsltSource = new StreamSource(xsltstream); // the factory pattern supports different XSLT processors TransformerFactory transFact = TransformerFactory.newInstance(); Transformer trans = transFact.newTransformer(xsltSource); CharArrayWriter cw = new CharArrayWriter(); trans.transform(xmlSource, new StreamResult(cw)); CharArrayReader cr = new CharArrayReader(cw.toCharArray()); TopicMapStoreIF store = new InMemoryTopicMapStore(); TopicMapIF topicmap = store.getTopicMap(); store.setBaseAddress(base); XTMTopicMapReader xr = new XTMTopicMapReader(cr, base); xr.setValidation(false); xr.importInto(topicmap); return topicmap; } }