001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.lenya.cms.editors.forms;
019:
020: import java.io.IOException;
021: import java.util.HashSet;
022: import java.util.Set;
023:
024: import javax.xml.parsers.ParserConfigurationException;
025:
026: import org.apache.cocoon.components.ContextHelper;
027: import org.apache.cocoon.environment.Request;
028: import org.apache.lenya.cms.cocoon.source.SourceUtil;
029: import org.apache.lenya.cms.linking.LinkConverter;
030: import org.apache.lenya.cms.publication.ResourceType;
031: import org.apache.lenya.cms.usecase.DocumentUsecase;
032: import org.apache.lenya.cms.usecase.UsecaseException;
033: import org.apache.lenya.cms.usecase.xml.UsecaseErrorHandler;
034: import org.apache.lenya.cms.workflow.WorkflowUtil;
035: import org.apache.lenya.cms.workflow.usecases.UsecaseWorkflowHelper;
036: import org.apache.lenya.xml.DocumentHelper;
037: import org.apache.lenya.xml.Schema;
038: import org.apache.lenya.xml.ValidationUtil;
039: import org.w3c.dom.Document;
040: import org.xml.sax.SAXException;
041:
042: /**
043: * One form editor.
044: *
045: * @version $Id: OneFormEditor.java 603380 2007-12-11 22:10:28Z andreas $
046: */
047: public class OneFormEditor extends DocumentUsecase {
048:
049: /**
050: * @see org.apache.lenya.cms.usecase.AbstractUsecase#getNodesToLock()
051: */
052: protected org.apache.lenya.cms.repository.Node[] getNodesToLock()
053: throws UsecaseException {
054: org.apache.lenya.cms.publication.Document doc = getSourceDocument();
055: Set nodes = new HashSet();
056: if (doc != null) {
057: nodes.add(doc.getRepositoryNode());
058: }
059: return (org.apache.lenya.cms.repository.Node[]) nodes
060: .toArray(new org.apache.lenya.cms.repository.Node[nodes
061: .size()]);
062: }
063:
064: /**
065: * @see org.apache.lenya.cms.usecase.AbstractUsecase#doCheckPreconditions()
066: */
067: protected void doCheckPreconditions() throws Exception {
068: super .doCheckPreconditions();
069: if (!hasErrors()) {
070: UsecaseWorkflowHelper.checkWorkflow(this .manager, this ,
071: getEvent(), getSourceDocument(), getLogger());
072: }
073: setParameter("executable", Boolean.valueOf(!hasErrors()));
074: }
075:
076: /**
077: * @see org.apache.lenya.cms.usecase.AbstractUsecase#doExecute()
078: */
079: protected void doExecute() throws Exception {
080: super .doExecute();
081: Document xml = getXml();
082: saveDocument(xml);
083: }
084:
085: protected String getEncoding() {
086: Request request = ContextHelper.getRequest(this .context);
087: String encoding = request.getCharacterEncoding();
088: return encoding;
089: }
090:
091: protected String getXmlString(String encoding) {
092: // Get namespaces
093: String namespaces = removeRedundantNamespaces(getParameterAsString("namespaces"));
094: if (getLogger().isDebugEnabled()) {
095: getLogger().debug(namespaces);
096: }
097: // Aggregate content
098: String content = "<?xml version=\"1.0\" encoding=\""
099: + encoding
100: + "\"?>\n"
101: + addNamespaces(namespaces,
102: getParameterAsString("content"));
103: return content;
104: }
105:
106: public void advance() throws UsecaseException {
107: clearErrorMessages();
108: try {
109: Document xml = getXml();
110: if (xml != null) {
111: validate(xml);
112: }
113: if (!hasErrors()) {
114: SourceUtil.writeDOM(xml, getSourceDocument()
115: .getOutputStream());
116: deleteParameter("content");
117: }
118: } catch (Exception e) {
119: throw new UsecaseException(e);
120: }
121: }
122:
123: protected void doCheckExecutionConditions() throws Exception {
124: super .doCheckExecutionConditions();
125: if (hasErrors()) {
126: return;
127: }
128:
129: Document xml = getXml();
130: if (xml != null) {
131: validate(xml);
132: }
133: }
134:
135: protected void validate(Document xml) throws Exception {
136: ResourceType resourceType = getSourceDocument()
137: .getResourceType();
138: Schema schema = resourceType.getSchema();
139: ValidationUtil.validate(this .manager, xml, schema,
140: new UsecaseErrorHandler(this ));
141: }
142:
143: protected Document getXml() throws ParserConfigurationException,
144: IOException {
145: String encoding = getEncoding();
146: String xmlString = getXmlString(encoding);
147:
148: Document xml = null;
149: try {
150: xml = DocumentHelper.readDocument(xmlString, encoding);
151: } catch (SAXException e) {
152: addErrorMessage("error-document-form", new String[] { e
153: .getMessage() });
154: }
155: return xml;
156: }
157:
158: /**
159: * Save the content to the document source. After saving, the XML is
160: * validated. If validation errors occur, the usecase transaction is rolled
161: * back, so the changes are not persistent. If the validation succeeded, the
162: * workflow event is invoked.
163: *
164: * @param content The content to save.
165: * @throws Exception if an error occurs.
166: */
167: protected void saveDocument(Document content) throws Exception {
168: saveXMLFile(content, getSourceDocument());
169:
170: WorkflowUtil.invoke(this .manager, getSession(), getLogger(),
171: getSourceDocument(), getEvent());
172: }
173:
174: /**
175: * Save the XML file
176: * @param content The content
177: * @param document The source
178: */
179: protected void saveXMLFile(Document content,
180: org.apache.lenya.cms.publication.Document document) {
181: try {
182: SourceUtil.writeDOM(content, document.getOutputStream());
183: LinkConverter converter = new LinkConverter(this .manager,
184: getLogger());
185: converter.convertUrlsToUuids(document, false);
186: } catch (Exception e) {
187: addErrorMessage(e.getMessage());
188: }
189: }
190:
191: /**
192: * Remove redundant namespaces
193: * @param namespaces The namespaces to remove
194: * @return The namespace string without the removed namespaces
195: */
196: private String removeRedundantNamespaces(String namespaces) {
197: String[] namespace = namespaces.split(" ");
198:
199: String ns = "";
200: for (int i = 0; i < namespace.length; i++) {
201: if (ns.indexOf(namespace[i]) < 0) {
202: ns = ns + " " + namespace[i];
203: } else {
204: if (getLogger().isDebugEnabled()) {
205: getLogger().debug(
206: "Redundant namespace: " + namespace[i]);
207: }
208: }
209: }
210: return ns;
211: }
212:
213: /**
214: * Add namespaces
215: * @param namespaces The namespaces to add
216: * @param content The content to add them to
217: * @return The content with the added namespaces
218: */
219: private String addNamespaces(String namespaces, String content) {
220: int i = content.indexOf(">");
221: return content.substring(0, i) + " " + namespaces
222: + content.substring(i);
223: }
224:
225: protected String getEvent() {
226: return "edit";
227: }
228:
229: }
|