001: /* ***** BEGIN LICENSE BLOCK *****
002: * Version: MPL 1.1
003: * The contents of this file are subject to the Mozilla Public License Version
004: * 1.1 (the "License"); you may not use this file except in compliance with
005: * the License. You may obtain a copy of the License at
006: * http://www.mozilla.org/MPL/
007: *
008: * Software distributed under the License is distributed on an "AS IS" basis,
009: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
010: * for the specific language governing rights and limitations under the
011: * License.
012: *
013: * The Original Code is Riot.
014: *
015: * The Initial Developer of the Original Code is
016: * Neteye GmbH.
017: * Portions created by the Initial Developer are Copyright (C) 2007
018: * the Initial Developer. All Rights Reserved.
019: *
020: * Contributor(s):
021: * Felix Gnass [fgnass at neteye dot de]
022: *
023: * ***** END LICENSE BLOCK ***** */
024: package org.riotfamily.pages.dao;
025:
026: import java.io.Serializable;
027: import java.util.ArrayList;
028: import java.util.Collection;
029: import java.util.Date;
030: import java.util.Iterator;
031: import java.util.List;
032: import java.util.Map;
033:
034: import org.apache.commons.logging.Log;
035: import org.apache.commons.logging.LogFactory;
036: import org.riotfamily.components.model.VersionContainer;
037: import org.riotfamily.components.service.ComponentService;
038: import org.riotfamily.pages.component.PageComponentListLocator;
039: import org.riotfamily.pages.model.Page;
040: import org.riotfamily.pages.model.PageAlias;
041: import org.riotfamily.pages.model.PageNode;
042: import org.riotfamily.pages.model.Site;
043: import org.springframework.beans.factory.InitializingBean;
044: import org.springframework.util.Assert;
045: import org.springframework.util.ObjectUtils;
046:
047: /**
048: * Abstract base class for {@link PageDao} implementations.
049: *
050: * @author Felix Gnass [fgnass at neteye dot de]
051: * @author Jan-Frederic Linde [jfl at neteye dot de]
052: * @since 6.5
053: */
054: public abstract class AbstractPageDao implements PageDao,
055: InitializingBean {
056:
057: private static final Log log = LogFactory
058: .getLog(AbstractPageDao.class);
059:
060: private ComponentService componentService;
061:
062: private Map childHandlerNames;
063:
064: private Map autoCreatePages;
065:
066: public AbstractPageDao() {
067: }
068:
069: public void setComponentService(ComponentService componentService) {
070: this .componentService = componentService;
071: }
072:
073: public void setChildHandlerNames(Map childHandlerNames) {
074: this .childHandlerNames = childHandlerNames;
075: }
076:
077: protected String getChildHandlerName(String parentHandlerName) {
078: if (childHandlerNames != null) {
079: return (String) childHandlerNames.get(parentHandlerName);
080: }
081: return null;
082: }
083:
084: public void setAutoCreatePages(Map autoCreatePages) {
085: this .autoCreatePages = autoCreatePages;
086: }
087:
088: public final void afterPropertiesSet() throws Exception {
089: Assert.notNull(componentService, "A ComponentDao must be set.");
090: initDao();
091: }
092:
093: protected void initDao() {
094: }
095:
096: protected abstract Object loadObject(Class clazz, Serializable id);
097:
098: protected abstract void saveObject(Object object);
099:
100: protected abstract void updateObject(Object object);
101:
102: protected abstract void deleteObject(Object object);
103:
104: protected abstract void flush();
105:
106: public Page loadPage(Long id) {
107: return (Page) loadObject(Page.class, id);
108: }
109:
110: public Site loadSite(Long id) {
111: return (Site) loadObject(Site.class, id);
112: }
113:
114: public Site findSite(String hostName, String path) {
115: Iterator it = listSites().iterator();
116: while (it.hasNext()) {
117: Site site = (Site) it.next();
118: if (site.matches(hostName, path)) {
119: return site;
120: }
121: }
122: return null;
123: }
124:
125: public void saveNode(PageNode node) {
126: if (node.getHandlerName() == null && node.getParent() != null) {
127: node.setHandlerName(getChildHandlerName(node.getParent()
128: .getHandlerName()));
129: }
130:
131: String handlerName = node.getHandlerName();
132: if (autoCreatePages != null && handlerName != null) {
133: PageDefinition child = (PageDefinition) autoCreatePages
134: .get(handlerName);
135: if (child != null) {
136: ArrayList sites = new ArrayList();
137: Iterator it = node.getPages().iterator();
138: while (it.hasNext()) {
139: Page page = (Page) it.next();
140: sites.add(page.getSite());
141: }
142: child.createNode(node, sites, this );
143: }
144: }
145:
146: saveObject(node);
147: }
148:
149: public void savePage(Page parent, Page page) {
150: page.setSite(parent.getSite());
151: savePage(parent.getNode(), page);
152: }
153:
154: public void savePage(Site site, Page page) {
155: savePage(getRootNode(), page);
156: }
157:
158: private void savePage(PageNode parentNode, Page page) {
159: PageNode node = page.getNode();
160: if (node == null) {
161: node = new PageNode();
162:
163: }
164: node.addPage(page); // It could be that the node does not yet contain
165: // the page itself, for example when edited nested...
166:
167: if (!PageValidationUtils.isValidChild(parentNode, page)) {
168: log.warn("Page not saved because not valid: " + page);
169: throw new DuplicatePathComponentException(
170: "Page '{0}' did not validate", page.toString());
171: }
172:
173: parentNode.addChildNode(node);
174: page.setCreationDate(new Date());
175:
176: saveNode(node);
177: deleteAlias(page);
178:
179: log.debug("Page saved: " + page);
180: }
181:
182: public Page addTranslation(Page page, Site site) {
183: log.info("Adding translation " + page + " --> " + site);
184: Page translation = new Page();
185: translation.setSite(site);
186: translation.setCreationDate(new Date());
187: translation.setPathComponent(page.getPathComponent());
188: translation.setFolder(page.isFolder());
189: translation.setHidden(page.isHidden());
190: PageNode node = page.getNode();
191: if (node.isSystemNode()) {
192: translation.setPublished(page.isPublished());
193: }
194: translation.setVersionContainer(componentService
195: .copyVersionContainer(page.getVersionContainer()));
196:
197: node.addPage(translation);
198: updateNode(node);
199: deleteAlias(translation);
200: saveObject(translation);
201:
202: componentService.copyComponentLists(
203: PageComponentListLocator.TYPE_PAGE, page.getId()
204: .toString(), translation.getId().toString());
205:
206: return translation;
207: }
208:
209: public void updatePage(Page page) {
210: updateNode(page.getNode());
211: updateObject(page);
212:
213: if (!PageValidationUtils.isValidChild(page.getNode()
214: .getParent(), page)) {
215: log.warn("Page not saved because not valid: " + page);
216: throw new DuplicatePathComponentException(
217: "Page '{0}' did not validate", page.toString());
218: }
219:
220: String oldPath = page.getPath();
221: String newPath = page.buildPath();
222: if (!ObjectUtils.nullSafeEquals(oldPath, newPath)) {
223: log.info("Path modified: " + page);
224: page.setPath(newPath);
225: createAlias(page, oldPath);
226: updatePaths(page.getChildPages());
227: }
228: }
229:
230: public void updateNode(PageNode node) {
231: updateObject(node);
232: }
233:
234: public void moveNode(PageNode node, PageNode newParent) {
235: PageNode parentNode = node.getParent();
236: parentNode.getChildNodes().remove(node);
237: newParent.addChildNode(node);
238: updatePaths(node.getPages());
239: }
240:
241: private void updatePaths(Collection pages) {
242: Iterator it = pages.iterator();
243: while (it.hasNext()) {
244: Page page = (Page) it.next();
245: String oldPath = page.getPath();
246: page.setPath(page.buildPath());
247: createAlias(page, oldPath);
248: updateObject(page);
249: updatePaths(page.getChildPages());
250: }
251: }
252:
253: protected abstract void clearAliases(Page page);
254:
255: protected abstract void deleteAliases(Site site);
256:
257: public void deleteAlias(Page page) {
258: PageAlias alias = findPageAlias(page.getSite(), page.getPath());
259: if (alias != null) {
260: log.info("Deleting " + alias);
261: deleteObject(alias);
262: }
263: }
264:
265: protected void createGoneAlias(Site site, String path) {
266: PageAlias alias = new PageAlias(null, site, path);
267: log.info("Creating " + alias);
268: saveObject(alias);
269: }
270:
271: protected void createAlias(Page page, String path) {
272: deleteAlias(page);
273: PageAlias alias = new PageAlias(page, page.getSite(), path);
274: log.info("Creating " + alias);
275: saveObject(alias);
276: }
277:
278: public void deletePage(Page page) {
279: log.info("Deleting page " + page);
280: Collection childPages = page.getChildPages();
281: if (childPages != null) {
282: Iterator it = childPages.iterator();
283: while (it.hasNext()) {
284: Page child = (Page) it.next();
285: deletePage(child);
286: }
287: }
288: componentService.deleteComponentLists(
289: PageComponentListLocator.TYPE_PAGE, page.getId()
290: .toString());
291:
292: clearAliases(page);
293:
294: PageNode node = page.getNode();
295: node.removePage(page);
296: deleteObject(page);
297:
298: VersionContainer vc = page.getVersionContainer();
299: page.setVersionContainer(null);
300: componentService.deleteVersionContainer(vc);
301:
302: if (node.hasPages()) {
303: updateNode(node);
304: } else {
305: log.debug("Node has no more pages - deleting it ...");
306: PageNode parentNode = node.getParent();
307: if (parentNode != null) {
308: parentNode.getChildNodes().remove(node);
309: updateNode(parentNode);
310: }
311: deleteObject(node);
312: }
313: }
314:
315: public void saveSite(Site site) {
316: saveObject(site);
317: Site masterSite = site.getMasterSite();
318: if (masterSite == null) {
319: masterSite = getDefaultSite();
320: }
321: translateSystemPages(getRootNode(), masterSite, site);
322: }
323:
324: private void translateSystemPages(PageNode node, Site masterSite,
325: Site site) {
326: List childNodes = node.getChildNodes();
327: if (childNodes != null) {
328: Iterator it = childNodes.iterator();
329: while (it.hasNext()) {
330: PageNode childNode = (PageNode) it.next();
331: if (childNode.isSystemNode()) {
332: addTranslation(childNode.getPage(masterSite), site);
333: translateSystemPages(childNode, masterSite, site);
334: }
335: }
336: }
337: }
338:
339: public void updateSite(Site site) {
340: updateObject(site);
341: }
342:
343: public void deleteSite(Site site) {
344: Iterator it = getRootNode().getChildPages(site).iterator();
345: while (it.hasNext()) {
346: Page page = (Page) it.next();
347: deletePage(page);
348: }
349: deleteAliases(site);
350: deleteObject(site);
351: }
352:
353: }
|