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 */
016package org.ametys.cms.transformation;
017
018import org.apache.avalon.framework.logger.AbstractLogEnabled;
019import org.apache.cocoon.xml.AttributesImpl;
020import org.apache.cocoon.xml.XMLUtils;
021import org.xml.sax.Attributes;
022import org.xml.sax.ContentHandler;
023import org.xml.sax.Locator;
024import org.xml.sax.SAXException;
025import org.xml.sax.ext.LexicalHandler;
026
027import org.ametys.runtime.i18n.I18nizableText;
028
029/**
030 * This interface is for component that wants to be in the docbook pipeline.
031 * As a pipeline you receive events (from the ContentHandler and LexicalHandler interfaces) 
032 * you may transform it and write it to the given contentHandler (setContentHandler) and 
033 * given lexicalHandler (setLexicalHandler) 
034 */
035public abstract class AbstractEnhancementHandler extends AbstractLogEnabled implements ContentHandler, LexicalHandler
036{
037    /** Processing instruction for unmodifiable content */
038    public static final String PROCESSING_INSTRUCTION_UNMODIFIABLE = "ametys-unmodifiable";
039    
040    /** The content handler where to write */
041    protected ContentHandler _contentHandler;
042    /** The lexical handler where to write */
043    protected LexicalHandler _lexicalHandler;
044    
045    /** 
046     * True if the current HTML should not be modified
047     * Use to prevent to apply transformation on sax events (eg: HTML expert)
048     */
049    protected boolean _inUnmodifiableContent;
050    
051    /**
052     * Set the target content handler
053     * @param contentHandler the target content handler
054     */
055    public void setContentHandler(ContentHandler contentHandler)
056    {
057        _contentHandler = contentHandler;
058    }
059    
060    /**
061     * Set the target lexical handler
062     * @param lexicalHandler the target lexical handler
063     */
064    public void setLexicalHandler(LexicalHandler lexicalHandler)
065    {
066        _lexicalHandler = lexicalHandler;
067    }
068    
069    /**
070     * SAX an error message in content.
071     * @param title the error title. Can be null.
072     * @param message the error message. Can be null.
073     * @param absoluteIconPath the absolute path of the icon. Can be null.
074     * @throws SAXException if an error occurred while SAXing
075     */
076    protected void saxError (I18nizableText title, I18nizableText message, String absoluteIconPath) throws SAXException
077    {
078        AttributesImpl atts = new AttributesImpl();
079        
080        atts.addCDATAAttribute("class", "ametys-cms-content-inline-error");
081        XMLUtils.startElement(_contentHandler, "div", atts);
082        
083        if (absoluteIconPath != null)
084        {
085            atts = new AttributesImpl();
086            atts.addCDATAAttribute("src", absoluteIconPath);
087            XMLUtils.createElement(_contentHandler, "img", atts);
088        }
089        
090        if (title != null)
091        {
092            XMLUtils.startElement(_contentHandler, "strong");
093            title.toSAX(_contentHandler);
094            XMLUtils.endElement(_contentHandler, "strong");
095            XMLUtils.createElement(_contentHandler, "br");
096        }
097        
098        if (message != null)
099        {
100            message.toSAX(_contentHandler);
101        }
102        
103        XMLUtils.endElement(_contentHandler, "div");
104    }
105    
106    @Override
107    public void startDocument() throws SAXException
108    {
109        _contentHandler.startDocument();
110    }
111    @Override
112    public void endDocument() throws SAXException
113    {
114        _contentHandler.endDocument();
115    }
116
117    @Override
118    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException
119    {
120        _contentHandler.startElement(uri, localName, qName, atts);
121    }
122    @Override
123    public void endElement(String uri, String localName, String qName) throws SAXException
124    {
125        _contentHandler.endElement(uri, localName, qName);
126    }
127    
128    @Override
129    public void characters(char[] ch, int start, int length) throws SAXException
130    {
131        _contentHandler.characters(ch, start, length);
132    }
133    @Override
134    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
135    {
136        _contentHandler.ignorableWhitespace(ch, start, length);
137    }
138    
139    @Override
140    public void processingInstruction(String target, String data) throws SAXException
141    {
142        if (PROCESSING_INSTRUCTION_UNMODIFIABLE.equals(target))
143        {
144            if ("start".equals(data))
145            {
146                // Following characters or elements should not be transformed or modified by other content or lexical handlers
147                _inUnmodifiableContent = true;
148            }
149            else
150            {
151                // Following characters or elements could be transformed or modified  by other content or lexical handlers
152                _inUnmodifiableContent = false;
153            }
154        }
155        
156        _contentHandler.processingInstruction(target, data);
157    }
158    
159    @Override
160    public void setDocumentLocator(Locator locator)
161    {
162        _contentHandler.setDocumentLocator(locator);
163    }
164    @Override
165    public void skippedEntity(String name) throws SAXException
166    {
167        _contentHandler.skippedEntity(name);
168    }
169    
170    @Override
171    public void startPrefixMapping(String prefix, String uri) throws SAXException
172    {
173        _contentHandler.startPrefixMapping(prefix, uri);
174    }
175    @Override
176    public void endPrefixMapping(String prefix) throws SAXException
177    {
178        _contentHandler.endPrefixMapping(prefix);
179    }
180    
181    @Override
182    public void startEntity(String name) throws SAXException
183    {
184        _lexicalHandler.startEntity(name);
185    }
186    @Override
187    public void endEntity(String name) throws SAXException
188    {
189        _lexicalHandler.endEntity(name);
190    }
191
192    @Override
193    public void startCDATA() throws SAXException
194    {
195        _lexicalHandler.startCDATA();
196    }
197    @Override
198    public void endCDATA() throws SAXException
199    {
200        _lexicalHandler.endCDATA();
201    }
202
203    @Override
204    public void startDTD(String name, String publicId, String systemId) throws SAXException
205    {
206        _lexicalHandler.startDTD(name, publicId, systemId);
207    }
208    
209    @Override
210    public void endDTD() throws SAXException
211    {
212        _lexicalHandler.endCDATA();
213    }
214
215    @Override
216    public void comment(char[] ch, int start, int length) throws SAXException
217    {
218        _lexicalHandler.comment(ch, start, length);
219    }
220}