001: /*
002: * Copyright 2001-2007 Hippo (www.hippo.nl)
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: package nl.hippo.cms.fileimport;
017:
018: import java.io.IOException;
019: import java.util.HashMap;
020: import java.util.Map;
021: import java.util.Stack;
022: import java.util.regex.Pattern;
023: import org.apache.avalon.framework.parameters.Parameters;
024: import org.apache.cocoon.ProcessingException;
025: import org.apache.cocoon.environment.SourceResolver;
026: import org.apache.cocoon.transformation.AbstractTransformer;
027:
028: import org.xml.sax.Attributes;
029: import org.xml.sax.SAXException;
030: import org.xml.sax.helpers.AttributesImpl;
031:
032: public class OooStyleCanonicalizingTransformer extends
033: AbstractTransformer {
034: private static final String OOO_STYLE_NAMESPACE_URI = "http://openoffice.org/2000/style";
035:
036: private static final String OOO_TEXT_NAMESPACE_URI = "http://openoffice.org/2000/text";
037:
038: private static final String FORMATTING_OBJECTS_NAMESPACE_URI = "http://www.w3.org/1999/XSL/Format";
039:
040: private static final String HIPPO_CMS_STYLE_NAMESPACE_URI = "http://hippo.nl/cms-style/1.0";
041:
042: private static final String STYLE_TAG_NAME = "style";
043:
044: private static final String NAME_ATTRIBUTE_NAME = "name";
045:
046: private static final String PARENT_STYLE_NAME_ATTRIBUTE_NAME = "parent-style-name";
047:
048: private static final String STYLE_NAME_ATTRIBUTE_NAME = "style-name";
049:
050: private static final String PROPERTIES_TAG_NAME = "properties";
051:
052: private static final String P_TAG_NAME = "p";
053:
054: private static final String SPAN_TAG_NAME = "span";
055:
056: private static final Pattern PARAGRAPH_STYLE_NAME_PATTERN = Pattern
057: .compile("^P[0-9]+$");
058:
059: private static final Pattern SPAN_STYLE_NAME_PATTERN = Pattern
060: .compile("^T[0-9]+$");
061:
062: private static final int BOLD_FLAG = 1;
063:
064: private static final int ITALIC_FLAG = 2;
065:
066: private static final int UNDERLINE_FLAG = 4;
067:
068: private Map m_paragraphStyleTranslations;
069:
070: private Map m_spanStyleTranslations;
071:
072: private Stack m_spanStack;
073:
074: private String m_spanStyleToStorePropertiesOf;
075:
076: public void startElement(String namespaceURI, String localName,
077: String qualifiedName, Attributes attributes)
078: throws SAXException {
079: boolean shouldInvokeSuperStartElement = true;
080:
081: if (namespaceURI.equals(OOO_STYLE_NAMESPACE_URI)) {
082: if (localName.equals(STYLE_TAG_NAME)) {
083: handleStyleDeclaration(attributes);
084: } else if (localName.equals(PROPERTIES_TAG_NAME)) {
085: handleStyleDeclarationProperties(attributes);
086: }
087: } else if (namespaceURI.equals(OOO_TEXT_NAMESPACE_URI)) {
088: if (localName.equals(P_TAG_NAME)) {
089: shouldInvokeSuperStartElement = false;
090: Attributes newAttributes = handleParagraph(attributes);
091: super .startElement(namespaceURI, localName,
092: qualifiedName, newAttributes);
093: } else if (localName.equals(SPAN_TAG_NAME)) {
094: shouldInvokeSuperStartElement = false;
095: String styleName = attributes.getValue(
096: OOO_TEXT_NAMESPACE_URI,
097: STYLE_NAME_ATTRIBUTE_NAME);
098: if (m_spanStyleTranslations.containsKey(styleName)) {
099: handleSpan(styleName);
100: } else {
101: m_spanStack.push(new Integer(0));
102: }
103: }
104: }
105:
106: if (shouldInvokeSuperStartElement) {
107: super .startElement(namespaceURI, localName, qualifiedName,
108: attributes);
109: }
110: }
111:
112: public void endElement(String namespaceURI, String localName,
113: String qualifiedName) throws SAXException {
114: boolean shouldInvokeSuperEndElement = true;
115:
116: if (namespaceURI.equals(OOO_TEXT_NAMESPACE_URI)) {
117: if (localName.equals(SPAN_TAG_NAME)) {
118: shouldInvokeSuperEndElement = false;
119: Integer style = (Integer) m_spanStack.pop();
120: if (style.intValue() != 0) {
121: if ((style.intValue() & UNDERLINE_FLAG) != 0) {
122: super .endElement(HIPPO_CMS_STYLE_NAMESPACE_URI,
123: "underline", "cms-style:underline");
124: }
125: if ((style.intValue() & ITALIC_FLAG) != 0) {
126: super .endElement(HIPPO_CMS_STYLE_NAMESPACE_URI,
127: "italic", "cms-style:italic");
128: }
129: if ((style.intValue() & BOLD_FLAG) != 0) {
130: super .endElement(HIPPO_CMS_STYLE_NAMESPACE_URI,
131: "bold", "cms-style:bold");
132: }
133: }
134: }
135: }
136:
137: if (shouldInvokeSuperEndElement) {
138: super .endElement(namespaceURI, localName, qualifiedName);
139: }
140: }
141:
142: private void handleStyleDeclaration(Attributes attributes) {
143: String name = attributes.getValue(OOO_STYLE_NAMESPACE_URI,
144: NAME_ATTRIBUTE_NAME);
145: if (PARAGRAPH_STYLE_NAME_PATTERN.matcher(name).matches()) {
146: String parentName = attributes.getValue(
147: OOO_STYLE_NAMESPACE_URI,
148: PARENT_STYLE_NAME_ATTRIBUTE_NAME);
149: m_paragraphStyleTranslations.put(name, parentName);
150: } else if (SPAN_STYLE_NAME_PATTERN.matcher(name).matches()) {
151: m_spanStyleToStorePropertiesOf = name;
152: }
153: }
154:
155: private void handleStyleDeclarationProperties(Attributes attributes) {
156: if (m_spanStyleToStorePropertiesOf != null) {
157: int m_style = 0;
158: m_style |= "bold".equals(attributes.getValue(
159: FORMATTING_OBJECTS_NAMESPACE_URI, "font-weight")) ? BOLD_FLAG
160: : 0;
161: m_style |= "italic".equals(attributes.getValue(
162: FORMATTING_OBJECTS_NAMESPACE_URI, "font-style")) ? ITALIC_FLAG
163: : 0;
164: m_style |= "single".equals(attributes.getValue(
165: OOO_STYLE_NAMESPACE_URI, "text-underline")) ? UNDERLINE_FLAG
166: : 0;
167: m_spanStyleTranslations.put(m_spanStyleToStorePropertiesOf,
168: new Integer(m_style));
169: m_spanStyleToStorePropertiesOf = null;
170: }
171: }
172:
173: private Attributes handleParagraph(Attributes attributes) {
174: Attributes result = attributes;
175: String styleName = attributes.getValue(OOO_TEXT_NAMESPACE_URI,
176: STYLE_NAME_ATTRIBUTE_NAME);
177: if (m_paragraphStyleTranslations.containsKey(styleName)) {
178: AttributesImpl newResult = new AttributesImpl(attributes);
179: int indexOfStyleNameAttribute = newResult.getIndex(
180: OOO_TEXT_NAMESPACE_URI, STYLE_NAME_ATTRIBUTE_NAME);
181: newResult.setValue(indexOfStyleNameAttribute,
182: (String) m_paragraphStyleTranslations
183: .get(styleName));
184: result = newResult;
185: }
186: return result;
187: }
188:
189: private void handleSpan(String styleName) throws SAXException {
190: Integer style = (Integer) m_spanStyleTranslations
191: .get(styleName);
192: m_spanStack.push(style);
193: if ((style.intValue() & BOLD_FLAG) != 0) {
194: super .startElement(HIPPO_CMS_STYLE_NAMESPACE_URI, "bold",
195: "cms-style:bold", new AttributesImpl());
196: }
197: if ((style.intValue() & ITALIC_FLAG) != 0) {
198: super .startElement(HIPPO_CMS_STYLE_NAMESPACE_URI, "italic",
199: "cms-style:italic", new AttributesImpl());
200: }
201: if ((style.intValue() & UNDERLINE_FLAG) != 0) {
202: super .startElement(HIPPO_CMS_STYLE_NAMESPACE_URI,
203: "underline", "cms-style:underline",
204: new AttributesImpl());
205: }
206: }
207:
208: public void setup(SourceResolver sourceResolver, Map objectModel,
209: String source, Parameters parameters)
210: throws ProcessingException, SAXException, IOException {
211: m_paragraphStyleTranslations = new HashMap();
212: m_spanStyleTranslations = new HashMap();
213: m_spanStack = new Stack();
214: m_spanStyleToStorePropertiesOf = null;
215: }
216: }
|