001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
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 org.outerj.daisy.frontend.editor;
017:
018: import org.apache.cocoon.forms.formmodel.Form;
019: import org.apache.cocoon.forms.formmodel.Field;
020: import org.apache.avalon.framework.service.ServiceManager;
021: import org.apache.avalon.framework.context.Context;
022: import org.apache.xmlbeans.XmlOptions;
023: import org.outerj.daisy.repository.schema.PartTypeUse;
024: import org.outerj.daisy.repository.Part;
025: import org.outerj.daisy.repository.Document;
026: import org.outerj.daisy.repository.Repository;
027: import org.outerj.daisy.frontend.util.FormHelper;
028: import org.outerj.daisy.publisher.Publisher;
029: import org.outerj.daisy.xmlutil.LocalSAXParserFactory;
030: import org.outerx.daisy.x10Bookdef.BookDocument;
031: import org.outerx.daisy.x10Bookdef.SectionDocument;
032: import org.outerx.daisy.x10Publisher.PublisherRequestDocument;
033: import org.outerx.daisy.x10Publisher.ResolveDocumentIdsDocument;
034: import org.xml.sax.helpers.DefaultHandler;
035: import org.xml.sax.Attributes;
036: import org.xml.sax.SAXException;
037:
038: import java.io.ByteArrayInputStream;
039: import java.io.StringReader;
040: import java.io.ByteArrayOutputStream;
041: import java.util.List;
042: import java.util.ArrayList;
043: import java.util.Map;
044:
045: public class BookPartEditor implements PartEditor {
046: private ServiceManager serviceManager;
047:
048: private BookPartEditor(ServiceManager serviceManager) {
049: this .serviceManager = serviceManager;
050: }
051:
052: public static class Factory implements PartEditorFactory {
053: public PartEditor getPartEditor(Map properties,
054: ServiceManager serviceManager, Context context) {
055: return new BookPartEditor(serviceManager);
056: }
057: }
058:
059: public Form getForm(PartTypeUse partTypeUse,
060: DocumentEditorForm documentEditorForm, Repository repository)
061: throws Exception {
062: Form form = FormHelper.createForm(serviceManager,
063: "resources/form/parteditor_book_definition.xml");
064: form.getChild("book").addValidator(
065: new PartRequiredValidator(documentEditorForm,
066: partTypeUse.isRequired(), false));
067: return form;
068: }
069:
070: public String getFormTemplate() {
071: return "resources/form/parteditor_book_template.xml";
072: }
073:
074: public void load(Form form, Document document, Part part,
075: Repository repository) throws Exception {
076: // annotate book tree XML with document names
077: byte[] data = part.getData();
078: String result = annotateWithDocumentTitles(data, document,
079: repository);
080: Field field = (Field) form.getChild("book");
081: if (result != null) {
082: field.setValue(result);
083: } else {
084: field.setValue(new String(data, "UTF-8"));
085: }
086: }
087:
088: public void save(Form form, Document document) throws Exception {
089: Field field = (Field) form.getChild("book");
090: String value = (String) field.getValue();
091: byte[] data = null;
092: if (value != null) {
093: // remove (auto-added) titles again from section nodes which have an ID
094: try {
095: XmlOptions xmlOptions = new XmlOptions()
096: .setLoadUseXMLReader(LocalSAXParserFactory
097: .newXmlReader());
098: BookDocument bookDocument = BookDocument.Factory.parse(
099: new StringReader(value), xmlOptions);
100: removeTitles(bookDocument.getBook().getContent()
101: .getSectionList());
102: ByteArrayOutputStream os = new ByteArrayOutputStream(
103: value.length() + 300);
104: bookDocument.save(os);
105: data = os.toByteArray();
106: } catch (Throwable e) {
107: // don't fail on this
108: }
109: }
110: PartEditorHelper.save(form, document, "book", data, "text/xml");
111: }
112:
113: private String annotateWithDocumentTitles(byte[] data,
114: Document document, Repository repository) {
115: try {
116: XmlOptions xmlOptions = new XmlOptions()
117: .setLoadUseXMLReader(LocalSAXParserFactory
118: .newXmlReader());
119: BookDocument bookDocument = BookDocument.Factory.parse(
120: new ByteArrayInputStream(data), xmlOptions);
121: PublisherRequestDocument publisherRequestDocument = PublisherRequestDocument.Factory
122: .newInstance();
123: PublisherRequestDocument.PublisherRequest publisherRequest = publisherRequestDocument
124: .addNewPublisherRequest();
125: ResolveDocumentIdsDocument.ResolveDocumentIds resolveDocIds = publisherRequest
126: .addNewResolveDocumentIds();
127: resolveDocIds.setBranch(String.valueOf(document
128: .getBranchId()));
129: resolveDocIds.setLanguage(String.valueOf(document
130: .getLanguageId()));
131:
132: List<SectionDocument.Section> sections = bookDocument
133: .getBook().getContent().getSectionList();
134: buildRequest(sections, resolveDocIds);
135: Publisher publisher = (Publisher) repository
136: .getExtension("Publisher");
137: ResolvedIdCollector collector = new ResolvedIdCollector();
138: publisher.processRequest(publisherRequestDocument,
139: collector);
140: annotateSections(sections, collector.getNames(), -1);
141:
142: return bookDocument.xmlText();
143: } catch (Throwable e) {
144: // resolving IDs failed, don't care
145: return null;
146: }
147: }
148:
149: private void buildRequest(List<SectionDocument.Section> sections,
150: ResolveDocumentIdsDocument.ResolveDocumentIds resolveDocIds) {
151: for (SectionDocument.Section section : sections) {
152: if (section.isSetDocumentId()) {
153: ResolveDocumentIdsDocument.ResolveDocumentIds.Document document = resolveDocIds
154: .addNewDocument();
155: document.setId(section.getDocumentId());
156: if (section.isSetBranch())
157: document.setBranch(section.getBranch());
158: if (section.isSetLanguage())
159: document.setLanguage(section.getLanguage());
160: if (section.isSetVersion())
161: document.setVersion(section.getVersion());
162: }
163: buildRequest(section.getSectionList(), resolveDocIds);
164: }
165: }
166:
167: private int annotateSections(
168: List<SectionDocument.Section> sections, List names, int pos) {
169: for (SectionDocument.Section section : sections) {
170: if (section.isSetDocumentId()) {
171: pos++;
172: section.setTitle((String) names.get(pos));
173: }
174: pos = annotateSections(section.getSectionList(), names, pos);
175: }
176: return pos;
177: }
178:
179: static class ResolvedIdCollector extends DefaultHandler {
180: private List<String> documentNames = new ArrayList<String>(50);
181:
182: public List<String> getNames() {
183: return documentNames;
184: }
185:
186: public void startElement(String uri, String localName,
187: String qName, Attributes attributes)
188: throws SAXException {
189: if (uri.equals("http://outerx.org/daisy/1.0#publisher")
190: && localName.equals("document")) {
191: documentNames.add(attributes.getValue("name"));
192: }
193: }
194: }
195:
196: private void removeTitles(List<SectionDocument.Section> sections) {
197: for (SectionDocument.Section section : sections) {
198: if (section.isSetDocumentId() && section.isSetTitle()) {
199: section.unsetTitle();
200: }
201: removeTitles(section.getSectionList());
202: }
203: }
204:
205: }
|