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.util.Arrays;
021: import java.util.HashSet;
022: import java.util.List;
023: import java.util.Set;
024:
025: import org.apache.lenya.cms.publication.Area;
026: import org.apache.lenya.cms.publication.Document;
027: import org.apache.lenya.cms.publication.DocumentLocator;
028: import org.apache.lenya.cms.publication.DocumentManager;
029: import org.apache.lenya.cms.publication.Publication;
030: import org.apache.lenya.cms.publication.PublicationException;
031: import org.apache.lenya.cms.repository.Node;
032: import org.apache.lenya.cms.site.Link;
033: import org.apache.lenya.cms.site.NodeSet;
034: import org.apache.lenya.cms.site.SiteException;
035: import org.apache.lenya.cms.site.SiteNode;
036: import org.apache.lenya.cms.site.SiteStructure;
037: import org.apache.lenya.cms.site.SiteUtil;
038: import org.apache.lenya.cms.usecase.DocumentUsecase;
039: import org.apache.lenya.cms.usecase.UsecaseException;
040: import org.apache.lenya.cms.workflow.WorkflowUtil;
041: import org.apache.lenya.cms.workflow.usecases.UsecaseWorkflowHelper;
042: import org.apache.lenya.util.Assert;
043: import org.apache.lenya.workflow.Workflowable;
044:
045: /**
046: * Usecase to move a subsite to another area.
047: *
048: * @version $Id:$
049: */
050: public abstract class MoveSubsite extends DocumentUsecase {
051:
052: /**
053: * @return The possible source areas.
054: */
055: protected abstract String[] getSourceAreas();
056:
057: /**
058: * @return The target area.
059: */
060: protected abstract String getTargetArea();
061:
062: /**
063: * @see org.apache.lenya.cms.usecase.AbstractUsecase#doCheckPreconditions()
064: */
065: protected void doCheckPreconditions() throws Exception {
066: super .doCheckPreconditions();
067: if (hasErrors()) {
068: return;
069: }
070:
071: List sourceAreas = Arrays.asList(getSourceAreas());
072: if (!sourceAreas.contains(getSourceDocument().getArea())) {
073: addErrorMessage("This usecase can only be invoked in the authoring area!");
074: } else {
075:
076: Document document = getSourceDocument();
077:
078: NodeSet subsite = SiteUtil.getSubSite(this .manager,
079: document.getLink().getNode());
080: Document[] docs = subsite.getDocuments();
081: for (int i = 0; i < docs.length; i++) {
082: if (docs[i].existsAreaVersion(Publication.LIVE_AREA)) {
083: Document liveVersion = docs[i]
084: .getAreaVersion(Publication.LIVE_AREA);
085: addErrorMessage("delete-doc-live",
086: new String[] { liveVersion.toString() });
087: }
088: UsecaseWorkflowHelper.checkWorkflow(this .manager, this ,
089: getEvent(), docs[i], getLogger());
090: }
091: }
092: }
093:
094: /**
095: * @return The workflow event.
096: */
097: protected abstract String getEvent();
098:
099: /**
100: * Lock all source documents and the site structure repository nodes because
101: * changes to the site structure would compromise the operation.
102: */
103: protected Node[] getNodesToLock() throws UsecaseException {
104: Set nodes = new HashSet();
105:
106: if (getSourceDocument() != null) {
107: try {
108:
109: SiteStructure sourceSite = getSourceDocument().area()
110: .getSite();
111: SiteStructure targetSite = getSourceDocument()
112: .getPublication().getArea(getTargetArea())
113: .getSite();
114:
115: nodes.add(sourceSite.getRepositoryNode());
116: nodes.add(targetSite.getRepositoryNode());
117:
118: Document[] docs = SiteUtil.getSubSite(this .manager,
119: getSourceDocument().getLink().getNode())
120: .getDocuments();
121: for (int i = 0; i < docs.length; i++) {
122: nodes.add(docs[i].getRepositoryNode());
123: }
124:
125: } catch (PublicationException e) {
126: throw new UsecaseException(e);
127: }
128: }
129:
130: return (Node[]) nodes.toArray(new Node[nodes.size()]);
131: }
132:
133: /**
134: * @see org.apache.lenya.cms.usecase.AbstractUsecase#doExecute()
135: */
136: protected void doExecute() throws Exception {
137:
138: String targetAreaName = getTargetArea();
139: Document doc = getSourceDocument();
140: Document[] sources = SiteUtil.getSubSite(this .manager,
141: doc.getLink().getNode()).getDocuments();
142: Area targetArea = doc.getPublication().getArea(targetAreaName);
143:
144: DocumentLocator targetLoc = doc.getLocator().getAreaVersion(
145: targetAreaName);
146: targetLoc = SiteUtil.getAvailableLocator(this .manager,
147: getDocumentFactory(), targetLoc);
148:
149: for (int i = 0; i < sources.length; i++) {
150: WorkflowUtil.invoke(this .manager, getSession(),
151: getLogger(), sources[i], getEvent(), true);
152:
153: if (this .getClass().getName().equals(
154: Restore.class.getName())) {
155: Workflowable workflowable = WorkflowUtil
156: .getWorkflowable(this .manager, getSession(),
157: getLogger(), sources[i]);
158: String state = workflowable.getLatestVersion()
159: .getState();
160: if (!state.equals("authoring")) {
161: addErrorMessage("The state is [" + state
162: + "] instead of [authoring]!");
163: }
164: }
165:
166: }
167:
168: DocumentManager docManager = null;
169: try {
170: docManager = (DocumentManager) this .manager
171: .lookup(DocumentManager.ROLE);
172: docManager.moveAll(doc.area(), doc.getPath(), targetArea,
173: targetLoc.getPath());
174:
175: } finally {
176: if (docManager != null) {
177: this .manager.release(docManager);
178: }
179: }
180:
181: setTargetDocument(doc.getAreaVersion(targetAreaName));
182:
183: }
184:
185: public String getTargetURL(boolean success) {
186: if (getTargetArea().equals(Publication.AUTHORING_AREA)) {
187: return super .getTargetURL(success);
188: }
189:
190: String url;
191: if (!success) {
192: url = getSourceURL();
193: } else {
194: try {
195: Document document = getTargetDocument(success);
196: SiteStructure site = document.getPublication().getArea(
197: Publication.AUTHORING_AREA).getSite();
198: return getTargetUrl(site, document.getPath())
199: + getExitQueryString();
200: } catch (Exception e) {
201: throw new RuntimeException(e);
202: }
203: }
204: return url + getExitQueryString();
205: }
206:
207: protected static String getTargetUrl(SiteStructure site, String path)
208: throws SiteException {
209: if (path.length() == 0) {
210: return "/" + site.getPublication().getId() + "/"
211: + site.getArea() + "/";
212: } else if (site.contains(path)) {
213: SiteNode node = site.getNode(path);
214: if (node.getLanguages().length > 0) {
215: Link link;
216: String defaultLanguage = site.getPublication()
217: .getDefaultLanguage();
218: if (node.hasLink(defaultLanguage)) {
219: link = node.getLink(defaultLanguage);
220: } else {
221: link = node.getLink(node.getLanguages()[0]);
222: }
223: return link.getDocument().getCanonicalWebappURL();
224: } else {
225: return getTargetUrl(site, getParentPath(path));
226: }
227: } else {
228: return getTargetUrl(site, getParentPath(path));
229: }
230: }
231:
232: protected static String getParentPath(String path) {
233: Assert.notNull("path", path);
234: Assert.isTrue("not empty", path.length() > 0);
235: return path.substring(0, path.lastIndexOf("/"));
236: }
237:
238: }
|