BaseLink geändert, so daß es nun auch GlobalizedMessage als Parameter für setConfirmation akzeptiert.

git-svn-id: https://svn.libreccm.org/ccm/trunk@1581 8810af33-2d31-482b-a856-94f89814c4df
master
quasi 2012-04-11 10:47:15 +00:00
parent 7cb62dc985
commit d70384d34f
1 changed files with 124 additions and 118 deletions

View File

@ -23,6 +23,7 @@ import java.util.TooManyListenersException;
import com.arsdigita.bebop.event.PrintListener; import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.event.PrintEvent; import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.util.Assert; import com.arsdigita.util.Assert;
import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.util.UncheckedWrapperException;
@ -30,45 +31,21 @@ import com.arsdigita.util.UncheckedWrapperException;
* The parent of all Bebop Link classes, this class represents a URL on a page. * The parent of all Bebop Link classes, this class represents a URL on a page.
* It may contain a label, an image, or any other component. * It may contain a label, an image, or any other component.
* *
* <p> The following table lists all Bebop Link classes and suggests * <p> The following table lists all Bebop Link classes and suggests when they
* when they might be used. * might be used. <p> <table BORDER=3> <tr> <th>Link Class</th> <th>Usage</th>
* <p> * </tr> <tr> <td>{@link BaseLink}</td> <td>Parent class of Bebop Link classes.
* <table BORDER=3> * Extend this class to build your own Link class.</td> </tr> <tr> <td>{@link Link}</td>
* <tr> * <td>Link class that manages its own URL variables. Session information is
* <th>Link Class</th> * added to the target URL for this type.</td> </tr> <tr> <td>{@link ExternalLink}</td>
* <th>Usage</th> * <td>Link that does not encode the URL with any session information. Used for
* </tr> * a link to a page outside the site.</td> </tr> <tr> <td>{@link ControlLink}</td>
* <tr> * <td> Used for references within its own page (often as fields in a table
* <td>{@link BaseLink}</td> * header for sorting a column).</td> </tr> <tr> <td>{@link ActionLink}</td>
* <td>Parent class of Bebop Link classes. Extend this class to
* build your own Link class.</td>
* </tr>
* <tr>
* <td>{@link Link}</td>
* <td>Link class that manages its own URL variables. Session information
* is added to the target URL for this type.</td>
* </tr>
* <tr>
* <td>{@link ExternalLink}</td>
* <td>Link that does not encode the URL with any session information.
* Used for a link to a page outside the site.</td>
* </tr>
* <tr>
* <td>{@link ControlLink}</td>
* <td> Used for references within its own page (often
* as fields in a table header for sorting a column).</td>
* </tr>
* <tr>
* <td>{@link ActionLink}</td>
* <td>Sets its own control event and runs its own * <td>Sets its own control event and runs its own
* {@link com.arsdigita.bebop.event.ActionListener}s. When the link is clicked, * {@link com.arsdigita.bebop.event.ActionListener}s. When the link is clicked,
* the code in the Listener's <tt>actionPerformed</tt> method runs.</td> * the code in the Listener's <tt>actionPerformed</tt> method runs.</td> </tr>
* </tr> * <tr> <td>{@link ToggleLink}</td> <td>A link that turns into label when it is
* <tr> * selected and turns back into a link when it is unselected.</td> </tr>
* <td>{@link ToggleLink}</td>
* <td>A link that turns into label when it is selected and
* turns back into a link when it is unselected.</td>
* </tr>
* </table> * </table>
* *
* @version $Id: BaseLink.java 998 2005-11-15 22:27:13Z sskracic $ * @version $Id: BaseLink.java 998 2005-11-15 22:27:13Z sskracic $
@ -77,20 +54,18 @@ public abstract class BaseLink extends TextStylable
implements Cloneable { implements Cloneable {
/** /**
* The name of the attribute used in XML to indicate which type of link * The name of the attribute used in XML to indicate which type of link this
* this link represents. * link represents.
*/ */
private final String TYPE_ATTR = "type"; private final String TYPE_ATTR = "type";
private final String HREF_NO_JAVASCRIPT = "href_no_javascript"; private final String HREF_NO_JAVASCRIPT = "href_no_javascript";
private final String HREF = "href"; private final String HREF = "href";
protected String m_url; protected String m_url;
protected String m_noJavascriptURL = null; protected String m_noJavascriptURL = null;
protected Component m_child; protected Component m_child;
private PrintListener m_printListener; private PrintListener m_printListener;
private String m_sConfirmMsg = ""; private String m_sConfirmMsg = "";
private GlobalizedMessage m_confirmMsg;
/** /**
* Constructor * Constructor
@ -149,6 +124,7 @@ public abstract class BaseLink extends TextStylable
this("", l); this("", l);
} }
@Override
public Object clone() throws CloneNotSupportedException { public Object clone() throws CloneNotSupportedException {
BaseLink result = (BaseLink) super.clone(); BaseLink result = (BaseLink) super.clone();
result.m_printListener = null; result.m_printListener = null;
@ -156,60 +132,57 @@ public abstract class BaseLink extends TextStylable
} }
/** /**
* Adds a print listener. * Adds a print listener. Since the
* Since the <code>PrintListener</code> is expected to modify the * <code>PrintListener</code> is expected to modify the target of the
* target of the <code>PrintEvent</code>, only one print listener can be * <code>PrintEvent</code>, only one print listener can be set for a link.
* set for a link. *
* @param listener the print listener * @param listener the print listener
* @throws IllegalArgumentException if <code>listener</code> is null. * @throws IllegalArgumentException if
* <code>listener</code> is null.
* @throws TooManyListenersException if a print listener has previously been * @throws TooManyListenersException if a print listener has previously been
* added. * added. @pre listener != null
* @pre listener != null */ */
public void addPrintListener(PrintListener listener) public void addPrintListener(PrintListener listener)
throws IllegalStateException, TooManyListenersException throws IllegalStateException, TooManyListenersException {
{ if (listener == null) {
if ( listener == null ) { throw new IllegalArgumentException("Argument listener can not be null");
throw new IllegalArgumentException
("Argument listener can not be null");
} }
if ( m_printListener != null ) { if (m_printListener != null) {
throw new TooManyListenersException throw new TooManyListenersException("Too many listeners. Can only have one");
("Too many listeners. Can only have one");
} }
m_printListener = listener; m_printListener = listener;
} }
/** /**
* Removes a previously added print listener. If the passed in * Removes a previously added print listener. If the passed in
* <code>listener</code> is * <code>listener</code> is not the listener that was added with {@link #addPrintListener
* not the listener that was added with {@link #addPrintListener
* addPrintListener}, an IllegalArgumentException will be thrown. * addPrintListener}, an IllegalArgumentException will be thrown.
*
* @param listener the listener that was previously added with * @param listener the listener that was previously added with
* <code>addPrintListener</code> * <code>addPrintListener</code>
* @throws IllegalArgumentException if <code>listener</code> is not the * @throws IllegalArgumentException if
* currently registered print listener or is <code>null</code>. * <code>listener</code> is not the currently registered print listener or
* @pre listener != null * is
* <code>null</code>. @pre listener != null
*/ */
public void removePrintListener(PrintListener listener) public void removePrintListener(PrintListener listener)
throws IllegalArgumentException throws IllegalArgumentException {
{ if (listener == null) {
if ( listener == null ) {
throw new IllegalArgumentException("listener can not be null"); throw new IllegalArgumentException("listener can not be null");
} }
if ( listener != m_printListener ) { if (listener != m_printListener) {
throw new IllegalArgumentException throw new IllegalArgumentException("listener is not registered with this widget");
("listener is not registered with this widget");
} }
m_printListener = null; m_printListener = null;
} }
protected BaseLink firePrintEvent(PageState state) { protected BaseLink firePrintEvent(PageState state) {
BaseLink l = this; BaseLink l = this;
if ( m_printListener != null ) { if (m_printListener != null) {
try { try {
l = (BaseLink) this.clone(); l = (BaseLink) this.clone();
m_printListener.prepare(new PrintEvent(this, state, l)); m_printListener.prepare(new PrintEvent(this, state, l));
} catch ( CloneNotSupportedException e ) { } catch (CloneNotSupportedException e) {
l = this; l = this;
throw new UncheckedWrapperException(e); throw new UncheckedWrapperException(e);
} }
@ -217,7 +190,6 @@ public abstract class BaseLink extends TextStylable
return l; return l;
} }
public final Component getChild() { public final Component getChild() {
return m_child; return m_child;
} }
@ -227,7 +199,7 @@ public abstract class BaseLink extends TextStylable
m_child = child; m_child = child;
} }
public final String getTarget(){ public final String getTarget() {
return m_url; return m_url;
} }
@ -247,31 +219,33 @@ public abstract class BaseLink extends TextStylable
setAttribute(TYPE_ATTR, t); setAttribute(TYPE_ATTR, t);
} }
protected abstract void generateURL(PageState state, Element parent); protected abstract void generateURL(PageState state, Element parent);
/** /**
* <p>Generates a DOM fragment: * <p>Generates a DOM fragment: <p><pre>
* <p><pre>
* &lt;bebop:link href="..." type="..." %bebopAttr;/> * &lt;bebop:link href="..." type="..." %bebopAttr;/>
* </pre> * </pre> The
* The <code>href</code> attribute contains the target the link * <code>href</code> attribute contains the target the link should point to.
* should point to. The <code>type</code> attribute is used to * The
* give more finegrained control over which kind of link this element * <code>type</code> attribute is used to give more finegrained control over
* represents. The types are <code>link</code> for a * which kind of link this element represents. The types are
* <code>Link</code>, <code>control</code> for a {@link ControlLink}, * <code>link</code> for a
* and <code>toggle</code> for a {@link ToggleLink}. There may be * <code>Link</code>,
* additional attributes depending on what type of link this link * <code>control</code> for a {@link ControlLink}, and
* represents. * <code>toggle</code> for a {@link ToggleLink}. There may be additional
* attributes depending on what type of link this link represents.
*
* @see ControlLink#generateXML * @see ControlLink#generateXML
* @see ToggleLink#generateXML * @see ToggleLink#generateXML
*/ */
@Override
public void generateXML(PageState state, Element parent) { public void generateXML(PageState state, Element parent) {
if ( isVisible(state) ) { if (isVisible(state)) {
BaseLink target = firePrintEvent(state); BaseLink target = firePrintEvent(state);
Element link = parent.newChildElement ("bebop:link", BEBOP_XML_NS); Element link = parent.newChildElement("bebop:link", BEBOP_XML_NS);
target.generateURL(state, link); target.generateURL(state, link);
target.exportAttributes(link); target.exportConfirmAttributes(state, link);
// target.exportAttributes(link);
//setup the link without javascript //setup the link without javascript
target.setupNoJavascriptURL(state, link); target.setupNoJavascriptURL(state, link);
target.exportAttributes(link); target.exportAttributes(link);
@ -314,7 +288,9 @@ public abstract class BaseLink extends TextStylable
protected void setupNoJavascriptURL(PageState ps, Element link) { protected void setupNoJavascriptURL(PageState ps, Element link) {
String sURL = null; String sURL = null;
if (m_sConfirmMsg.length() > 0) { if (m_sConfirmMsg.length() > 0
|| (m_confirmMsg != null && m_confirmMsg.localize().toString().length() > 0)) {
//if we want the confirm link, create the link //if we want the confirm link, create the link
String sOkUrl = getAbsoluteUrl(ps, link.getAttribute(HREF)); String sOkUrl = getAbsoluteUrl(ps, link.getAttribute(HREF));
String sCancelUrl = null; String sCancelUrl = null;
@ -324,7 +300,11 @@ public abstract class BaseLink extends TextStylable
Assert.fail("Could not get current page state as URL"); Assert.fail("Could not get current page state as URL");
} }
if (m_sConfirmMsg.length() > 0) {
sURL = ConfirmPage.getConfirmUrl(m_sConfirmMsg, sOkUrl, sCancelUrl); sURL = ConfirmPage.getConfirmUrl(m_sConfirmMsg, sOkUrl, sCancelUrl);
} else if (m_confirmMsg != null) {
sURL = ConfirmPage.getConfirmUrl(m_confirmMsg.localize().toString(), sOkUrl, sCancelUrl);
}
} else { } else {
//don't want confirm link--just no javascript link //don't want confirm link--just no javascript link
@ -340,22 +320,24 @@ public abstract class BaseLink extends TextStylable
} }
/** /**
* Adds type-specific XML attributes to the XML element representing * Adds type-specific XML attributes to the XML element representing this
* this link. Subclasses should override this method if they introduce * link. Subclasses should override this method if they introduce more
* more attributes than the ones {@link #generateXML generateXML} * attributes than the ones {@link #generateXML generateXML} produces by
* produces by default. * default.
* *
* @param state the current request * @param state the current request
* @param link the XML element representing this link * @param link the XML element representing this link
*/ */
protected void generateExtraXMLAttributes(PageState state, Element link) {} protected void generateExtraXMLAttributes(PageState state, Element link) {
}
/** /**
* Sets onClick event and <em>disables the javascript-based double-click protection for this link</em>. * Sets onClick event and <em>disables the javascript-based double-click
* Not for confirmation messages; Should call setConfirmation for that. * protection for this link</em>. Not for confirmation messages; Should call
* setConfirmation for that.
* *
* @param value * @param value @pre value.toLowerCase().startsWith("return confirm(") ==
* @pre value.toLowerCase().startsWith("return confirm(") == false * false
* *
* @see #setConfirmation * @see #setConfirmation
*/ */
@ -364,8 +346,8 @@ public abstract class BaseLink extends TextStylable
//use setConfirmation() instead, or else the javascript will break //use setConfirmation() instead, or else the javascript will break
if (value != null) { if (value != null) {
Assert.isTrue(!value.toLowerCase().startsWith("return confirm("), Assert.isTrue(!value.toLowerCase().startsWith("return confirm("),
"Do not use setOnClick() to set confirmation messages. " + "Do not use setOnClick() to set confirmation messages. "
"Use setCofirmation() instead."); + "Use setCofirmation() instead.");
} }
setAttribute(ON_CLICK, value); setAttribute(ON_CLICK, value);
@ -373,20 +355,20 @@ public abstract class BaseLink extends TextStylable
/** /**
* Forces the user to click through a confirmation dialog before this link * Forces the user to click through a confirmation dialog before this link
* is followed. The user is prompted with the specified message. If the * is followed. The user is prompted with the specified message. If the user
* user does not does not confirm, the link is not followed. The current * does not does not confirm, the link is not followed. The current
* implementation uses the JavaScript confirm function and the onClick * implementation uses the JavaScript confirm function and the onClick
* attribute. * attribute. If JavaScript is not enabled in the client browser, this
* If JavaScript is not enabled in the client browser, this method will * method will redirect the browser to a Bebop confirmation page rather than
* redirect the browser to a Bebop confirmation page rather than use * use a JavaScript confirmation. Subsequent calls to setOnClick will undo
* a JavaScript confirmation. * the effect of this method.
* Subsequent calls to setOnClick will undo the effect of this method.
* *
* @param message the confirmation message presented to the user. This * @param message the confirmation message presented to the user. This
* message cannot have an apostrophe or back slash * message cannot have an apostrophe or back slash
* *
* @pre message.indexOf("'") == -1 && message.indexOf("\\") == -1 * @pre message.indexOf("'") == -1 && message.indexOf("\\") == -1
**/ *
*/
public void setConfirmation(String message) { public void setConfirmation(String message) {
//make sure that the message doesn't have any apostrophe's //make sure that the message doesn't have any apostrophe's
//or back slashes //or back slashes
@ -405,6 +387,30 @@ public abstract class BaseLink extends TextStylable
m_sConfirmMsg = message; m_sConfirmMsg = message;
} }
public void setConfirmation(GlobalizedMessage msg) {
m_confirmMsg = msg;
}
private void exportConfirmAttributes(PageState state, Element link) {
if (m_sConfirmMsg.length() > 0 || m_confirmMsg != null) {
// Set confirm link, if
setAttribute("confirm", "confirm");
if (m_sConfirmMsg.length() > 0) {
//set the onclick attribute for the link
setAttribute(ON_CLICK, "return confirm(\\'" + m_sConfirmMsg + "\\');");
} else if (m_confirmMsg != null) {
//set the onclick attribute for the link
setAttribute(ON_CLICK, "return confirm(\\'" + m_confirmMsg.localize() + "\\');");
}
}
}
public final void setNoJavascriptTarget(String sURL) { public final void setNoJavascriptTarget(String sURL) {
Assert.isUnlocked(this); Assert.isUnlocked(this);
m_noJavascriptURL = sURL; m_noJavascriptURL = sURL;