001/* 002 * Copyright 2010 Anyware Services 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 */ 016 017package org.ametys.cms.transformation.docbook; 018 019import java.io.InputStream; 020import java.util.ArrayList; 021import java.util.List; 022 023import javax.xml.transform.dom.DOMResult; 024import javax.xml.transform.sax.TransformerHandler; 025 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.avalon.framework.service.Serviceable; 029import org.apache.excalibur.source.Source; 030import org.apache.excalibur.source.SourceResolver; 031import org.apache.excalibur.xml.sax.SAXParser; 032import org.apache.excalibur.xml.xpath.XPathProcessor; 033import org.apache.excalibur.xml.xslt.XSLTProcessor; 034import org.w3c.dom.Element; 035import org.w3c.dom.Node; 036import org.w3c.dom.NodeList; 037import org.xml.sax.InputSource; 038 039import org.ametys.cms.content.references.OutgoingReferences; 040import org.ametys.cms.content.references.RichTextOutgoingReferencesExtractor; 041import org.ametys.cms.data.RichText; 042 043/** 044 * This impl extract outgoing references on docbook rich texts 045 */ 046public class DocbookOutgoingReferencesExtractor implements RichTextOutgoingReferencesExtractor, Serviceable 047{ 048 /** Avalon Role */ 049 public static final String ROLE = DocbookOutgoingReferencesExtractor.class.getName(); 050 051 /** Avalon service manager */ 052 protected ServiceManager _manager; 053 054 private SourceResolver _sourceResolver; 055 private XSLTProcessor _xsltProcessor; 056 private XPathProcessor _xpathProcessor; 057 058 public void service(ServiceManager manager) throws ServiceException 059 { 060 _manager = manager; 061 _xsltProcessor = (XSLTProcessor) manager.lookup(XSLTProcessor.ROLE + "/xalan"); 062 _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); 063 _xpathProcessor = (XPathProcessor) manager.lookup(XPathProcessor.ROLE); 064 } 065 066 /** 067 * The uri to use for conversion to outgoing references format 068 * @return The uri 069 */ 070 protected String _getXSLTURI() 071 { 072 return "docbookenhancement://docbook2outgoingreferences.xsl"; 073 } 074 075 /** 076 * Take the metadata stream and transform it using the xslt configured (_getXSLTURI) 077 * @param metadata The metadata to transform 078 * @return The root node of the result XML after the transformation 079 */ 080 protected Node _getNodeAfterXSLT(RichText metadata) 081 { 082 DOMResult result = null; 083 Source xsltSource = null; 084 SAXParser saxParser = null; 085 086 try 087 { 088 xsltSource = _sourceResolver.resolveURI(_getXSLTURI()); 089 TransformerHandler th = _xsltProcessor.getTransformerHandler(xsltSource); 090 091 result = new DOMResult(); 092 th.setResult(result); 093 094 saxParser = (SAXParser) _manager.lookup(SAXParser.ROLE); 095 096 try (InputStream is = metadata.getInputStream()) 097 { 098 saxParser.parse(new InputSource(is), th); 099 } 100 } 101 catch (Exception e) 102 { 103 throw new RuntimeException("Cannot find the xslt to extract rich text outgoing references", e); 104 } 105 finally 106 { 107 _sourceResolver.release(xsltSource); 108 _manager.release(saxParser); 109 } 110 111 return result.getNode(); 112 } 113 114 @Override 115 public OutgoingReferences getOutgoingReferences(RichText richText) 116 { 117 OutgoingReferences references = new OutgoingReferences(); 118 119 Node resultNode = _getNodeAfterXSLT(richText); 120 NodeList referenceNodes = _xpathProcessor.selectNodeList(resultNode, "/references/reference"); 121 122 for (int i = 0; i < referenceNodes.getLength(); i++) 123 { 124 Element referenceNode = (Element) referenceNodes.item(i); 125 String type = referenceNode.getAttribute("type"); 126 String value = referenceNode.getTextContent(); 127 128 List<String> referenceValues = references.get(type); 129 if (referenceValues == null) 130 { 131 referenceValues = new ArrayList<>(); 132 references.put(type, referenceValues); 133 } 134 referenceValues.add(value); 135 } 136 137 return references; 138 } 139}