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.Repeater;
020: import org.apache.cocoon.forms.formmodel.Field;
021: import org.apache.cocoon.forms.validation.ValidationErrorAware;
022: import org.apache.cocoon.forms.validation.ValidationError;
023: import org.apache.avalon.framework.service.ServiceManager;
024: import org.apache.avalon.framework.context.Context;
025: import org.apache.xmlbeans.XmlObject;
026: import org.apache.xmlbeans.XmlCursor;
027: import org.apache.xmlbeans.XmlOptions;
028: import org.outerj.daisy.repository.schema.PartTypeUse;
029: import org.outerj.daisy.repository.Document;
030: import org.outerj.daisy.repository.Part;
031: import org.outerj.daisy.repository.Repository;
032: import org.outerj.daisy.frontend.util.FormHelper;
033: import org.outerj.daisy.books.publisher.impl.util.XMLPropertiesHelper;
034: import org.xml.sax.InputSource;
035:
036: import java.io.ByteArrayInputStream;
037: import java.io.StringReader;
038: import java.util.Map;
039: import java.util.Iterator;
040:
041: /**
042: * Part editor for the book metadata.
043: */
044: public class BookMetadataPartEditor implements PartEditor {
045: private final ServiceManager serviceManager;
046:
047: private BookMetadataPartEditor(ServiceManager serviceManager) {
048: this .serviceManager = serviceManager;
049: }
050:
051: public static class Factory implements PartEditorFactory {
052: public PartEditor getPartEditor(Map properties,
053: ServiceManager serviceManager, Context context) {
054: return new BookMetadataPartEditor(serviceManager);
055: }
056: }
057:
058: public Form getForm(PartTypeUse partTypeUse,
059: DocumentEditorForm documentEditorForm, Repository repository)
060: throws Exception {
061: final Form form = FormHelper.createForm(serviceManager,
062: "resources/form/parteditor_bookmeta_definition.xml");
063:
064: Field editMode = (Field) form.getChild("editmode");
065: editMode.setValue("gui");
066: editMode.addValueChangedListener(new EditModeListener(
067: new EditModeListener.EditModeListenerConfig() {
068: public String getXmlFieldPath() {
069: return "editors/xml/metadataXml";
070: }
071:
072: public String getXmlFromGuiEditor() {
073: return getMetadataXml((Repeater) form
074: .lookupWidget("editors/gui/metadata"));
075: }
076:
077: public boolean loadGui(String xml) {
078: Map metadata;
079: try {
080: metadata = XMLPropertiesHelper.load(
081: new InputSource(new StringReader(
082: xml)), null, "metadata");
083: } catch (Exception e) {
084: // TODO nicer error message?
085: ((ValidationErrorAware) form
086: .lookupWidget(getXmlFieldPath()))
087: .setValidationError(new ValidationError(
088: e.toString(), false));
089: return false;
090: }
091: Repeater repeater = (Repeater) form
092: .lookupWidget("editors/gui/metadata");
093: repeater.clear();
094: loadRepeater(repeater, metadata);
095: return true;
096: }
097:
098: public void clearGui() {
099: Repeater repeater = (Repeater) form
100: .lookupWidget("editors/gui/metadata");
101: repeater.clear();
102: }
103: }));
104:
105: // set some defaults
106: Repeater repeater = (Repeater) form
107: .lookupWidget("editors/gui/metadata");
108: Repeater.RepeaterRow row = repeater.addRow();
109: row.getChild("name").setValue("title");
110: row.getChild("value").setValue("enter book title here");
111: row = repeater.addRow();
112: row.getChild("name").setValue("locale");
113: row.getChild("value").setValue("en");
114:
115: return form;
116: }
117:
118: public String getFormTemplate() {
119: return "resources/form/parteditor_bookmeta_template.xml";
120: }
121:
122: public void load(Form form, Document document, Part part,
123: Repository repository) throws Exception {
124: Repeater repeater = (Repeater) form
125: .lookupWidget("editors/gui/metadata");
126: repeater.clear();
127:
128: byte[] data = part.getData();
129:
130: Map metadata = null;
131: try {
132: metadata = XMLPropertiesHelper.load(
133: new ByteArrayInputStream(data), "metadata");
134: } catch (Throwable e) {
135: // ignore
136: }
137:
138: if (metadata != null) {
139: loadRepeater(repeater, metadata);
140: } else {
141: // parsing failed
142: form.setAttribute("ignore-editmode-change", Boolean.TRUE);
143: form.getChild("editmode").setValue("xml");
144: // TODO might want to do smarter encoding detection
145: form.lookupWidget("editors/xml/metadataXml").setValue(
146: new String(data, "UTF-8"));
147: }
148: }
149:
150: public void save(Form form, Document document) throws Exception {
151: Field editMode = (Field) form.getChild("editmode");
152: if (editMode.getValue().equals("xml")) {
153: PartEditorHelper.save(form, document,
154: "editors/xml/metadataXml", "text/xml");
155: } else if (editMode.getValue().equals("gui")) {
156: Repeater repeater = (Repeater) form
157: .lookupWidget("editors/gui/metadata");
158: String xml = getMetadataXml(repeater);
159: PartEditorHelper.save(form, document, null, xml
160: .getBytes("UTF-8"), "text/xml");
161: }
162: }
163:
164: private static String getMetadataXml(Repeater repeater) {
165: XmlObject xml = XmlObject.Factory.newInstance();
166: XmlCursor cursor = xml.newCursor();
167: cursor.toNextToken();
168: cursor.beginElement("metadata");
169:
170: for (int i = 0; i < repeater.getSize(); i++) {
171: Repeater.RepeaterRow row = repeater.getRow(i);
172: String name = (String) row.getChild("name").getValue();
173: if (name == null)
174: name = "";
175: String value = (String) row.getChild("value").getValue();
176: if (value == null)
177: value = "";
178: cursor.beginElement("entry");
179: cursor.insertAttributeWithValue("key", name);
180: cursor.insertChars(value);
181: cursor.toEndToken();
182: cursor.toNextToken();
183: }
184: cursor.dispose();
185:
186: XmlOptions xmlOptions = new XmlOptions();
187: xmlOptions.setSavePrettyPrint();
188: xmlOptions.setCharacterEncoding("UTF-8");
189: return xml.xmlText(xmlOptions);
190: }
191:
192: private static void loadRepeater(Repeater repeater, Map metadata) {
193: Iterator metadataIt = metadata.entrySet().iterator();
194: while (metadataIt.hasNext()) {
195: Map.Entry entry = (Map.Entry) metadataIt.next();
196: Repeater.RepeaterRow row = repeater.addRow();
197: row.getChild("name").setValue(entry.getKey());
198: row.getChild("value").setValue(entry.getValue());
199: }
200: }
201: }
|