/* * * Copyright 2005 AgileTec s.r.l. (http://www.agiletec.it) All rights reserved. * * This file is part of jAPS software. * jAPS is a free software; * you can redistribute it and/or modify it * under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation; version 2. * * See the file License for the specific language governing permissions * and limitations under the License * * * * Copyright 2005 AgileTec s.r.l. (http://www.agiletec.it) All rights reserved. * */ package com.agiletec.aps.system.services.page; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; import java.util.List; import com.agiletec.aps.system.ApsSystemUtils; import com.agiletec.aps.system.common.AbstractDAO; import com.agiletec.aps.system.exception.ApsSystemException; import com.agiletec.aps.system.services.pagemodel.IPageModelManager; import com.agiletec.aps.system.services.showlettype.IShowletTypeManager; import com.agiletec.aps.system.services.showlettype.ShowletType; import com.agiletec.aps.util.ApsProperties; /** * Data Access Object for the 'page' objects * @author M.Diana - E.Santoboni */ public class PageDAO extends AbstractDAO implements IPageDAO { /** * Load a sorted list of the pages and the configuration of the showlets * @return the list of pages */ @Override public List<IPage> loadPages() { Connection conn = null; Statement stat = null; ResultSet res = null; List<IPage> pages = null; try { conn = this.getConnection(); stat = conn.createStatement(); res = stat.executeQuery(ALL_PAGES); pages = this.createPages(res); } catch (Throwable t) { processDaoException(t, "Error loading pages", "loadPages"); } finally { closeDaoResources(res, stat, conn); } return pages; } /** * Read & create in a single passage, for efficiency reasons, the pages and the * association of the associated showlets. * @param res the result set where to extract pages information from. * @return The list of the pages defined in the system * @throws Throwable In case of error */ protected List<IPage> createPages(ResultSet res) throws Throwable { List<IPage> pages = new ArrayList<IPage>(); Object record[] = null; Page page = null; Showlet showlets[] = null; int numFrames = 0; String prevCode = "...no previous code..."; while (res.next()) { record = getRecord(res); String code = (String) record[3]; if (!code.equals(prevCode)) { if (page != null) { pages.add(page); } page = this.createPage(record); numFrames = page.getModel().getFrames().length; showlets = new Showlet[numFrames]; page.setShowlets(showlets); prevCode = code; } if (record[9] != null) { Integer pos = new Integer(record[9].toString()); int intPos = pos.intValue(); if (intPos >= 0 && intPos < numFrames) { showlets[intPos] = this.createShowlet(record, page); } else { ApsSystemUtils.getLogger().info("The position read from the database exceeds " + "the numer of frames defined in the model of the page '"+ page.getCode()+"'"); } } } pages.add(page); return pages; } /** * Return an array of the objects contained in the given result set. This is needed in * order to put the record in a buffer because some drivers will prevent the access to the * same column twice in the same result set. * WARNING: to fetch the objects of the record use the same index of the result set, * starting from 1 for the first column. * * @param res The result set containing the objects to put in a buffer. * @return An array containing the objects fetched from the given result set * @throws SQLException in case of error */ protected Object[] getRecord(ResultSet res) throws SQLException { int size = res.getMetaData().getColumnCount(); Object record[] = new Object[size + 1]; for (int i = 1; i <= size; i++) { record[i] = res.getObject(i); } return record; } protected Page createPage(Object[] record) throws ApsSystemException { Page page = new Page(); page.setCode((String) record[3]); page.setParentCode((String) record[1]); page.setPosition(Integer.parseInt(record[2].toString())); Integer showable = new Integer (record[4].toString()); page.setShowable(showable.intValue() == 1); String modelCode = (String) record[5]; page.setModel(this.getPageModelManager().getPageModel(modelCode)); String titleText = (String) record[6]; ApsProperties titles = new ApsProperties(); try { titles.loadFromXml(titleText); } catch (Throwable t) { String msg = "IO error detected while parsing the titles of the page '" + page.getCode()+"'"; ApsSystemUtils.logThrowable(t, this, "createPage", msg); throw new ApsSystemException(msg, t); } page.setTitles(titles); page.setGroup((String) record[7]); String extraConfig = (String) record[8]; if (null != extraConfig && extraConfig.trim().length() > 0) { try { PageExtraConfigDOM configDom = new PageExtraConfigDOM(); configDom.addExtraConfig(page, extraConfig); } catch (Throwable t) { String msg = "IO error detected while parsing the extra config of the page '" + page.getCode()+"'"; ApsSystemUtils.logThrowable(t, this, "createPage", msg); throw new ApsSystemException(msg, t); } } return page; } protected Showlet createShowlet(Object[] record, IPage page) throws ApsSystemException { Showlet showlet = new Showlet(); int pos = Integer.parseInt(record[9].toString()); String typeCode = (String) record[10]; ShowletType type = this.getShowletTypeManager().getShowletType(typeCode); showlet.setType(type); ApsProperties config = new ApsProperties(); String configText = (String) record[11]; if (null != configText && configText.trim().length() > 0) { try { config.loadFromXml(configText); } catch (Throwable t) { String msg = "IO error detected while parsing the configuration of the showlet in position " +pos+ " of the page '"+ page.getCode()+"'"; ApsSystemUtils.logThrowable(t, this, "createShowlet", msg); throw new ApsSystemException(msg, t); } } else { config = type.getConfig(); } showlet.setConfig(config); String contentPublished = (String) record[12]; showlet.setPublishedContent(contentPublished); return showlet; } /** * Insert a new page. * @param page The new page to insert. */ @Override public void addPage(IPage page) { Connection conn = null; try { conn = this.getConnection(); conn.setAutoCommit(false); this.addPageRecord(page, conn); this.addShowletForPage(page, conn); conn.commit(); } catch (Throwable t) { this.executeRollback(conn); processDaoException(t, "Error while adding a new page", "addPage"); } finally { closeConnection(conn); } } protected void addPageRecord(IPage page, Connection conn) throws ApsSystemException { int position = 1; if (page.getParent().getChildren()!= null ){ position = page.getParent().getChildren().length + 1; } PreparedStatement stat = null; try { stat = conn.prepareStatement(ADD_PAGE); stat.setString(1, page.getCode()); stat.setString(2, page.getParent().getCode()); if (page.isShowable()) { stat.setInt(3, 1); } else { stat.setInt(3, 0); } stat.setInt(4, position); stat.setString(5, page.getModel().getCode()); stat.setString(6, page.getTitles().toXml()); stat.setString(7, page.getGroup()); String extraConfig = this.getExtraConfig(page); stat.setString(8, extraConfig); stat.executeUpdate(); } catch (Throwable t) { processDaoException(t, "Error adding a new page record", "addPageRecord"); } finally { closeDaoResources(null, stat); } } /** * Delete the page identified by the given code. * @param page The page to delete. */ @Override public void deletePage(IPage page) { Connection conn = null; try { conn = this.getConnection(); conn.setAutoCommit(false); this.deleteShowlets(page.getCode(), conn); this.deletePageRecord(page.getCode(), conn); this.shiftPages(page.getParentCode(), page.getPosition(), conn); conn.commit(); } catch (Throwable t) { this.executeRollback(conn); processDaoException(t, "Error deleting the page", "deletePage"); } finally { closeConnection(conn); } } protected void deletePageRecord(String pageCode, Connection conn) throws ApsSystemException { PreparedStatement stat = null; try { stat = conn.prepareStatement(DELETE_PAGE); stat.setString(1, pageCode); stat.executeUpdate(); } catch (Throwable t) { processDaoException(t, "Error deleting a page record", "deletePageRecord"); } finally { closeDaoResources(null, stat); } } /** * Delete the showlets associated to a page. * @param codePage The code of the page containing the showlets to delete. * @throws ApsSystemException In case of database error */ protected void deleteShowlets(String codePage, Connection conn) throws ApsSystemException { PreparedStatement stat = null; try { stat = conn.prepareStatement(DELETE_SHOWLETS_FOR_PAGE); stat.setString(1, codePage); stat.executeUpdate(); } catch (Throwable t) { processDaoException(t, "Error while deleting showlets", "deleteShowlets"); } finally { closeDaoResources(null, stat); } } /** * Decrement by one the position of a group of pages to compact the positions after a deletion * @param parentCode the code of the parent of the pages to compact. * @param position The empty position which needs to be compacted. * @param conn The connection to the database * @throws ApsSystemException In case of database error */ protected void shiftPages(String parentCode, int position, Connection conn) throws ApsSystemException { PreparedStatement stat = null; try { stat = conn.prepareStatement(SHIFT_PAGE); stat.setString(1, parentCode); stat.setInt(2, position); stat.executeUpdate(); } catch (Throwable t) { processDaoException(t, "Error while compating positions", "shiftPages"); } finally { closeDaoResources(null, stat); } } /** * Updates the position for the page movement * @param pageDown The page to move downwards * @param pageUp The page to move upwards */ @Override public void updatePosition(IPage pageDown, IPage pageUp) { Connection conn = null; PreparedStatement stat = null; PreparedStatement stat2 = null; try { conn = this.getConnection(); conn.setAutoCommit(false); stat = conn.prepareStatement(MOVE_DOWN); stat.setString(1, pageDown.getCode()); stat.executeUpdate(); stat2 = conn.prepareStatement(MOVE_UP); stat2.setString(1, pageUp.getCode()); stat2.executeUpdate(); conn.commit(); } catch (Throwable t) { this.executeRollback(conn); processDaoException(t, "Error detected while updating positions", "updatePosition"); } finally { closeDaoResources(null, stat); closeDaoResources(null, stat2, conn); } } /** * Updates a page record in the database. * @param page The page to update */ @Override public void updatePage(IPage page) { Connection conn = null; try { conn = this.getConnection(); conn.setAutoCommit(false); this.deleteShowlets(page.getCode(), conn); this.updatePageRecord(page, conn); this.addShowletForPage(page, conn); conn.commit(); } catch (Throwable t) { this.executeRollback(conn); processDaoException(t, "Error while updating the page", "updatePage"); } finally { closeConnection(conn); } } protected void updatePageRecord(IPage page, Connection conn) throws ApsSystemException { PreparedStatement stat = null; try { stat = conn.prepareStatement(UPDATE_PAGE); stat.setString(1, page.getParentCode()); if (page.isShowable()) { stat.setInt(2, 1); } else { stat.setInt(2, 0); } stat.setString(3, page.getModel().getCode()); stat.setString(4, page.getTitles().toXml()); stat.setString(5, page.getGroup()); String extraConfig = this.getExtraConfig(page); stat.setString(6, extraConfig); stat.setString(7, page.getCode()); stat.executeUpdate(); } catch (Throwable t) { processDaoException(t, "Error while updating the page record", "updatePageRecord"); } finally { closeDaoResources(null, stat); } } protected String getExtraConfig(IPage page) { PageExtraConfigDOM dom = this.getExtraConfigDOM(); return dom.extractXml(page); } protected PageExtraConfigDOM getExtraConfigDOM() { return new PageExtraConfigDOM(); } protected void addShowletForPage(IPage page, Connection conn) throws ApsSystemException { if (null == page.getShowlets()) return; PreparedStatement stat = null; try { Showlet[] showlets = page.getShowlets(); stat = conn.prepareStatement(ADD_SHOWLET_FOR_PAGE); for (int i = 0; i < showlets.length; i++) { Showlet showlet = showlets[i]; if (showlet != null) { if (null == showlet.getType()) { ApsSystemUtils.getLogger().severe("Showlet Type null when adding " + "showlet on frame '" + i + "' of page '" + page.getCode() + "'"); continue; } this.valueAddShowletStatement(page.getCode(), i, showlet, stat); stat.addBatch(); stat.clearParameters(); } } stat.executeBatch(); } catch (Throwable t) { processDaoException(t, "Error while inserting the showlets in a page", "addShowletForPage"); } finally { closeDaoResources(null, stat); } } @Override public void removeShowlet(String pageCode, int pos) { Connection conn = null; PreparedStatement stat = null; try { conn = this.getConnection(); conn.setAutoCommit(false); stat = conn.prepareStatement(REMOVE_SHOWLET_FROM_FRAME); stat.setString(1, pageCode); stat.setInt(2, pos); stat.executeUpdate(); conn.commit(); } catch (Throwable t) { this.executeRollback(conn); processDaoException(t, "" + "Error removing the showlet in the page '" +pageCode + "' in the frame " + pos, "removeShowlet"); } finally { closeDaoResources(null, stat, conn); } } @Override public void joinShowlet(String pageCode, Showlet showlet, int pos) { this.removeShowlet(pageCode, pos); Connection conn = null; PreparedStatement stat = null; try { conn = this.getConnection(); conn.setAutoCommit(false); stat = conn.prepareStatement(ADD_SHOWLET_FOR_PAGE); this.valueAddShowletStatement(pageCode, pos, showlet, stat); stat.executeUpdate(); conn.commit(); } catch (Throwable t) { this.executeRollback(conn); processDaoException(t, "Error adding a showlet in the frame " +pos+" of the page '"+pageCode+"'", "joinShowlet"); } finally { closeDaoResources(null, stat, conn); } } private void valueAddShowletStatement(String pageCode, int pos, Showlet showlet, PreparedStatement stat) throws Throwable { stat.setString(1, pageCode); stat.setInt(2, pos); stat.setString(3, showlet.getType().getCode()); if (!showlet.getType().isLogic()) { String config = null; if (null != showlet.getConfig()) { config = showlet.getConfig().toXml(); } stat.setString(4, config); } else { stat.setNull(4, Types.VARCHAR); } stat.setString(5, showlet.getPublishedContent()); } protected IPageModelManager getPageModelManager() { return _pageModelManager; } public void setPageModelManager(IPageModelManager pageModelManager) { this._pageModelManager = pageModelManager; } protected IShowletTypeManager getShowletTypeManager() { return _showletTypeManager; } public void setShowletTypeManager(IShowletTypeManager showletTypeManager) { this._showletTypeManager = showletTypeManager; } private IPageModelManager _pageModelManager; private IShowletTypeManager _showletTypeManager; // attenzione: l'ordinamento deve rispettare prima l'ordine delle pagine // figlie nelle pagine madri, e poi l'ordine delle showlet nella pagina. private static final String ALL_PAGES = "SELECT p.parentcode, p.pos, p.code, p.showinmenu, " + "p.modelcode, p.titles, p.groupcode, p.extraconfig, " + "s.framepos, s.showletcode, s.config, s.publishedcontent " + "FROM pages p LEFT JOIN showletconfig s ON p.code = s.pagecode " + "ORDER BY p.parentcode, p.pos, p.code, s.framepos"; private static final String ADD_PAGE = "INSERT INTO pages(code, parentcode, showinmenu, pos, modelcode, titles, groupcode, extraconfig) VALUES ( ? , ? , ? , ? , ? , ? , ? , ? )"; private static final String DELETE_PAGE = "DELETE FROM pages WHERE code = ? "; private static final String DELETE_SHOWLETS_FOR_PAGE = "DELETE FROM showletconfig WHERE pagecode = ? "; private static final String REMOVE_SHOWLET_FROM_FRAME = DELETE_SHOWLETS_FOR_PAGE + " AND framepos = ? "; private static final String MOVE_UP = "UPDATE pages SET pos = (pos - 1) WHERE code = ? "; private static final String MOVE_DOWN = "UPDATE pages SET pos = (pos + 1) WHERE code = ? "; private static final String UPDATE_PAGE = "UPDATE pages SET parentcode = ? , showinmenu = ? , modelcode = ? , titles = ? , groupcode = ? , extraconfig = ? WHERE code = ? "; private static final String SHIFT_PAGE = "UPDATE pages SET pos = (pos - 1) WHERE parentcode = ? AND pos > ? "; private static final String ADD_SHOWLET_FOR_PAGE = "INSERT INTO showletconfig (pagecode, framepos, showletcode, config, publishedcontent) VALUES ( ?, ?, ?, ?, ?)"; }