Changed the column type for the abstract and misc properties of Publications from varchar(4096) to text. It also now possible to enable the HTML editor for the abstract and misc fields of publications. The default is still no HTML editor.

git-svn-id: https://svn.libreccm.org/ccm/trunk@2558 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2014-03-07 06:52:42 +00:00
parent 13b7c7cf2e
commit b396010920
15 changed files with 1557 additions and 1462 deletions

View File

@ -18,7 +18,6 @@
*/ */
package com.arsdigita.cms.ui.authoring; package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.Component; import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.RequestLocal; import com.arsdigita.bebop.RequestLocal;
@ -34,14 +33,12 @@ import com.arsdigita.cms.util.GlobalizationUtil;
import com.arsdigita.domain.DomainObject; import com.arsdigita.domain.DomainObject;
import com.arsdigita.util.Assert; import com.arsdigita.util.Assert;
/** /**
* Displays the current text body of the article and allows the user * Displays the current text body of the article and allows the user to edit it, by uploading a file
* to edit it, by uploading a file or entering text in a textbox. * or entering text in a textbox.
* *
* The {@link com.arsdigita.bebop.PropertySheet} class is often used * The {@link com.arsdigita.bebop.PropertySheet} class is often used as the display component in the
* as the display component in the default authoring kit steps of * default authoring kit steps of this class.
* this class.
* *
* @author Stanislav Freidin (sfreidin@arsdigita.com) * @author Stanislav Freidin (sfreidin@arsdigita.com)
* @version $Id: GenericArticleBody.java 1949 2009-06-25 08:30:50Z terry $ * @version $Id: GenericArticleBody.java 1949 2009-06-25 08:30:50Z terry $
@ -54,12 +51,11 @@ public class GenericArticleBody extends TextAssetBody {
/** /**
* Construct a new GenericArticleBody component * Construct a new GenericArticleBody component
* *
* @param itemModel The {@link ItemSelectionModel} which will * @param itemModel The {@link ItemSelectionModel} which will be responsible for loading the
* be responsible for loading the current item * current item
* *
* @param parent The parent wizard which contains the form. The form * @param parent The parent wizard which contains the form. The form may use the wizard's
* may use the wizard's methods, such as stepForward and stepBack, * methods, such as stepForward and stepBack, in its process listener.
* in its process listener.
*/ */
public GenericArticleBody(ItemSelectionModel itemModel, AuthoringKitWizard parent) { public GenericArticleBody(ItemSelectionModel itemModel, AuthoringKitWizard parent) {
super(new ItemAssetModel(itemModel)); super(new ItemAssetModel(itemModel));
@ -73,6 +69,7 @@ public class GenericArticleBody extends TextAssetBody {
PageState state = e.getPageState(); PageState state = e.getPageState();
reset(state); reset(state);
} }
}); });
// Set the right component access on the forms // Set the right component access on the forms
@ -87,9 +84,10 @@ public class GenericArticleBody extends TextAssetBody {
} }
/** /**
* Adds the options for the mime type select widget of * Adds the options for the mime type select widget of <code>GenericArticleForm</code> and sets
* <code>GenericArticleForm</code> and sets the default mime type. * the default mime type.
**/ *
*/
@Override @Override
protected void setMimeTypeOptions(SingleSelect mimeSelect) { protected void setMimeTypeOptions(SingleSelect mimeSelect) {
mimeSelect.addOption(new Option("text/html", "HTML Text")); mimeSelect.addOption(new Option("text/html", "HTML Text"));
@ -100,6 +98,7 @@ public class GenericArticleBody extends TextAssetBody {
* Create a new text asset and associate it with the current item * Create a new text asset and associate it with the current item
* *
* @param s the current page state * @param s the current page state
*
* @return a valid TextAsset * @return a valid TextAsset
*/ */
protected TextAsset createTextAsset(PageState s) { protected TextAsset createTextAsset(PageState s) {
@ -120,8 +119,8 @@ public class GenericArticleBody extends TextAssetBody {
} }
/** /**
* Set additional parameters of a brand new text asset, such as the * Set additional parameters of a brand new text asset, such as the parent ID, after the asset
* parent ID, after the asset has been successfully uploaded * has been successfully uploaded
* *
* @param s the current page state * @param s the current page state
* @param a the new <code>TextAsset</code> * @param a the new <code>TextAsset</code>
@ -142,12 +141,11 @@ public class GenericArticleBody extends TextAssetBody {
* Get the current GenericArticle * Get the current GenericArticle
*/ */
protected GenericArticle getGenericArticle(PageState s) { protected GenericArticle getGenericArticle(PageState s) {
return (GenericArticle)m_itemModel.getSelectedObject(s); return (GenericArticle) m_itemModel.getSelectedObject(s);
} }
/** /**
* An ACSObjectSelectionModel that selects the current text asset for * An ACSObjectSelectionModel that selects the current text asset for the text page
* the text page
*/ */
private static class ItemAssetModel extends ItemSelectionModel { private static class ItemAssetModel extends ItemSelectionModel {
@ -159,24 +157,25 @@ public class GenericArticleBody extends TextAssetBody {
m_asset = new RequestLocal() { m_asset = new RequestLocal() {
@Override @Override
protected Object initialValue(PageState s) { protected Object initialValue(PageState s) {
GenericArticle t = (GenericArticle) GenericArticle t
((ItemSelectionModel)getSingleSelectionModel()) = (GenericArticle) ((ItemSelectionModel) getSingleSelectionModel()).
.getSelectedObject(s); getSelectedObject(s);
Assert.exists(t); Assert.exists(t);
return t.getTextAsset(); return t.getTextAsset();
} }
}; };
} }
@Override @Override
public Object getSelectedKey(PageState s) { public Object getSelectedKey(PageState s) {
TextAsset a = (TextAsset)getSelectedObject(s); TextAsset a = (TextAsset) getSelectedObject(s);
return (a == null) ? null : a.getID(); return (a == null) ? null : a.getID();
} }
@Override @Override
public DomainObject getSelectedObject(PageState s) { public DomainObject getSelectedObject(PageState s) {
return (DomainObject)m_asset.get(s); return (DomainObject) m_asset.get(s);
} }
@Override @Override
@ -186,13 +185,15 @@ public class GenericArticleBody extends TextAssetBody {
@Override @Override
public void setSelectedKey(PageState s, Object key) { public void setSelectedKey(PageState s, Object key) {
throw new UnsupportedOperationException( (String) GlobalizationUtil.globalize("cms.ui.authoring.not_implemented").localize()); throw new UnsupportedOperationException((String) GlobalizationUtil.globalize(
"cms.ui.authoring.not_implemented").localize());
} }
@Override @Override
public boolean isSelected(PageState s) { public boolean isSelected(PageState s) {
return (getSelectedObject(s) != null); return (getSelectedObject(s) != null);
} }
} }
} }

View File

@ -34,6 +34,8 @@
storage="ccm-core/templating.properties"/> storage="ccm-core/templating.properties"/>
<config class="com.arsdigita.ui.UIConfig" <config class="com.arsdigita.ui.UIConfig"
storage="ccm-core/ui.properties"/> storage="ccm-core/ui.properties"/>
<config class="com.arsdigita.util.SystemInformation"
storage="ccm-core/systeminformation.properties"/>
<config class="com.arsdigita.versioning.VersioningConfig" <config class="com.arsdigita.versioning.VersioningConfig"
storage="ccm-core/versioning.properties"/> storage="ccm-core/versioning.properties"/>
<config class="com.arsdigita.web.WebConfig" <config class="com.arsdigita.web.WebConfig"

View File

@ -52,16 +52,17 @@ import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* <p>The top-level container for all Bebop components and containers. </p> * <p>
* The top-level container for all Bebop components and containers. </p>
* *
* <UL> <LI>Holds references to the components of a page.</LI> <LI>Provides * <UL> <LI>Holds references to the components of a page.</LI> <LI>Provides methods for servicing
* methods for servicing requests and for notifying other components that a * requests and for notifying other components that a request for this page has been received
* request for this page has been received through * through {@link ActionListener ActionListeners}.</LI>
* {@link ActionListener ActionListeners}.</LI>
* *
* <LI>Tracks request parameters for stateful components, such as tabbed panes * <LI>Tracks request parameters for stateful components, such as tabbed panes and sortable
* and sortable tables.</LI> </UL> <p> A typical * tables.</LI> </UL>
* <code>Page</code> may be created as follows: null <blockquote><pre><code> * <p>
* A typical <code>Page</code> may be created as follows: null <blockquote><pre><code>
* Page p = new Page("Hello World"); * Page p = new Page("Hello World");
* p.add(new Label("Hello World"); * p.add(new Label("Hello World");
* p.lock(); * p.lock();
@ -84,16 +85,14 @@ public class Page extends BlockStylable implements Container {
*/ */
private static final String DELIMITER = "."; private static final String DELIMITER = ".";
/** /**
* The prefix that gets prepended to all state variables. Components * The prefix that gets prepended to all state variables. Components must not use variables
* must not use variables starting with this prefix. This guarantees * starting with this prefix. This guarantees that the page state and variables individual
* that the page state and variables individual components wish to pass * components wish to pass do not interfere with each other.
* do not interfere with each other.
*/ */
private static final String COMPONENT_PREFIX = "bbp" + DELIMITER; private static final String COMPONENT_PREFIX = "bbp" + DELIMITER;
private static final String INTERNAL = COMPONENT_PREFIX; private static final String INTERNAL = COMPONENT_PREFIX;
/** /**
* The name of the special parameter that indicates which component has * The name of the special parameter that indicates which component has been selected.
* been selected.
*/ */
static final String SELECTED = INTERNAL + "s"; static final String SELECTED = INTERNAL + "s";
static final String CONTROL_EVENT = INTERNAL + "e"; static final String CONTROL_EVENT = INTERNAL + "e";
@ -108,16 +107,16 @@ public class Page extends BlockStylable implements Container {
CONTROL_EVENT_KEYS.add(CONTROL_VALUE); CONTROL_EVENT_KEYS.add(CONTROL_VALUE);
s_log.debug("Static initalizer finished."); s_log.debug("Static initalizer finished.");
} }
/** /**
* The name of the request parameter used for the visibility state of * The name of the request parameter used for the visibility state of components stored in
* components stored in m_invisible. * m_invisible.
*/ */
static final String INVISIBLE = INTERNAL + "i"; static final String INVISIBLE = INTERNAL + "i";
/** /**
* Map of stateful components (id --> Component) SortedMap used because * Map of stateful components (id --> Component) SortedMap used because component based hash for
* component based hash for page is based on concatenation of component * page is based on concatenation of component ids, and so need to guarantee that they are
* ids, and so need to guarantee that they are returned in the same * returned in the same order for the same page - cg.
* order for the same page - cg.
*/ */
private SortedMap m_componentMap; private SortedMap m_componentMap;
private List m_components; private List m_components;
@ -127,42 +126,38 @@ public class Page extends BlockStylable implements Container {
private Map m_componentParameterMap = new HashMap(); private Map m_componentParameterMap = new HashMap();
private FormModel m_stateModel; private FormModel m_stateModel;
/** /**
* <code>Container</code> that renders this * <code>Container</code> that renders this <code>Page</code>.
* <code>Page</code>.
*/ */
protected Container m_panel; protected Container m_panel;
private List m_actionListeners; private List m_actionListeners;
private List m_requestListeners; private List m_requestListeners;
/** /**
* The title of the page to be added in the head of HTML output. The * The title of the page to be added in the head of HTML output. The title is wrapped in a Label
* title is wrapped in a Label to allow developers to add PrintListeners * to allow developers to add PrintListeners to dynamically change the value of the title.
* to dynamically change the value of the title.
*/ */
private Label m_title; private Label m_title;
/** /**
* Stores the actual title for the current request. The title may be * Stores the actual title for the current request. The title may be generated with a
* generated with a PrintListener of the m_title Label. * PrintListener of the m_title Label.
*/ */
private RequestLocal m_currentTitle; private RequestLocal m_currentTitle;
/** /**
* A list of all the client-side stylesheets. The elements of the list * A list of all the client-side stylesheets. The elements of the list are of type
* are of type Page.Stylesheet, defined at the end of this file. * Page.Stylesheet, defined at the end of this file.
*/ */
private List m_clientStylesheets; private List m_clientStylesheets;
private StringParameter m_selected; private StringParameter m_selected;
private StringParameter m_controlEvent; private StringParameter m_controlEvent;
private StringParameter m_controlValue; private StringParameter m_controlValue;
/** /**
* The default (initial) visibility of components. The encoding is * The default (initial) visibility of components. The encoding is identical to that for
* identical to that for PageState.m_invisible. * PageState.m_invisible.
* *
* This variable is package-friendly since it needs to be accessed by * This variable is package-friendly since it needs to be accessed by PageState.
* PageState.
*/ */
protected BitSet m_invisible; protected BitSet m_invisible;
/** /**
* The PageErrorDisplay component that will display page state * The PageErrorDisplay component that will display page state validation errors on this page
* validation errors on this page
*/ */
private Component m_errorDisplay; private Component m_errorDisplay;
/** /**
@ -170,44 +165,40 @@ public class Page extends BlockStylable implements Container {
*/ */
private boolean m_finished = false; private boolean m_finished = false;
/** /**
* indicates whether pageState.stateAsURL() should export the entire * indicates whether pageState.stateAsURL() should export the entire state for this page, or
* state for this page, or whether it should only export the control * whether it should only export the control event as a URL and use the HttpSession for the rest
* event as a URL and use the HttpSession for the rest of the page * of the page state.
* state.
*/ */
private boolean m_useHttpSession = false; private boolean m_useHttpSession = false;
/** /**
* Returns * Returns <code>true</code> if this page should export state through the HttpSession instead of
* <code>true</code> if this page should export state through the * the URL query string.
* HttpSession instead of the URL query string. <P>If this returns * <P>
* <code>true</code>, then PageState.stateAsURL() will only export the * If this returns <code>true</code>, then PageState.stateAsURL() will only export the control
* control event as a URL query string. If this returns * event as a URL query string. If this returns <code>false</code>, then stateAsURL() will
* <code>false</code>, then stateAsURL() will export the entire page * export the entire page state.
* state.
* *
* *
* @see PageState#stateAsURL * @see PageState#stateAsURL
* *
* @return <code>true</code> if this page should export state through * @return <code>true</code> if this page should export state through the HttpSession;
* the HttpSession; <code>false</code> if it should export using the URL * <code>false</code> if it should export using the URL query string.
* query string.
*/ */
public boolean isUsingHttpSession() { public boolean isUsingHttpSession() {
return m_useHttpSession; return m_useHttpSession;
} }
/** /**
* Indicates to this page whether it should export its entire state to * Indicates to this page whether it should export its entire state to subsequent requests
* subsequent requests through the URL query string, or if it should use * through the URL query string, or if it should use the HttpSession instead and only use the
* the HttpSession instead and only use the URL query string for the * URL query string for the control event.
* control event.
* *
* @see PageState#stateAsURL * @see PageState#stateAsURL
* *
* @param b <code>true</code> if PageState.stateAsURL() will export only * @param b <code>true</code> if PageState.stateAsURL() will export only the control event as a
* the control event as a URL query string. <code>false</code> if * URL query string. <code>false</code> if stateAsURL() will export the entire page
* stateAsURL() will export the entire page state. * state.
*/ */
public void setUsingHttpSession(boolean b) { public void setUsingHttpSession(boolean b) {
m_useHttpSession = b; m_useHttpSession = b;
@ -249,6 +240,7 @@ public class Page extends BlockStylable implements Container {
protected Object initialValue(PageState state) { protected Object initialValue(PageState state) {
return m_title.firePrintEvent(state); return m_title.firePrintEvent(state);
} }
}; };
// Initialize the set of state parameters to hold // Initialize the set of state parameters to hold
@ -271,16 +263,14 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Creates an empty page with default title and implicit BoxPanel * Creates an empty page with default title and implicit BoxPanel container.
* container.
*/ */
public Page() { public Page() {
this(""); this("");
} }
/** /**
* Creates an empty page with the specified title and implicit BoxPanel * Creates an empty page with the specified title and implicit BoxPanel container.
* container.
* *
* @param title title for this page * @param title title for this page
*/ */
@ -291,8 +281,7 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Creates an empty page with the specified title and implicit BoxPanel * Creates an empty page with the specified title and implicit BoxPanel container.
* container.
* *
* @param title title for this page * @param title title for this page
*/ */
@ -312,14 +301,13 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Adds a component with the specified layout constraints to this * Adds a component with the specified layout constraints to this container. Layout constraints
* container. Layout constraints are defined in each layout container as * are defined in each layout container as static ints. To specify multiple constraints, use
* static ints. To specify multiple constraints, use bitwise OR. * bitwise OR.
* *
* @param c component to add to this container * @param c component to add to this container
* *
* @param constraints layout constraints (a bitwise OR of static ints in * @param constraints layout constraints (a bitwise OR of static ints in the particular layout)
* the particular layout)
*/ */
@Override @Override
public void add(Component c, int constraints) { public void add(Component c, int constraints) {
@ -327,21 +315,18 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Returns * Returns <code>true</code> if this list contains the specified element. More formally, returns
* <code>true</code> if this list contains the specified element. More * <code>true</code> if and only if this list contains at least one element e such that (o==null
* formally, returns * ? e==null : o.equals(e)).
* <code>true</code> if and only if this list contains at least one * <P>
* element e such that (o==null ? e==null : o.equals(e)). <P> This * This method returns <code>true</code> only if the component has been directly added to this
* method returns * container. If this container contains another container that contains this component, this
* <code>true</code> only if the component has been directly added to * method returns <code>false</code>.
* this container. If this container contains another container that
* contains this component, this method returns
* <code>false</code>.
* *
* @param o element whose presence in this container is to be tested * @param o element whose presence in this container is to be tested
* *
* @return <code>true</code> if this Container contains the specified * @return <code>true</code> if this Container contains the specified component directly;
* component directly; <code>false</code> otherwise. * <code>false</code> otherwise.
*/ */
@Override @Override
public boolean contains(Object o) { public boolean contains(Object o) {
@ -349,13 +334,11 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Returns the component at the specified position. Each call to the add * Returns the component at the specified position. Each call to the add method increments the
* method increments the index. Since the user has no control over the * index. Since the user has no control over the index of added components (other than counting
* index of added components (other than counting each call to add), * each call to add), this method should be used in conjunction with indexOf.
* this method should be used in conjunction with indexOf.
* *
* @param index the index of the item to be retrieved from this * @param index the index of the item to be retrieved from this Container
* Container
* *
* @return the component at the specified position in this container. * @return the component at the specified position in this container.
*/ */
@ -369,12 +352,13 @@ public class Page extends BlockStylable implements Container {
* *
* @param c component to search for * @param c component to search for
* *
* @return the index in this list of the first occurrence of the * @return the index in this list of the first occurrence of the specified element, or -1 if
* specified element, or -1 if this list does not contain this element. * this list does not contain this element.
* *
* @pre c != null * @pre c != null
* @post contains(c) implies (return >= 0) && (return < size()) * @post contains(c) implies (return >= 0) && (return < size())
* @post !contains(c) implies return == -1 * @pos
* t !contains(c) implies return == -1
*/ */
@Override @Override
public int indexOf(Component c) { public int indexOf(Component c) {
@ -382,11 +366,10 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Returns * Returns <code>true</code> if the container contains no components.
* <code>true</code> if the container contains no components.
* *
* @return <code>true</code> if this container contains no * * * @return <code>true</code> if this container contains no * * components; <code>false</code>
* components; <code>false</code> otherwise. * otherwise.
*/ */
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
@ -394,9 +377,8 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Returns the number of elements in this container. This does not * Returns the number of elements in this container. This does not recursively count the
* recursively count the components that are indirectly contained in * components that are indirectly contained in this container.
* this container.
* *
* @return the number of components directly in this container. * @return the number of components directly in this container.
*/ */
@ -411,8 +393,7 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Returns the panel that the * Returns the panel that the <code>Page</code> uses for rendering its components.
* <code>Page</code> uses for rendering its components.
* *
* @return the panel. * @return the panel.
*/ */
@ -421,9 +402,8 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Set the Container used for rendering components on this page. Caution * Set the Container used for rendering components on this page. Caution should be used with
* should be used with this function, as the existing container is * this function, as the existing container is simply overwritten.
* simply overwritten.
* *
* @author Matthew Booth (mbooth@redhat.com) * @author Matthew Booth (mbooth@redhat.com)
*/ */
@ -432,7 +412,8 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* <p> Retrieves the title of this page. </p> * <p>
* Retrieves the title of this page. </p>
* *
* @return the static title of this page. * @return the static title of this page.
*/ */
@ -444,6 +425,7 @@ public class Page extends BlockStylable implements Container {
* Retrieves the title of this page as a Bebop label component. * Retrieves the title of this page as a Bebop label component.
* *
* @param state the state of the current request * @param state the state of the current request
*
* @return the title of the page for the current request. * @return the title of the page for the current request.
*/ */
public final Label getTitle(PageState state) { public final Label getTitle(PageState state) {
@ -471,16 +453,15 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Sets the {@link Component} that will display the validation errors in * Sets the {@link Component} that will display the validation errors in the current
* the current {@link PageState}. Any validation error in the * {@link PageState}. Any validation error in the <code>PageState</code> will cause the
* <code>PageState</code> will cause the * <code>Page</code> to completely ignore all other components and render only the error display
* <code>Page</code> to completely ignore all other components and * component.
* render only the error display component. <p> By default, a * <p>
* {@link PageErrorDisplay} component is used to display the validation * By default, a {@link PageErrorDisplay} component is used to display the validation errors.
* errors.
* *
* @param c the component that will display the validation errors in the * @param c the component that will display the validation errors in the current
* current <code>PageState</code> * <code>PageState</code>
*/ */
public final void setErrorDisplay(Component c) { public final void setErrorDisplay(Component c) {
Assert.isUnlocked(this); Assert.isUnlocked(this);
@ -488,37 +469,37 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Gets the {@link Component} that will display the validation errors in * Gets the {@link Component} that will display the validation errors in the current
* the current {@link PageState}. Any validation error in the * {@link PageState}. Any validation error in the <code>PageState</code> will cause the
* <code>PageState</code> will cause the * <code>Page</code> to completely ignore all other components and render only the error display
* <code>Page</code> to completely ignore all other components and * component.
* render only the error display component. <p> By default, a * <p>
* {@link PageErrorDisplay} component is used to display the validation * By default, a {@link PageErrorDisplay} component is used to display the validation errors.
* errors.
* *
* @return the component that will display the validation errors in the * @return the component that will display the validation errors in the current
* current <code>PageState</code>. * <code>PageState</code>.
*/ */
public final Component getErrorDisplay() { public final Component getErrorDisplay() {
return m_errorDisplay; return m_errorDisplay;
} }
/** /**
* Adds a client-side stylesheet that should be used in HTML output. * Adds a client-side stylesheet that should be used in HTML output. Arbitrarily many
* Arbitrarily many client-side stylesheets can be added with this * client-side stylesheets can be added with this method. To use a CSS stylesheet, call
* method. To use a CSS stylesheet, call something like * something like <code>setStyleSheet("style.css", "text/css")</code>.
* <code>setStyleSheet("style.css", "text/css")</code>.
* *
* <p> These values will ultimately wind up in a <tt>&lt;link&gt;</tt> * <p>
* These values will ultimately wind up in a <tt>&lt;link&gt;</tt>
* tag in the head of the HTML page. * tag in the head of the HTML page.
* *
* <p> Note that the stylesheet set with this call has nothing to do * <p>
* with the XSLT stylesheet (transformer) that is applied to the XML * Note that the stylesheet set with this call has nothing to do with the XSLT stylesheet
* generated from this page! * (transformer) that is applied to the XML generated from this page!
* *
* @param styleSheetURI the location of the stylesheet * @param styleSheetURI the location of the stylesheet
* @param mimeType the MIME type of the stylesheet, usually * @param mimeType the MIME type of the stylesheet, usually
* <tt>text/css</tt> * <tt>text/css</tt>
*
* @pre ! isLocked() * @pre ! isLocked()
*/ */
public void addClientStylesheet(String styleSheetURI, String mimeType) { public void addClientStylesheet(String styleSheetURI, String mimeType) {
@ -526,14 +507,14 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Adds a global state parameter to this page. Global parameters are * Adds a global state parameter to this page. Global parameters are values that need to be
* values that need to be preserved between requests, but that have no * preserved between requests, but that have no special connection to any of the components on
* special connection to any of the components on the page. For a page * the page. For a page that displays details about an item, a global parameter would be used to
* that displays details about an item, a global parameter would be used * identify the item.
* to identify the item.
* *
* <p> If the parameter was previously added as a component state * <p>
* parameter, its name is unmangled and stays unmangled. * If the parameter was previously added as a component state parameter, its name is unmangled
* and stays unmangled.
* *
* @param p the global parameter to add * @param p the global parameter to add
* *
@ -549,8 +530,10 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Constructs the top nodes of the DOM or JDOM tree. Used by * Constructs the top nodes of the DOM or JDOM tree. Used by generateXML(PageState, Document)
* generateXML(PageState, Document) below. <p>Generates DOM fragment: * below.
* <p>
* Generates DOM fragment:
* <pre> * <pre>
* &lt;bebop:page> * &lt;bebop:page>
* &lt;bebop:title> ... value set with <i>setTitle</i> ... &lt;/bebop:title> * &lt;bebop:title> ... value set with <i>setTitle</i> ... &lt;/bebop:title>
@ -558,8 +541,7 @@ public class Page extends BlockStylable implements Container {
* ... page content gnerated by children ... * ... page content gnerated by children ...
* &lt;/bebop:page></pre> The content of the <tt>&lt;title&gt;</tt> * &lt;/bebop:page></pre> The content of the <tt>&lt;title&gt;</tt>
* element can be set by calling {@link #setTitle setTitle}. The * element can be set by calling {@link #setTitle setTitle}. The
* <tt>&lt;stylesheet&gt;</tt> element will only be present if a * <tt>&lt;stylesheet&gt;</tt> element will only be present if a stylesheet has been set with {@link
* stylesheet has been set with {@link
* #setStyleSheet setStyleSheet}. * #setStyleSheet setStyleSheet}.
* *
* @param ps the page state for the current page * @param ps the page state for the current page
@ -587,13 +569,13 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Constructs a DOM or JDOM tree with all components on the page. The * Constructs a DOM or JDOM tree with all components on the page. The tree represents the page
* tree represents the page that results from the * that results from the {@link javax.servlet.http.HttpServletRequest} kept in the
* {@link javax.servlet.http.HttpServletRequest} kept in the
* <code>state</code>. * <code>state</code>.
* *
* @param state the page state produced by {@link #process} * @param state the page state produced by {@link #process}
* @param parent the DOM node for the whole Document * @param parent the DOM node for the whole Document
*
* @see #process process * @see #process process
* @pre isLocked() * @pre isLocked()
* @pre state != null * @pre state != null
@ -617,8 +599,7 @@ public class Page extends BlockStylable implements Container {
if (Kernel.getConfig().isDebugEnabled() && debugStructure(state. if (Kernel.getConfig().isDebugEnabled() && debugStructure(state.
getRequest())) { getRequest())) {
Element structure = Element structure = page.newChildElement("bebop:structure", BEBOP_XML_NS);
page.newChildElement("bebop:structure", BEBOP_XML_NS);
showStructure(state, structure); showStructure(state, structure);
} }
@ -636,11 +617,11 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Creates a PageState object and processes it by calling the respond * Creates a PageState object and processes it by calling the respond method on the selected
* method on the selected component. Processes a request by notifying * component. Processes a request by notifying the component from which the process originated
* the component from which the process originated and {@link #fireActionEvent * and {@link #fireActionEvent
* broadcasts} an {@link ActionEvent} to all the listeners that * broadcasts} an {@link ActionEvent} to all the listeners that registered with
* registered with {@link #addActionListener addActionListener}. * {@link #addActionListener addActionListener}.
* *
* @see #generateXML(PageState,Document) generateXML * @see #generateXML(PageState,Document) generateXML
* @pre isLocked() * @pre isLocked()
@ -662,8 +643,8 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Processes the supplied PageState object according to this PageModel. * Processes the supplied PageState object according to this PageModel. Calls the respond method
* Calls the respond method on the selected Bebop component. * on the selected Bebop component.
*/ */
public void process(PageState state) throws ServletException { public void process(PageState state) throws ServletException {
Assert.isLocked(this); Assert.isLocked(this);
@ -708,13 +689,12 @@ public class Page extends BlockStylable implements Container {
// return state; // return state;
// } // }
/** /**
* Builds a DOM Document from the current request state by doing a * Builds a DOM Document from the current request state by doing a depth-first tree walk on the
* depth-first tree walk on the current set of components in this Page, * current set of components in this Page, calling generateXML on each. Does NOT do the
* calling generateXML on each. Does NOT do the rendering. If the HTTP * rendering. If the HTTP response has already been committed, does not build the XML document.
* response has already been committed, does not build the XML document. *
* @return a DOM ready for rendering, or null if the response has already been committed.
* *
* @return a DOM ready for rendering, or null if the response has
* already been committed.
* @post res.isCommitted() == (return == null) * @post res.isCommitted() == (return == null)
*/ */
public Document buildDocument(HttpServletRequest req, public Document buildDocument(HttpServletRequest req,
@ -745,9 +725,8 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Finishes building the page. The tree of components is traversed and * Finishes building the page. The tree of components is traversed and each component is told to
* each component is told to add its state parameters to the page's * add its state parameters to the page's state model.
* state model.
* *
* @pre ! isLocked() * @pre ! isLocked()
*/ */
@ -761,6 +740,7 @@ public class Page extends BlockStylable implements Container {
addComponent(c); addComponent(c);
c.register(Page.this); c.register(Page.this);
} }
}; };
if (m_panel == null) { if (m_panel == null) {
s_log.warn("m_panel is null"); s_log.warn("m_panel is null");
@ -778,8 +758,8 @@ public class Page extends BlockStylable implements Container {
/** /**
* Locks the page and all its components against further modifications. * Locks the page and all its components against further modifications.
* *
* <p>Locking a page helps in finding mistakes that result from * <p>
* modifying a page's structure.</P> * Locking a page helps in finding mistakes that result from modifying a page's structure.</P>
*/ */
@Override @Override
public void lock() { public void lock() {
@ -792,6 +772,7 @@ public class Page extends BlockStylable implements Container {
protected void act(Component c) { protected void act(Component c) {
c.lock(); c.lock();
} }
}; };
componentLocker.preorder(m_panel); componentLocker.preorder(m_panel);
@ -805,8 +786,8 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Registers a listener that is notified whenever a request to this page * Registers a listener that is notified whenever a request to this page is made, after the
* is made, after the selected component has had a chance to respond. * selected component has had a chance to respond.
* *
* @pre l != null * @pre l != null
* @pre ! isLocked() * @pre ! isLocked()
@ -828,8 +809,8 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Registers a listener that is notified whenever a request to this page * Registers a listener that is notified whenever a request to this page is made, before the
* is made, before the selected component has had a chance to respond. * selected component has had a chance to respond.
* *
* @pre l != null * @pre l != null
* @pre ! isLocked() * @pre ! isLocked()
@ -843,6 +824,7 @@ public class Page extends BlockStylable implements Container {
* Removes a previously registered request listener. * Removes a previously registered request listener.
* *
* @param 1 the listener to remove * @param 1 the listener to remove
*
* @pre l != null * @pre l != null
* @pre ! isLocked() * @pre ! isLocked()
*/ */
@ -852,9 +834,9 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Broadcasts an {@link ActionEvent} to all registered listeners. The * Broadcasts an {@link ActionEvent} to all registered listeners. The source of the event is
* source of the event is this page, and the state recorded in the event * this page, and the state recorded in the event is the one resulting from processing the
* is the one resulting from processing the current request. * current request.
* *
* @param the state for this event * @param the state for this event
* *
@ -879,9 +861,9 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Broadcasts a {@link RequestEvent} to all registered listeners. The * Broadcasts a {@link RequestEvent} to all registered listeners. The source of the event is
* source of the event is this page, and the state recorded in the event * this page, and the state recorded in the event is the one resulting from processing the
* is the one resulting from processing the current request. * current request.
* *
* @param state the state for this event * @param state the state for this event
* *
@ -906,9 +888,9 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Export page generator information if set. The m_pageGenerator is a * Export page generator information if set. The m_pageGenerator is a HashMap containing the
* HashMap containing the information as key value. In general this * information as key value. In general this should include generator name and generator
* should include generator name and generator version. * version.
* *
* @param page parent element - should be bebeop:page * @param page parent element - should be bebeop:page
* *
@ -946,6 +928,7 @@ public class Page extends BlockStylable implements Container {
style.addAttribute("type", m_type); style.addAttribute("type", m_type);
} }
} }
} }
/** /**
@ -962,6 +945,7 @@ public class Page extends BlockStylable implements Container {
} /*else { } /*else {
s_log.error("c: " + c.toString()); s_log.error("c: " + c.toString());
}*/ }*/
String key = c.getKey(); String key = c.getKey();
if (key == null) { if (key == null) {
key = Integer.toString(m_components.size()); key = Integer.toString(m_components.size());
@ -977,12 +961,10 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Registers a state parameter for a component. It is permissible to * Registers a state parameter for a component. It is permissible to register the same state
* register the same state parameter several times, from the same or * parameter several times, from the same or different components. The name of the parameter
* different components. The name of the parameter will be changed to * will be changed to ensure that it won't clash with any other component's parameter. If the
* ensure that it won't clash with any other component's parameter. If * parameter is added more than once, the name is only changed the first time it is added.
* the parameter is added more than once, the name is only changed the
* first time it is added.
* *
* @param c the component to register the parameter for * @param c the component to register the parameter for
* @param p the state parameter to register * @param p the state parameter to register
@ -1017,24 +999,26 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* <p>Get the parameters registered for a given component.</p> * <p>
* Get the parameters registered for a given component.</p>
*/ */
public Collection getComponentParameters(Component c) { public Collection getComponentParameters(Component c) {
return (Collection) m_componentParameterMap.get(c); return (Collection) m_componentParameterMap.get(c);
} }
/** /**
* Gets the state index of a component. This is the number assigned to * Gets the state index of a component. This is the number assigned to the component in the
* the component in the register traveral * register traveral
* *
* @param c the component to search for * @param c the component to search for
* *
* @return the index in this list of the first occurrence of the * @return the index in this list of the first occurrence of the specified element, or -1 if
* specified element, or -1 if this list does not contain this element. * this list does not contain this element.
* *
* @pre c != null * @pre c != null
* @post contains(c) implies (return >= 0) && (return < size()) * @post contains(c) implies (return >= 0) && (return < size())
* @post !contains(c) implies return == -1 * @pos
* t !contains(c) implies return == -1
*/ */
public int stateIndex(Component c) { public int stateIndex(Component c) {
return m_components.indexOf(c); return m_components.indexOf(c);
@ -1062,7 +1046,8 @@ public class Page extends BlockStylable implements Container {
* Gets a page component by index. * Gets a page component by index.
* *
* @pre (i >= 0) && (i < size()) * @pre (i >= 0) && (i < size())
* @post return != null * @pos
* t return != null
*/ */
public Component getComponent(int i) { public Component getComponent(int i) {
return (Component) m_components.get(i); return (Component) m_components.get(i);
@ -1078,8 +1063,7 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Gets the form model that contains the parameters for the page's * Gets the form model that contains the parameters for the page's state.
* state.
*/ */
public final FormModel getStateModel() { public final FormModel getStateModel() {
return m_stateModel; return m_stateModel;
@ -1095,12 +1079,13 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Checks whether the specified component is visible by default on the * Checks whether the specified component is visible by default on the page.
* page.
* *
* @param c a component contained in the page * @param c a component contained in the page
* @return <code>true</code> if the component is visible by default; *
* <code>false</code> otherwise. * @return <code>true</code> if the component is visible by default; <code>false</code>
* otherwise.
*
* @see #setVisibleDefault setVisibleDefault * @see #setVisibleDefault setVisibleDefault
* @see Component#setVisible Component.setVisible * @see Component#setVisible Component.setVisible
*/ */
@ -1111,17 +1096,17 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* Sets whether the specified component is visible by default. The * Sets whether the specified component is visible by default. The default visibility is used
* default visibility is used when a page is displayed for the first * when a page is displayed for the first time and on subsequent requests until the visibility
* time and on subsequent requests until the visibility of a component * of a component is changed explicitly with {@link Component#setVisible
* is changed explicitly with {@link Component#setVisible
* Component.setVisible}. * Component.setVisible}.
* *
* <p> When a component is first added to a page, it is visible. * <p>
* When a component is first added to a page, it is visible.
* *
* @param c a component whose visibility is to be set * @param c a component whose visibility is to be set
* @param v <code>true</code> if the component is visible; * @param v <code>true</code> if the component is visible; <code>false</code> otherwise.
* <code>false</code> otherwise. *
* @see Component#setVisible Component.setVisible * @see Component#setVisible Component.setVisible
* @see Component#register Component.register * @see Component#register Component.register
*/ */
@ -1138,9 +1123,7 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* The global name of the parameter * The global name of the parameter <code>name</code> in the component <code>c</code>.
* <code>name</code> in the component
* <code>c</code>.
*/ */
public String parameterName(Component c, String name) { public String parameterName(Component c, String name) {
if (c == null || !stateContains(c)) { if (c == null || !stateContains(c)) {
@ -1151,8 +1134,7 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* The global name of the parameter * The global name of the parameter <code>name</code>.
* <code>name</code>.
*/ */
public String parameterName(String name) { public String parameterName(String name) {
return parameterName(null, name); return parameterName(null, name);
@ -1172,13 +1154,13 @@ public class Page extends BlockStylable implements Container {
} }
c.setVisible(ps, isVisibleDefault(c)); c.setVisible(ps, isVisibleDefault(c));
} }
}; };
resetter.preorder(cmpnt); resetter.preorder(cmpnt);
} }
/** /**
* Return the prefix that is prepended to each component's state * Return the prefix that is prepended to each component's state parameters to keep them unique.
* parameters to keep them unique.
*/ */
private final String componentPrefix(Component c) { private final String componentPrefix(Component c) {
if (c == null) { if (c == null) {
@ -1204,6 +1186,7 @@ public class Page extends BlockStylable implements Container {
* Undo the name change that {@link #parameterName} does. * Undo the name change that {@link #parameterName} does.
* *
* @param name a possibly mangled name * @param name a possibly mangled name
*
* @return the unmangled name. * @return the unmangled name.
*/ */
private static final String unmangle(String name) { private static final String unmangle(String name) {
@ -1217,6 +1200,7 @@ public class Page extends BlockStylable implements Container {
} }
return name; return name;
} }
// Procs for debugging output // Procs for debugging output
private static String NAME = "name"; private static String NAME = "name";
@ -1234,23 +1218,19 @@ public class Page extends BlockStylable implements Container {
selected.setText(sel); selected.setText(sel);
// Control event // Control event
Element eventName = Element eventName = state.newChildElement("bebop:eventName", BEBOP_XML_NS);
state.newChildElement("bebop:eventName", BEBOP_XML_NS);
eventName.addAttribute(NAME, m_controlEvent.getName()); eventName.addAttribute(NAME, m_controlEvent.getName());
eventName.setText(req.getParameter(m_controlEvent.getName())); eventName.setText(req.getParameter(m_controlEvent.getName()));
Element eventValue = Element eventValue = state.newChildElement("bebop:eventValue", BEBOP_XML_NS);
state.newChildElement("bebop:eventValue", BEBOP_XML_NS);
eventValue.addAttribute(NAME, m_controlValue.getName()); eventValue.addAttribute(NAME, m_controlValue.getName());
eventValue.setText(req.getParameter(m_controlValue.getName())); eventValue.setText(req.getParameter(m_controlValue.getName()));
// Global parameters // Global parameters
Element globalState = Element globalState = root.newChildElement("bebop:params", BEBOP_XML_NS);
root.newChildElement("bebop:params", BEBOP_XML_NS);
for (Iterator ii = getStateModel().getParameters(); ii.hasNext();) { for (Iterator ii = getStateModel().getParameters(); ii.hasNext();) {
ParameterModel p = (ParameterModel) ii.next(); ParameterModel p = (ParameterModel) ii.next();
if (!p.getName().startsWith(COMPONENT_PREFIX)) { if (!p.getName().startsWith(COMPONENT_PREFIX)) {
Element param = Element param = globalState.newChildElement("bebop:param", BEBOP_XML_NS);
globalState.newChildElement("bebop:param", BEBOP_XML_NS);
param.addAttribute(NAME, p.getName()); param.addAttribute(NAME, p.getName());
param.setText(String.valueOf(s.getValue(p))); param.setText(String.valueOf(s.getValue(p)));
} }
@ -1279,8 +1259,7 @@ public class Page extends BlockStylable implements Container {
continue; continue;
} }
Element param = Element param = parent.newChildElement("bebop:param", BEBOP_XML_NS);
parent.newChildElement("bebop:param", BEBOP_XML_NS);
param.addAttribute(NAME, unmangle(p.getName())); param.addAttribute(NAME, unmangle(p.getName()));
param.addAttribute("defaultValue", param.addAttribute("defaultValue",
String.valueOf(req.getParameter(p.getName()))); String.valueOf(req.getParameter(p.getName())));
@ -1302,9 +1281,9 @@ public class Page extends BlockStylable implements Container {
} }
/** /**
* return a string that represents an ordered list of component ids used * return a string that represents an ordered list of component ids used on the page. For
* on the page. For situations where only the components present is of * situations where only the components present is of importance, this may be used by
* importance, this may be used by implementations of hashCode & equals * implementations of hashCode & equals
* *
* @return * @return
*/ */
@ -1328,6 +1307,6 @@ public class Page extends BlockStylable implements Container {
getTime())); getTime()));
return hashString.toString(); return hashString.toString();
} }
} }

View File

@ -190,7 +190,7 @@ public class Initializer extends CompoundInitializer {
}); });
// Set system informations // Set system informations
loadSystemInformation(); // loadSystemInformation();
// register the document converters // register the document converters
Converter converter = new PDFConverter(); Converter converter = new PDFConverter();
@ -229,14 +229,14 @@ public class Initializer extends CompoundInitializer {
s_log.info("Core init(DomainInitEvent) done"); s_log.info("Core init(DomainInitEvent) done");
} }
private void loadSystemInformation() { // private void loadSystemInformation() {
SystemInformation sysInfo = SystemInformation.getInstance(); // SystemInformation sysInfo = SystemInformation.getInstance();
//
// Hardcoded for now // // Hardcoded for now
sysInfo.put("version", "v2.1.0"); // sysInfo.put("version", "v2.3.x-SNAPSHOT");
sysInfo.put("appname", "ScientificCMS"); // sysInfo.put("appname", "ScientificCMS");
sysInfo.put("apphomepage", "http://www.scientificcms.org"); // sysInfo.put("apphomepage", "http://www.scientificcms.org");
sysInfo.lock(); // sysInfo.lock();
} // }
} }

View File

@ -2,34 +2,42 @@ waf.debug.title=Global debug flag
waf.debug.purpose=Enables or disables WAF debugging waf.debug.purpose=Enables or disables WAF debugging
waf.debug.example=true waf.debug.example=true
waf.debug.format=true|false waf.debug.format=true|false
waf.kernel.data_permission_check_enabled.title=DML permission checking flag waf.kernel.data_permission_check_enabled.title=DML permission checking flag
waf.kernel.data_permission_check_enabled.purpose=Enables or disables permissions checks on database writes waf.kernel.data_permission_check_enabled.purpose=Enables or disables permissions checks on database writes
waf.kernel.data_permission_check_enabled.example=true waf.kernel.data_permission_check_enabled.example=true
waf.kernel.data_permission_check_enabled.format=true|false waf.kernel.data_permission_check_enabled.format=true|false
waf.kernel.primary_user_identifier.title=The primary user identification waf.kernel.primary_user_identifier.title=The primary user identification
waf.kernel.primary_user_identifier.purpose=Determines whether email addresses or screen names are used to authenticate users waf.kernel.primary_user_identifier.purpose=Determines whether email addresses or screen names are used to authenticate users
waf.kernel.primary_user_identifier.example=email waf.kernel.primary_user_identifier.example=email
waf.kernel.primary_user_identifier.format=email|screen_name waf.kernel.primary_user_identifier.format=email|screen_name
waf.kernel.remember_login.title=Remember login by default waf.kernel.remember_login.title=Remember login by default
waf.kernel.remember_login.purpose=Determines whether the "remember login" feature is enabled or disabled by default waf.kernel.remember_login.purpose=Determines whether the "remember login" feature is enabled or disabled by default
waf.kernel.remember_login.example=true waf.kernel.remember_login.example=true
waf.kernel.remember_login.format=true|false waf.kernel.remember_login.format=true|false
waf.kernel.secure_login.title=Require secure login waf.kernel.secure_login.title=Require secure login
waf.kernel.secure_login.purpose=Accept only credentials presented over secure connection waf.kernel.secure_login.purpose=Accept only credentials presented over secure connection
waf.kernel.secure_login.example=true waf.kernel.secure_login.example=true
waf.kernel.secure_login.format=true|false waf.kernel.secure_login.format=true|false
waf.kernel.sso_login.title=Enable SSO login waf.kernel.sso_login.title=Enable SSO login
waf.kernel.sso_login.purpose=Enable alternative "RegisterSSO" login context. waf.kernel.sso_login.purpose=Enable alternative "RegisterSSO" login context.
waf.kernel.sso_login.example=false waf.kernel.sso_login.example=false
waf.kernel.sso_login.format=true|false waf.kernel.sso_login.format=true|false
waf.kernel.supported_languages.title=Set the supported languages for categorization waf.kernel.supported_languages.title=Set the supported languages for categorization
waf.kernel.supported_languages.purpose=Set the supported languages for categorization. First entry is the default language waf.kernel.supported_languages.purpose=Set the supported languages for categorization. First entry is the default language
waf.kernel.supported_languages.example=en,de,fr,nl,it,pt,es waf.kernel.supported_languages.example=en,de,fr,nl,it,pt,es
waf.kernel.supported_languages.format=[string] waf.kernel.supported_languages.format=[string]
waf.kernel.language_independent_items.title=Allow language independent content items waf.kernel.language_independent_items.title=Allow language independent content items
waf.kernel.language_independent_items.purpose=Allow language independent content items waf.kernel.language_independent_items.purpose=Allow language independent content items
waf.kernel.language_independent_items.example=false waf.kernel.language_independent_items.example=false
waf.kernel.language_independent_items.format=true|false waf.kernel.language_independent_items.format=true|false
waf.kernel.language_independent_code.title=Select language independent code waf.kernel.language_independent_code.title=Select language independent code
waf.kernel.language_independent_code.purpose=Allow language independent code waf.kernel.language_independent_code.purpose=Allow language independent code
waf.kernel.language_independent_code.example=-- waf.kernel.language_independent_code.example=--

View File

@ -4,63 +4,84 @@
*/ */
package com.arsdigita.util; package com.arsdigita.util;
import com.arsdigita.runtime.AbstractConfig;
import com.arsdigita.util.parameter.Parameter;
import com.arsdigita.util.parameter.StringParameter;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* *
* @author Sören Bernstein <quasi@quasiweb.de> * @author Sören Bernstein <quasi@quasiweb.de>
* @author Jens Pelzetter
*/ */
public class SystemInformation implements Lockable { public class SystemInformation extends AbstractConfig { //implements Lockable {
private Map<String, String> systemInformation = new HashMap<String, String>(); private Parameter sysInfoParam = new StringParameter(
private boolean locked = false; "ccm.systeminformation",
Parameter.REQUIRED,
"version::2.x.y; appname::LibreCCM; apphomepage::http://www.libreccm.org;");
private Map<String, String> systemInformation;// = new HashMap<String, String>();
//private boolean locked = false;
/** /**
* The one and only instance of this class * The one and only instance of this class
*/ */
private static final SystemInformation INSTANCE = new SystemInformation(); private static SystemInformation INSTANCE;// = new SystemInformation();
private SystemInformation() { public SystemInformation() {
// Nothing register(sysInfoParam);
loadInfo();
} }
/** /**
* @return The instance of this class. * @return The instance of this class.
*/ */
public static SystemInformation getInstance() { public static SystemInformation getInstance() {
return SystemInformation.INSTANCE; if (INSTANCE == null) {
INSTANCE = new SystemInformation();
INSTANCE.load();
} }
/** return INSTANCE;
* Put system information into the map. If this instance is locked, this method
* throw an {@link AssertionError}.
*
* @param key Key for the Map. Also used as attribute name during output.
* @param value Value
* @throws IllegalArgumentException if key or value is null or empty
*/
final public void put(String key, String value) throws IllegalArgumentException {
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Parameter key must not be null or empty.");
}
if (value == null || value.isEmpty()) {
throw new IllegalArgumentException("Parameter value must not be null or empty.");
}
// Test if instance is not locked
Assert.isUnlocked(this);
systemInformation.put(key, value);
} }
// /**
// * Put system information into the map. If this instance is locked, this method throw an
// * {@link AssertionError}.
// *
// * @param key Key for the Map. Also used as attribute name during output.
// * @param value Value
// *
// * @throws IllegalArgumentException if key or value is null or empty
// */
// final public void put(final String key, final String value) throws IllegalArgumentException {
// if (key == null || key.isEmpty()) {
// throw new IllegalArgumentException("Parameter key must not be null or empty.");
// }
// if (value == null || value.isEmpty()) {
// throw new IllegalArgumentException("Parameter value must not be null or empty.");
// }
// // Test if instance is not locked
// Assert.isUnlocked(this);
// systemInformation.put(key, value);
// }
/** /**
* Get system informations by key. * Get system informations by key.
* *
* @param key Key for the map * @param key Key for the map
*
* @return value for key * @return value for key
*
* @throws IllegalArgumentException if key is null or empty * @throws IllegalArgumentException if key is null or empty
*/ */
final public String get(String key) throws IllegalArgumentException { final public String get(String key) throws IllegalArgumentException {
if (systemInformation == null) {
loadMap();
}
if (key == null || key.isEmpty()) { if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Parameter key must not be null or empty."); throw new IllegalArgumentException("Parameter key must not be null or empty.");
} }
@ -73,7 +94,11 @@ public class SystemInformation implements Lockable {
* @return iterator of map * @return iterator of map
*/ */
final public Iterator<Map.Entry<String, String>> iterator() { final public Iterator<Map.Entry<String, String>> iterator() {
return ((Set<Map.Entry<String, String>>) systemInformation.entrySet()).iterator(); if (systemInformation == null) {
loadMap();
}
return (systemInformation.entrySet()).iterator();
} }
/** /**
@ -81,20 +106,43 @@ public class SystemInformation implements Lockable {
* @return * @return
*/ */
final public boolean isEmpty() { final public boolean isEmpty() {
return systemInformation.isEmpty(); if (systemInformation == null) {
loadMap();
} }
/**
* Lock this instance to prevent further changes. return systemInformation.isEmpty();
*/
final public void lock() {
locked = true;
} }
/** /**
* Test, if this instance is locked. * Lock this instance to prevent further changes.
* @return locked
*/ */
final public boolean isLocked() { // final public void lock() {
return locked; // locked = true;
// }
//
// /**
// * Test, if this instance is locked.
// *
// * @return locked
// */
// final public boolean isLocked() {
// return locked;
// }
private void loadMap() {
systemInformation = new HashMap<String, String>();
final String[] tokens = ((String) get(sysInfoParam)).split(";");
for (String token : tokens) {
processToken(token);
} }
}
private void processToken(final String token) {
final String[] parts = token.split("::");
if (2 == parts.length) {
systemInformation.put(parts[0].trim(), parts[1].trim());
}
}
} }

View File

@ -2,7 +2,7 @@
<ccm:application xmlns:ccm="http://ccm.redhat.com/ccm-project" <ccm:application xmlns:ccm="http://ccm.redhat.com/ccm-project"
name="ccm-sci-publications" name="ccm-sci-publications"
prettyName="OpenCCM Content Types" prettyName="OpenCCM Content Types"
version="6.6.6" version="6.6.7"
release="1" release="1"
webapp="ROOT"> webapp="ROOT">
<ccm:dependencies> <ccm:dependencies>

View File

@ -26,8 +26,8 @@ import com.arsdigita.cms.ContentBundle;
object type Publication extends ContentPage { object type Publication extends ContentPage {
Integer[0..1] yearOfPublication = ct_publications.year INTEGER; Integer[0..1] yearOfPublication = ct_publications.year INTEGER;
String[0..1] abstract = ct_publications.abstract VARCHAR(4096); String[0..1] abstract = ct_publications.abstract CLOB;
String[0..1] misc = ct_publications.misc VARCHAR(4096); String[0..1] misc = ct_publications.misc CLOB;
//The reviewed property has been moved here for performance reasons. It //The reviewed property has been moved here for performance reasons. It
//is necessary to have access to this property from a data query //is necessary to have access to this property from a data query
//over all publications of a person. Since this property was only //over all publications of a person. Since this property was only

View File

@ -0,0 +1,3 @@
-- Alter abstract and misc column type to text
ALTER TABLE ct_publications ALTER COLUMN abstract TYPE text;
ALTER TABLE ct_publications ALTER COLUMN misc TYPE text;

View File

@ -0,0 +1,8 @@
\echo 'ScientificCMS Publications module 6.6.6 -> 6.6.7 Upgrade script (PostgreSQL)'
begin;
\i ../default/upgrade/6.6.6-6.6.7/abstract_to_text.sql
end;

View File

@ -18,4 +18,7 @@
<version from="6.6.5" to="6.6.6"> <version from="6.6.5" to="6.6.6">
<script class="com.arsdigita.cms.contenttypes.upgrades.SciPublicationsUpgrade665to666"/> <script class="com.arsdigita.cms.contenttypes.upgrades.SciPublicationsUpgrade665to666"/>
</version> </version>
<version from="6.6.6" to="6.6.7">
<script sql="ccm-sci-publications/upgrade/::database::-6.6.6-6.6.7.sql" />
</version>
</upgrade> </upgrade>

View File

@ -74,64 +74,56 @@ public class PublicationsConfig extends AbstractConfig {
private final Parameter orgaBundleType; private final Parameter orgaBundleType;
private final Parameter enableFirstPublishedProperty; private final Parameter enableFirstPublishedProperty;
private final Parameter enableLanguageProperty; private final Parameter enableLanguageProperty;
private final Parameter enableAbstractHTML;
private final Parameter enableMiscHTML;
public PublicationsConfig() { public PublicationsConfig() {
attachOrgaUnitsStep = attachOrgaUnitsStep = new BooleanParameter(
new BooleanParameter(
"com.arsdigita.cms.contenttypes.publications.attach_orgaunits_step", "com.arsdigita.cms.contenttypes.publications.attach_orgaunits_step",
Parameter.REQUIRED, Parameter.REQUIRED,
Boolean.FALSE); Boolean.FALSE);
orgaUnitsStepSortKey = orgaUnitsStepSortKey = new IntegerParameter(
new IntegerParameter(
"com.arsdigita.cms.contenttypes.publications.orgaunits_step_sort_key", "com.arsdigita.cms.contenttypes.publications.orgaunits_step_sort_key",
Parameter.REQUIRED, Parameter.REQUIRED,
10); 10);
attachOrganizationPublicationsStepTo = attachOrganizationPublicationsStepTo = new StringParameter(
new StringParameter(
"com.arsdigita.cms.contenttypes.publications.attach_organization_publications_step_to", "com.arsdigita.cms.contenttypes.publications.attach_organization_publications_step_to",
Parameter.REQUIRED, Parameter.REQUIRED,
""); "");
organizationPublicationsStepSortKey = organizationPublicationsStepSortKey = new IntegerParameter(
new IntegerParameter(
"com.arsdigita.cms.contenttypes.publications.organization_publications_step_sort_key", "com.arsdigita.cms.contenttypes.publications.organization_publications_step_sort_key",
Parameter.REQUIRED, Parameter.REQUIRED,
10); 10);
attachPersonPublicationsStep = attachPersonPublicationsStep = new BooleanParameter(
new BooleanParameter(
"com.arsdigita.cms.contenttypes.publications.attach_person_publications_step", "com.arsdigita.cms.contenttypes.publications.attach_person_publications_step",
Parameter.REQUIRED, Parameter.REQUIRED,
Boolean.TRUE); Boolean.TRUE);
personPublicationsStepSortKey = personPublicationsStepSortKey = new IntegerParameter(
new IntegerParameter(
"com.arsdigita.cms.contenttypes.publications.person_publications_step_sort_key", "com.arsdigita.cms.contenttypes.publications.person_publications_step_sort_key",
Parameter.REQUIRED, Parameter.REQUIRED,
10); 10);
attachPublicationsStepTo = attachPublicationsStepTo = new StringParameter(
new StringParameter(
"com.arsdigita.cms.contenttypes.publications.attach_publications_step_to", "com.arsdigita.cms.contenttypes.publications.attach_publications_step_to",
Parameter.REQUIRED, Parameter.REQUIRED,
""); "");
publicationsStepSortKey = publicationsStepSortKey = new IntegerParameter(
new IntegerParameter(
"com.arsdigita.cms.contenttypes.publications.publications_step_sort_key", "com.arsdigita.cms.contenttypes.publications.publications_step_sort_key",
Parameter.REQUIRED, Parameter.REQUIRED,
11); 11);
attachPublisherPublicationsStep = attachPublisherPublicationsStep = new BooleanParameter(
new BooleanParameter(
"com.arsdigita.cms.contenttypes.publications.attach_publisher_publications_step", "com.arsdigita.cms.contenttypes.publications.attach_publisher_publications_step",
Parameter.REQUIRED, Parameter.REQUIRED,
Boolean.TRUE); Boolean.TRUE);
publisherPublicationsStepSortKey = publisherPublicationsStepSortKey = new IntegerParameter(
new IntegerParameter(
"com.arsdigita.cms.contenttypes.publications.publisher_publications_step_sort_key", "com.arsdigita.cms.contenttypes.publications.publisher_publications_step_sort_key",
Parameter.REQUIRED, Parameter.REQUIRED,
10); 10);
@ -270,6 +262,16 @@ public class PublicationsConfig extends AbstractConfig {
Parameter.REQUIRED, Parameter.REQUIRED,
true); true);
enableAbstractHTML = new BooleanParameter(
"com.arsdigita.cms.contenttypes.publications.enable_abstract_html",
Parameter.REQUIRED,
false);
enableMiscHTML = new BooleanParameter(
"com.arsdigita.cms.contenttypes.publications.enable_misc_html",
Parameter.REQUIRED,
false);
register(attachOrgaUnitsStep); register(attachOrgaUnitsStep);
register(orgaUnitsStepSortKey); register(orgaUnitsStepSortKey);
register(attachOrganizationPublicationsStepTo); register(attachOrganizationPublicationsStepTo);
@ -307,6 +309,8 @@ public class PublicationsConfig extends AbstractConfig {
register(orgaBundleType); register(orgaBundleType);
register(enableFirstPublishedProperty); register(enableFirstPublishedProperty);
register(enableLanguageProperty); register(enableLanguageProperty);
register(enableAbstractHTML);
register(enableMiscHTML);
loadInfo(); loadInfo();
} }
@ -329,6 +333,7 @@ public class PublicationsConfig extends AbstractConfig {
* *
* @param folderPath Path of the default folder. * @param folderPath Path of the default folder.
* @param folderId ID of the default folder. * @param folderId ID of the default folder.
*
* @return * @return
*/ */
private Folder getDefaultFolder(final String folderPath, final Integer folderId) { private Folder getDefaultFolder(final String folderPath, final Integer folderId) {
@ -435,7 +440,8 @@ public class PublicationsConfig extends AbstractConfig {
* the next releases. Instead the path property should be used. * the next releases. Instead the path property should be used.
* *
* @return {@code null} if {@link #getDefaultAuthorsFolderPath()} and * @return {@code null} if {@link #getDefaultAuthorsFolderPath()} and
* {@link #getDefaultAuthorsFolderID()} both are not set, otherwise a {@link Folder} object. * {@link #getDefaultAuthorsFolderID()} both are not set, otherwise a {@link Folder}
* object.
*/ */
public Folder getDefaultAuthorsFolder() { public Folder getDefaultAuthorsFolder() {
return getDefaultFolder(getDefaultAuthorsFolderPath(), getDefaultAuthorsFolderID()); return getDefaultFolder(getDefaultAuthorsFolderPath(), getDefaultAuthorsFolderID());
@ -653,8 +659,7 @@ public class PublicationsConfig extends AbstractConfig {
/** /**
* *
* @return * @return @deprecated Use {@link getDefaultInProccedingsFolder}
* @deprecated Use {@link getDefaultInProccedingsFolder}
*/ */
@Deprecated @Deprecated
public Integer getDefaultInProceedingsFolderID() { public Integer getDefaultInProceedingsFolderID() {
@ -706,8 +711,7 @@ public class PublicationsConfig extends AbstractConfig {
/** /**
* *
* @return * @return @deprecated Use {@link #getDefaultPublicationsFolder() }
* @deprecated Use {@link #getDefaultPublicationsFolder() }
*/ */
@Deprecated @Deprecated
public Integer getDefaultPublicationsFolderID() { public Integer getDefaultPublicationsFolderID() {
@ -751,4 +755,12 @@ public class PublicationsConfig extends AbstractConfig {
return (Boolean) get(enableLanguageProperty); return (Boolean) get(enableLanguageProperty);
} }
public Boolean getEnableAbstractHTML() {
return (Boolean) get(enableAbstractHTML);
}
public Boolean getEnableMiscHTML() {
return (Boolean) get(enableMiscHTML);
}
} }

View File

@ -182,3 +182,13 @@ com.arsdigita.cms.contenttypes.publications.enable_language_property.title = Ena
com.arsdigita.cms.contenttypes.publications.enable_language_property.purpose = Enable language property com.arsdigita.cms.contenttypes.publications.enable_language_property.purpose = Enable language property
com.arsdigita.cms.contenttypes.publications.enable_language_property.example = true com.arsdigita.cms.contenttypes.publications.enable_language_property.example = true
com.arsdigita.cms.contenttypes.publications.enable_language_property.format = Boolean com.arsdigita.cms.contenttypes.publications.enable_language_property.format = Boolean
com.arsdigita.cms.contenttypes.publications.enable_abstract_html.title = Enable HTML editor for the abstract
com.arsdigita.cms.contenttypes.publications.enable_abstract_html.purpose = Enables or disables the HTML editor for the abstract
com.arsdigita.cms.contenttypes.publications.enable_abstract_html.example = true
com.arsdigita.cms.contenttypes.publications.enable_abstract_html.format = Boolean
com.arsdigita.cms.contenttypes.publications.enable_misc_html.title = Enable HTML editor for the misc field
com.arsdigita.cms.contenttypes.publications.enable_misc_html.purpose = Enables or disables the HTML editor for the misc field
com.arsdigita.cms.contenttypes.publications.enable_misc_html.example = true
com.arsdigita.cms.contenttypes.publications.enable_misc_html.format = Boolean

View File

@ -76,8 +76,8 @@ public class PublicationPropertiesStep extends SimpleEditStep {
Publication.YEAR_OF_PUBLICATION); Publication.YEAR_OF_PUBLICATION);
sheet.add(PublicationGlobalizationUtil.globalize( sheet.add(PublicationGlobalizationUtil.globalize(
"publications.ui.publication.abstract"), "publications.ui.publication.abstract"),
Publication.ABSTRACT, Publication.ABSTRACT);
new PreFormattedTextFormatter()); //new PreFormattedTextFormatter());
sheet.add(PublicationGlobalizationUtil.globalize( sheet.add(PublicationGlobalizationUtil.globalize(
"publications.ui.publication.misc"), "publications.ui.publication.misc"),
Publication.MISC); Publication.MISC);

View File

@ -36,6 +36,8 @@ import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.cms.ItemSelectionModel; import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.contenttypes.Publication; import com.arsdigita.cms.contenttypes.Publication;
import com.arsdigita.cms.contenttypes.PublicationsConfig;
import com.arsdigita.cms.ui.CMSDHTMLEditor;
import com.arsdigita.cms.ui.authoring.BasicPageForm; import com.arsdigita.cms.ui.authoring.BasicPageForm;
import com.arsdigita.globalization.GlobalizationHelper; import com.arsdigita.globalization.GlobalizationHelper;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
@ -58,6 +60,11 @@ public class PublicationPropertyForm
PublicationPropertyForm.class); PublicationPropertyForm.class);
private PublicationPropertiesStep m_step; private PublicationPropertiesStep m_step;
public static final String ID = "Publication_edit"; public static final String ID = "Publication_edit";
private final static PublicationsConfig config = new PublicationsConfig();
static {
config.load();
}
public PublicationPropertyForm(ItemSelectionModel itemModel) { public PublicationPropertyForm(ItemSelectionModel itemModel) {
this(itemModel, null); this(itemModel, null);
@ -76,19 +83,21 @@ public class PublicationPropertyForm
add(new Label(PublicationGlobalizationUtil.globalize( add(new Label(PublicationGlobalizationUtil.globalize(
"publications.ui.publication.year_of_publication"))); "publications.ui.publication.year_of_publication")));
final ParameterModel yearOfPublicationParam = new IntegerParameter(Publication.YEAR_OF_PUBLICATION); final ParameterModel yearOfPublicationParam = new IntegerParameter(
Publication.YEAR_OF_PUBLICATION);
final TextField yearOfPublication = new TextField(yearOfPublicationParam); final TextField yearOfPublication = new TextField(yearOfPublicationParam);
yearOfPublication.setMaxLength(4); yearOfPublication.setMaxLength(4);
//yearOfPublication.addValidationListener(new NotNullValidationListener()); //yearOfPublication.addValidationListener(new NotNullValidationListener());
//yearOfPublication.addValidationListener(new NotEmptyValidationListener()); //yearOfPublication.addValidationListener(new NotEmptyValidationListener());
add(yearOfPublication); add(yearOfPublication);
add(new Label(PublicationGlobalizationUtil.globalize("publications.ui.publication.first_published"))); add(new Label(PublicationGlobalizationUtil.globalize(
"publications.ui.publication.first_published")));
final ParameterModel firstPublishedParam = new IntegerParameter(Publication.FIRST_PUBLISHED); final ParameterModel firstPublishedParam = new IntegerParameter(Publication.FIRST_PUBLISHED);
final TextField firstPublished = new TextField(firstPublishedParam); final TextField firstPublished = new TextField(firstPublishedParam);
add(firstPublished); add(firstPublished);
add(new Label( PublicationGlobalizationUtil.globalize("publications.ui.publication.language"))); add(new Label(PublicationGlobalizationUtil.globalize("publications.ui.publication.language")));
final ParameterModel langParam = new StringParameter(Publication.LANG); final ParameterModel langParam = new StringParameter(Publication.LANG);
//final TextField lang = new TextField(langParam); //final TextField lang = new TextField(langParam);
final SingleSelect lang = new SingleSelect(langParam); final SingleSelect lang = new SingleSelect(langParam);
@ -101,7 +110,7 @@ public class PublicationPropertyForm
} }
}); });
for(Locale locale : locales) { for (Locale locale : locales) {
final Locale currentLocale = locale; final Locale currentLocale = locale;
final Label optionLabel = new Label(new PrintListener() { final Label optionLabel = new Label(new PrintListener() {
@ -109,25 +118,37 @@ public class PublicationPropertyForm
@Override @Override
public void prepare(final PrintEvent event) { public void prepare(final PrintEvent event) {
final Label target = (Label) event.getTarget(); final Label target = (Label) event.getTarget();
target.setLabel(currentLocale.getDisplayName(GlobalizationHelper.getNegotiatedLocale())); target.setLabel(currentLocale.getDisplayName(GlobalizationHelper.
getNegotiatedLocale()));
} }
}); });
lang.addOption(new Option(locale.toString(), optionLabel)); lang.addOption(new Option(locale.toString(), optionLabel));
} }
add(lang); add(lang);
add(new Label((String) PublicationGlobalizationUtil.globalize( add(new Label(PublicationGlobalizationUtil.globalize(
"publications.ui.publication.abstract").localize())); "publications.ui.publication.abstract")));
ParameterModel abstractParam = new StringParameter(Publication.ABSTRACT); ParameterModel abstractParam = new StringParameter(Publication.ABSTRACT);
TextArea abstractArea = new TextArea(abstractParam); TextArea abstractArea;
if (config.getEnableAbstractHTML()) {
abstractArea = new CMSDHTMLEditor(abstractParam);
} else {
abstractArea = new TextArea(abstractParam);
}
abstractArea.setCols(60); abstractArea.setCols(60);
abstractArea.setRows(18); abstractArea.setRows(18);
add(abstractArea); add(abstractArea);
add(new Label((String) PublicationGlobalizationUtil.globalize( add(new Label(PublicationGlobalizationUtil.globalize(
"publications.ui.publication.misc").localize())); "publications.ui.publication.misc")));
ParameterModel miscParam = new StringParameter(Publication.MISC); ParameterModel miscParam = new StringParameter(Publication.MISC);
TextArea misc = new TextArea(miscParam); TextArea misc;
if (config.getEnableMiscHTML()) {
misc = new CMSDHTMLEditor(miscParam);
} else {
misc = new TextArea(miscParam);
}
misc.setCols(60); misc.setCols(60);
misc.setRows(18); misc.setRows(18);
add(misc); add(misc);