001: /*
002: * Copyright (C) 2006 Methodhead Software LLC. All rights reserved.
003: *
004: * This file is part of TransferCM.
005: *
006: * TransferCM is free software; you can redistribute it and/or modify it under the
007: * terms of the GNU General Public License as published by the Free Software
008: * Foundation; either version 2 of the License, or (at your option) any later
009: * version.
010: *
011: * TransferCM is distributed in the hope that it will be useful, but WITHOUT ANY
012: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
013: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
014: * details.
015: *
016: * You should have received a copy of the GNU General Public License along with
017: * TransferCM; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
018: * Fifth Floor, Boston, MA 02110-1301 USA
019: */
020:
021: package com.methodhead.shim;
022:
023: import javax.servlet.http.HttpServletRequest;
024: import javax.servlet.http.HttpServletResponse;
025: import javax.servlet.jsp.JspWriter;
026: import org.apache.struts.action.ActionMapping;
027: import org.apache.struts.action.ActionForward;
028: import org.apache.struts.action.DynaActionForm;
029: import com.methodhead.persistable.Persistable;
030: import com.methodhead.persistable.PersistableException;
031: import com.methodhead.persistable.ConnectionSingleton;
032: import com.methodhead.aikp.IntKey;
033: import org.apache.commons.beanutils.DynaClass;
034: import org.apache.commons.beanutils.DynaProperty;
035: import org.apache.commons.beanutils.BasicDynaClass;
036: import org.apache.commons.lang.exception.ExceptionUtils;
037: import java.io.IOException;
038: import java.util.List;
039: import java.util.ArrayList;
040: import java.sql.ResultSet;
041: import java.sql.SQLException;
042: import java.util.regex.Pattern;
043: import java.util.regex.Matcher;
044: import org.apache.commons.lang.exception.ExceptionUtils;
045: import org.apache.log4j.Logger;
046:
047: /**
048: * A Shim module to manage HTML text.
049: * <ul>
050: * <li><tt>int page_id = 0</tt></li>
051: * <li><tt>String panel = ""</tt></li>
052: * <li><tt>String value = ""</tt></li>
053: * <li><tt>int htmlfragment_id = NULL</tt></li>
054: * </ul>
055: */
056: public class TextModule extends Persistable implements Module {
057:
058: private static DynaClass dynaClass_ = null;
059:
060: static {
061: DynaProperty[] dynaProperties = new DynaProperty[] {
062: new DynaProperty("page_id", Integer.class),
063: new DynaProperty("panel", String.class),
064: new DynaProperty("value", String.class),
065: new DynaProperty("htmlfragment_id", Integer.class) };
066:
067: dynaClass_ = new BasicDynaClass("shim_text", TextModule.class,
068: dynaProperties);
069: }
070:
071: // constructors /////////////////////////////////////////////////////////////
072:
073: public TextModule() {
074: super (dynaClass_);
075: init();
076: }
077:
078: public TextModule(DynaClass dynaClass) {
079: super (dynaClass);
080: init();
081: }
082:
083: // constants ////////////////////////////////////////////////////////////////
084:
085: // classes //////////////////////////////////////////////////////////////////
086:
087: // methods //////////////////////////////////////////////////////////////////
088:
089: /**
090: * Loads the text module for <tt>page</tt> and <tt>panel</tt> set by {@link
091: * #init init()}.
092: */
093: public void load() {
094: super .load("page_id=" + getInt("page_id") + " AND panel="
095: + getSqlLiteral(getString("panel")));
096: }
097:
098: /**
099: * Saves the text module for <tt>page</tt> and <tt>panel</tt> set by {@link
100: * #init init()}. The text module should already have been created with
101: * {@link #create create()}.
102: */
103: public void save() {
104: //
105: // force fragment id to null if it's zero; this let's us use the foreign
106: // key in the database
107: //
108: if (getInt("htmlfragment_id") == 0)
109: set("htmlfragment_id", null);
110:
111: super .save("page_id=" + getInt("page_id") + " AND panel="
112: + getSqlLiteral(getString("panel")));
113: }
114:
115: /**
116: * Saves the text module for <tt>page</tt> and <tt>panel</tt> set by {@link
117: * #init init()}. The text module should already have been created with
118: * {@link #create create()}.
119: */
120: public void saveNew() {
121: //
122: // force fragment id to null if it's zero; this let's us use the foreign
123: // key in the database
124: //
125: if (getInt("htmlfragment_id") == 0)
126: set("htmlfragment_id", null);
127:
128: super .saveNew();
129: }
130:
131: private void init() {
132: setInt("page_id", 0);
133: setString("panel", "");
134: setString("value", "");
135: set("htmlfragment_id", null);
136: }
137:
138: /**
139: * Returns a short descriptive name for the module.
140: */
141: public String getName() {
142: return "Text";
143: }
144:
145: /**
146: * Returns <tt>true</tt> if the module has a configuration interface; that
147: * is, if {@link #configure} actually does something.
148: */
149: public boolean isConfigurable() {
150: return true;
151: }
152:
153: /**
154: * Sets the module's <tt>page</tt> and <tt>panel</tt>. This method is called
155: * before any other operations are performed.
156: */
157: public void init(Page page, String panel) {
158:
159: if ((page == null) || (panel == null))
160: throw new ShimException("Page and/or panel is null.");
161:
162: if (page.getPanels().get(panel) == null)
163: throw new ShimException("Page has no panel \"" + panel
164: + "\"");
165:
166: setInt("page_id", page.getInt("id"));
167: setString("panel", panel);
168:
169: if (!"".equals(page.getSiteContext().getString("path")))
170: siteContextPath_ = page.getSiteContext().getString("path");
171: }
172:
173: /**
174: * Creates the module. This method is called when a module is instantiated
175: * for a page and panel. The module should be initialized such that future
176: * calls to {@link #configure} and {@link #display} are successful.
177: */
178: public void create() {
179: //
180: // try to load it first; leave text alone if it already exists
181: //
182: try {
183: load();
184: } catch (PersistableException e) {
185:
186: //
187: // otherwise, create the text
188: //
189: setString("value", "Insert your text here...");
190: saveNew();
191: }
192: }
193:
194: /**
195: * Manages the configuration interface for the module.
196: */
197: public ActionForward configure(ActionMapping mapping,
198: DynaActionForm form, HttpServletRequest request,
199: HttpServletResponse response) {
200:
201: return new ActionForward("/configureTextModuleForm.do?pageid="
202: + form.get("pageid") + "&panel=" + form.get("panel"));
203: }
204:
205: public boolean isEditable() {
206: return true;
207: }
208:
209: public void update(String text) {
210:
211: load("page_id=" + getInt("page_id") + " AND panel="
212: + getSqlLiteral(getString("panel")));
213:
214: //
215: // referencing a fragment?
216: //
217: if (getInt("htmlfragment_id") != 0) {
218: HtmlFragment fragment = new HtmlFragment();
219: fragment.load(new IntKey(getInt("htmlfragment_id")));
220: fragment.setString("value", text);
221: fragment.save();
222: } else {
223: setString("value", text);
224: save();
225: }
226: }
227:
228: /**
229: * Displays the module.
230: */
231: public void display(HttpServletRequest request,
232: HttpServletResponse response, JspWriter out)
233: throws IOException {
234:
235: load("page_id=" + getInt("page_id") + " AND panel="
236: + getSqlLiteral(getString("panel")));
237:
238: //
239: // referencing a fragment?
240: //
241: if (getInt("htmlfragment_id") != 0) {
242: HtmlFragment fragment = new HtmlFragment();
243: fragment.load(new IntKey(getInt("htmlfragment_id")));
244: out.println(fragment.getString("value"));
245: } else {
246: out.println(getString("value"));
247: }
248: }
249:
250: /**
251: * Destroys the module, freeing any resources associated with the module.
252: */
253: public void destroy() {
254: deleteAll(dynaClass_, "page_id=" + getInt("page_id")
255: + " AND panel=" + getSqlLiteral(getString("panel")));
256: }
257:
258: public void copyTo(Page page) {
259:
260: //
261: // load this module
262: //
263: load();
264:
265: //
266: // load the module to copy to
267: //
268: TextModule textModule = new TextModule();
269: textModule.init(page, getString("panel"));
270:
271: //
272: // already exists?
273: //
274: try {
275: textModule.load();
276:
277: //
278: // update it
279: //
280: textModule.setString("value", getString("value"));
281: textModule.setInt("htmlfragment_id",
282: getInt("htmlfragment_id"));
283: textModule.save();
284: } catch (PersistableException e) {
285:
286: //
287: // save new
288: //
289: textModule.setString("value", getString("value"));
290: textModule.setInt("htmlfragment_id",
291: getInt("htmlfragment_id"));
292: textModule.saveNew();
293: }
294: }
295:
296: /**
297: * Returns a list of pages which use text modules that refer to
298: * <tt>fragment</tt>. <tt>fragment</tt> is expected to be loaded when this
299: * method is called.
300: */
301: public List getDependentPages(HtmlFragment fragment) {
302:
303: List pages = new ArrayList();
304:
305: String sql = "SELECT " + " shim_page.id AS id " + "FROM "
306: + " shim_page " + "LEFT JOIN " + " shim_text ON "
307: + " shim_text.page_id=shim_page.id " + "WHERE "
308: + " shim_text.htmlfragment_id="
309: + fragment.getInt("id");
310:
311: ResultSet rs = null;
312: try {
313: rs = ConnectionSingleton.runQuery(sql);
314:
315: if (rs == null) {
316: throw new SQLException("Null result set.");
317: }
318:
319: while (rs.next()) {
320: Page page = new Page();
321: page.setSiteContext(fragment.getSiteContext());
322: page.load(new IntKey(rs.getInt("id")));
323: pages.add(page);
324: }
325: } catch (SQLException e) {
326: String msg = "Doing something. "
327: + ExceptionUtils.getStackTrace(e);
328: logger_.error(msg);
329: throw new RuntimeException(msg);
330: } finally {
331: ConnectionSingleton.close(rs);
332: }
333:
334: return pages;
335: }
336:
337: // properties ///////////////////////////////////////////////////////////////
338:
339: // attributes ///////////////////////////////////////////////////////////////
340:
341: private String siteContextPath_ = null;
342:
343: private static Logger logger_ = Logger.getLogger(TextModule.class);
344: }
|