/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.bebop;
import java.util.Collections;
import java.util.Iterator;
import com.arsdigita.bebop.util.Attributes;
import com.arsdigita.kernel.Kernel;
import com.arsdigita.util.Assert;
import com.arsdigita.xml.Element;
/**
* A simple implementation of the Component interface.
*
*
* @author David Lutterkort
* @author Stanislav Freidin
* @author Rory Solomon
* @author Uday Mathur
*
* @version $Id: SimpleComponent.java 1498 2007-03-19 16:22:15Z apevec $
*/
public class SimpleComponent extends Completable
implements Component, Cloneable {
private boolean m_locked;
/**
* The Attribute object is protected to make it easier for the Form Builder
* service to persist the SimpleComponent.
* Locking violation is not a problem since if the SimpleComponent is locked
* then the Attribute object will also be locked.
*/
protected Attributes m_attr;
private String m_key = null; // name mangling key
/**
* Clones a component. The clone is not locked and has its own set of
* attributes.
* @return the clone of a component.
* @post ! ((SimpleComponent) return).isLocked()
*/
@Override
public Object clone() throws CloneNotSupportedException {
SimpleComponent result = (SimpleComponent) super.clone();
if ( m_attr != null ) {
result.m_attr = (Attributes) m_attr.clone();
}
result.m_locked = false;
return result;
}
public void register(Page p) {
return;
}
public void register(Form f, FormModel m) {
return;
}
/**
* Does processing that is special to the component
* receiving the click.
* @param state the current page state
*/
public void respond(PageState state)
throws javax.servlet.ServletException { }
public Iterator children() {
return Collections.EMPTY_LIST.iterator();
}
/** Adds [J]DOM nodes for this component. Specifically for
* base class SimpleComponent, does nothing.
*/
public void generateXML(PageState state, Element p) {
return;
}
public final boolean isLocked() {
return m_locked;
}
public void lock () {
if (m_attr != null) {
m_attr.lock();
}
m_locked = true;
}
/**
* Unlocks this component. Package visibility is intentional; the
* only time a component should be unlocked is when it's pooled and
* gets locked because it's put into a page. It needs to be unlocked
* when the instance is recycled.
*/
void unlock() {
m_locked = false;
}
/* Working with standard component attributes */
/**
* Gets the class attribute.
* @return the class attribute.
*/
public String getClassAttr() {
return getAttribute(CLASS);
}
/**
* Sets the class attribute.
* @param theClass a valid XML name
*/
public void setClassAttr(String theClass) {
Assert.isUnlocked(this);
setAttribute(CLASS, theClass);
}
/**
* Gets the style attribute.
* @return the style attribute.
*/
public String getStyleAttr() {
return getAttribute(STYLE);
}
/**
* Sets the style attribute. style should be a valid CSS
* style, since its value will be copied verbatim to the output and
* appear as a style attribute in the top level XML or HTML
* output element.
*
* @param style a valid CSS style description for use in the
* style attribute of an HTML tag
* @see Standard Attributes
*/
public void setStyleAttr(String style) {
Assert.isUnlocked(this);
setAttribute(STYLE, style);
}
/**
* Gets the id attribute.
* @return the id attribute.
* @see #setIdAttr(String id)
*/
public String getIdAttr() {
return getAttribute(ID);
}
/**
* Sets the id attribute. id
* should be an XML name
* that is unique within the {@link Page Page} in which this component is
* contained. The value of id is copied literally to the
* output and not used for internal processing.
*
* @param id a valid XML identifier
* @see Standard Attributes
*/
public void setIdAttr(String id) {
Assert.isUnlocked(this);
setAttribute(ID, id);
}
/* Methods for attribute management */
/**
* Sets an attribute. Overwrites any old values. These values are used to
* generate attributes for the top level XML or HTML element that is
* output from this component with {@link #generateXML generateXML}.
*
* @pre name != null
* @post getAttribute(name) == value
*
* @param name attribute name, case insensitive
* @param value new attribute value
*/
final protected void setAttribute(String name, String value) {
Assert.isUnlocked(this);
if (m_attr == null) {
m_attr = new Attributes();
}
m_attr.setAttribute(name, value);
}
/**
* Gets the value of an attribute.
*
* @pre name != null
*
* @param name attribute name, case insensitive
* @return the string value previously set with {@link #setAttribute
* setAttribute}, or null if none was set.
* @see #setAttribute
*/
final protected String getAttribute(String name) {
return (m_attr == null) ? null : m_attr.getAttribute(name);
}
/**
* Adds the attributes set with {@link #setAttribute setAttribute} to the
* element target. The attributes set with
* exportAttributes overwrite attributes with identical names
* that target might already have.
*
* @pre target != null
*
* @param target element to which attributes are added
* @see #setAttribute
*/
final protected void exportAttributes(com.arsdigita.xml.Element target) {
if (m_attr != null) {
m_attr.exportAttributes(target);
}
if (Kernel.getConfig().isDebugEnabled() ||
Bebop.getConfig().showClassName()) {
target.addAttribute("bebop:classname", getClass().getName(),
BEBOP_XML_NS);
}
}
/**
* Returns true if any attributes have been set.
* @return true if any attributes have been set;
* false otherwise.
*/
final protected boolean hasAttributes() {
return m_attr != null;
}
/*
* Set an arbitrary meta data attribute on the component.
* The name of the attribute in the XML will be prefixed
* with the string 'metadata.'
*/
final public void setMetaDataAttribute(String name, String value) {
setAttribute("metadata." + name, value);
}
final public String getMetaDataAttribute(String name) {
return getAttribute("metadata." + name);
}
/**
* Supplies a key for parameter name mangling.
* @param key the key to mangle
*/
public Component setKey(String key) {
Assert.isUnlocked(this);
if (key.charAt(0) >= 0 && key.charAt(0) <= 9) {
throw new IllegalArgumentException("key \"" + key + "\" must not start with a digit.");
}
m_key = key;
return this;
}
/**
* Retrieves a key for parameter name mangling.
* @return a key for parameter name mangling.
*/
public final String getKey() {
return m_key;
}
public boolean isVisible(PageState s) {
return s.isVisible(this);
}
public void setVisible(PageState s, boolean v) {
s.setVisible(this, v);
}
}