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.site.usecases;
019:
020: import java.text.DateFormat;
021: import java.text.SimpleDateFormat;
022: import java.util.Date;
023: import java.util.Map;
024:
025: import org.apache.avalon.framework.service.ServiceSelector;
026: import org.apache.cocoon.components.ContextHelper;
027: import org.apache.cocoon.environment.ObjectModelHelper;
028: import org.apache.cocoon.environment.Request;
029: import org.apache.cocoon.environment.Session;
030: import org.apache.lenya.ac.Identity;
031: import org.apache.lenya.cms.metadata.dublincore.DublinCore;
032: import org.apache.lenya.cms.publication.Document;
033: import org.apache.lenya.cms.publication.DocumentException;
034: import org.apache.lenya.cms.publication.DocumentFactory;
035: import org.apache.lenya.cms.publication.DocumentManager;
036: import org.apache.lenya.cms.publication.ResourceType;
037: import org.apache.lenya.cms.repository.Node;
038: import org.apache.lenya.cms.site.SiteStructure;
039: import org.apache.lenya.cms.usecase.DocumentUsecase;
040: import org.apache.lenya.cms.usecase.UsecaseException;
041: import org.apache.lenya.xml.DocumentHelper;
042: import org.apache.xpath.XPathAPI;
043: import org.w3c.dom.Element;
044:
045: /**
046: * Usecase to create a Blog entry.
047: *
048: * @version $Id: CreateBlogEntry.java 557603 2007-07-19 12:48:31Z andreas $
049: */
050: public class CreateBlogEntry extends DocumentUsecase {
051:
052: protected static final String PARENT_ID = "parentId";
053: protected static final String DOCUMENT_TYPE = "doctype";
054: protected static final String DOCUMENT_ID = "documentId";
055:
056: /**
057: * @see org.apache.lenya.cms.usecase.AbstractUsecase#getNodesToLock()
058: */
059: protected Node[] getNodesToLock() throws UsecaseException {
060: SiteStructure structure = getSourceDocument().area().getSite();
061: Node[] nodes = { structure.getRepositoryNode() };
062: return nodes;
063: }
064:
065: /**
066: * @see org.apache.lenya.cms.usecase.AbstractUsecase#initParameters()
067: */
068: protected void initParameters() {
069: super .initParameters();
070:
071: Document parent = getSourceDocument();
072: try {
073: setParameter(PARENT_ID, parent.getPath());
074: } catch (DocumentException e) {
075: throw new RuntimeException(e);
076: }
077: }
078:
079: /**
080: * @see org.apache.lenya.cms.usecase.AbstractUsecase#doCheckExecutionConditions()
081: */
082: protected void doCheckExecutionConditions() throws Exception {
083:
084: String documentId = getParameterAsString(DOCUMENT_ID);
085:
086: if (documentId.equals("")) {
087: addErrorMessage("The document ID is required.");
088: }
089:
090: if (documentId.matches("[^a-zA-Z0-9\\-]+")) {
091: addErrorMessage("The document ID is not valid.");
092: }
093:
094: super .doCheckExecutionConditions();
095: }
096:
097: /**
098: * @see org.apache.lenya.cms.usecase.AbstractUsecase#doExecute()
099: */
100: protected void doExecute() throws Exception {
101: super .doExecute();
102:
103: // prepare values necessary for blog entry creation
104: Document parent = getSourceDocument();
105: String language = parent.getPublication().getDefaultLanguage();
106:
107: // create new document
108: // implementation note: since blog does not have a hierarchy,
109: // document id (full path) and document id-name (this leaf's id)
110: // are the same
111: DocumentManager documentManager = null;
112: ServiceSelector selector = null;
113: ResourceType resourceType = null;
114:
115: try {
116: selector = (ServiceSelector) this .manager
117: .lookup(ResourceType.ROLE + "Selector");
118: resourceType = (ResourceType) selector
119: .select(getDocumentTypeName());
120:
121: documentManager = (DocumentManager) this .manager
122: .lookup(DocumentManager.ROLE);
123:
124: DocumentFactory map = getDocumentFactory();
125:
126: String documentId = getDocumentID();
127:
128: String sampleName = resourceType.getSampleNames()[0];
129: String sampleUri = resourceType.getSample(sampleName)
130: .getUri();
131:
132: Document document = documentManager.add(map, resourceType,
133: sampleUri, getSourceDocument().getPublication(),
134: getSourceDocument().getArea(), documentId,
135: language, "xml",
136: getParameterAsString(DublinCore.ELEMENT_TITLE),
137: true);
138:
139: transformXML(document);
140: } finally {
141: if (documentManager != null) {
142: this .manager.release(documentManager);
143: }
144: if (selector != null) {
145: if (resourceType != null) {
146: selector.release(resourceType);
147: }
148: this .manager.release(selector);
149: }
150: }
151: }
152:
153: /**
154: * The blog publication has a specific site structuring: it groups nodes by date.
155: *
156: * <p>
157: * Example structuring of blog entries:
158: * </p>
159: * <ul>
160: * <li>2004</li>
161: * <li>2005</li>
162: * <ul>
163: * <li>01</li>
164: * <li>02</li>
165: * <ul>
166: * <li>23</li>
167: * <li>24</li>
168: * <ul>
169: * <li>article-one</li>
170: * <li>article-two</li>
171: * </ul>
172: * </ul>
173: * </ul>
174: * </ul>
175: *
176: * @return The document ID.
177: */
178: protected String getDocumentID() {
179: DateFormat fmtyyyy = new SimpleDateFormat("yyyy");
180: DateFormat fmtMM = new SimpleDateFormat("MM");
181: DateFormat fmtdd = new SimpleDateFormat("dd");
182: Date date = new Date();
183:
184: String year = fmtyyyy.format(date);
185: String month = fmtMM.format(date);
186: String day = fmtdd.format(date);
187:
188: String documentId = "/entries/" + year + "/" + month + "/"
189: + day + "/" + getNewDocumentName() + "/index";
190: return documentId;
191: }
192:
193: /**
194: * @return The document name.
195: * @see org.apache.lenya.cms.site.usecases.Create#getNewDocumentName()
196: */
197: protected String getNewDocumentName() {
198: return getParameterAsString(DOCUMENT_ID);
199: }
200:
201: /**
202: * @return The name of the document type.
203: * @see org.apache.lenya.cms.site.usecases.Create#getDocumentTypeName()
204: */
205: protected String getDocumentTypeName() {
206: return getParameterAsString(DOCUMENT_TYPE);
207: }
208:
209: protected void transformXML(Document document) throws Exception {
210:
211: Map objectModel = ContextHelper.getObjectModel(getContext());
212: Request request = ObjectModelHelper.getRequest(objectModel);
213: Session session = request.getSession(false);
214: Identity identity = (Identity) session
215: .getAttribute(Identity.class.getName());
216: String title = getParameterAsString(DublinCore.ELEMENT_TITLE);
217:
218: org.w3c.dom.Document xmlDoc = DocumentHelper
219: .readDocument(document.getInputStream());
220:
221: Element parent = xmlDoc.getDocumentElement();
222:
223: if (getLogger().isDebugEnabled())
224: getLogger().debug(
225: "NewBlogEntryCreator.transformXML(): " + document);
226:
227: String[] steps = document.getPath().split("/");
228: String nodeId = steps[5];
229:
230: // Replace id
231: Element element = (Element) XPathAPI.selectSingleNode(parent,
232: "/*[local-name() = 'entry']/*[local-name() = 'id']");
233:
234: String year = steps[2];
235: String month = steps[3];
236: String day = steps[4];
237:
238: DocumentHelper.setSimpleElementText(element, year + "/" + month
239: + "/" + day + "/" + nodeId);
240:
241: // Replace title
242: element = (Element) XPathAPI.selectSingleNode(parent,
243: "/*[local-name() = 'entry']/*[local-name() = 'title']");
244: DocumentHelper.setSimpleElementText(element, title);
245:
246: element = (Element) XPathAPI.selectSingleNode(parent,
247: "/*[local-name() = 'entry']/*[local-name() = 'link']");
248: element.setAttribute("rel", "alternate");
249: element.setAttribute("href", "");
250: element.setAttribute("type", "text/xml");
251:
252: // Replace Summary
253: element = (Element) XPathAPI
254: .selectSingleNode(parent,
255: "/*[local-name() = 'entry']/*[local-name() = 'summary']");
256: DocumentHelper.setSimpleElementText(element, "Summary");
257:
258: element = (Element) XPathAPI
259: .selectSingleNode(
260: parent,
261: "/*[local-name() = 'entry']/*[local-name() = 'author']/*[local-name() = 'name']");
262:
263: if (element == null) {
264: throw new RuntimeException(
265: "Element entry/author/name not found.");
266: }
267:
268: DocumentHelper.setSimpleElementText(element, identity.getUser()
269: .getId());
270:
271: // Replace date created, issued and modified
272: DateFormat datefmt = new SimpleDateFormat(
273: "yyyy-MM-dd'T'HH:mm:ss");
274: DateFormat ofsfmt = new SimpleDateFormat("Z");
275: Date date = new Date();
276:
277: String dateofs = ofsfmt.format(date);
278: String datestr = datefmt.format(date) + dateofs.substring(0, 3)
279: + ":" + dateofs.substring(3, 5);
280:
281: element = (Element) XPathAPI
282: .selectSingleNode(parent,
283: "/*[local-name() = 'entry']/*[local-name() = 'created']");
284: DocumentHelper.setSimpleElementText(element, datestr);
285: element = (Element) XPathAPI
286: .selectSingleNode(parent,
287: "/*[local-name() = 'entry']/*[local-name() = 'issued']");
288: DocumentHelper.setSimpleElementText(element, datestr);
289: element = (Element) XPathAPI
290: .selectSingleNode(parent,
291: "/*[local-name() = 'entry']/*[local-name() = 'modified']");
292: DocumentHelper.setSimpleElementText(element, datestr);
293:
294: DocumentHelper
295: .writeDocument(xmlDoc, document.getOutputStream());
296: }
297: }
|