001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.tags.databinding.datagrid;
020:
021: import javax.servlet.http.HttpServletRequest;
022: import javax.servlet.jsp.JspException;
023:
024: import org.apache.beehive.netui.tags.AbstractSimpleTag;
025: import org.apache.beehive.netui.tags.TagConfig;
026: import org.apache.beehive.netui.tags.javascript.ScriptRequestState;
027: import org.apache.beehive.netui.tags.html.Form;
028: import org.apache.beehive.netui.tags.rendering.AbstractHtmlState;
029: import org.apache.beehive.netui.tags.rendering.AbstractHtmlControlState;
030: import org.apache.beehive.netui.databinding.datagrid.api.rendering.DataGridTagModel;
031:
032: /**
033: * <p>
034: * This class is a base class for all data grid tags that render HTML output for the grid. This base
035: * class provides services to its subclasses including lookup of the {@link DataGridTagModel} for the
036: * current data grid. In addition, this class exposes tagId generation functionality. These methods
037: * are used to create strings that will be written onto HTML tags for the "id" or "name" attributes.
038: * Such identifiers can be created in one of two ways -- indexed or un-indexed. An un-indexed tag
039: * identifier is one that the page author is responsible for making unique within a given
040: * scope in the rendered output. An indexed tag identifier is one that the data grid will suffix
041: * with the index for the current row in the grid. This is used to help create unique identifiers
042: * from JSP tags that are rendered repeatedly. For example, a {@link SpanCell} renders an HTML
043: * <span> tag; with its <code>tagId</code> attribute set, it will render a tag identifier for
044: * every row in the page. The indexed is added as a suffix in order to help page authors create
045: * more unique identifiers. Ultimately, the page author is responsible for ensuring that their
046: * tag identifiers are unique within a scope.
047: * </p>
048: */
049: public abstract class AbstractDataGridHtmlTag extends AbstractSimpleTag {
050:
051: /**
052: * Get the {@link DataGridTagModel} for the data grid.
053: * @return the data grid tag model
054: */
055: protected final DataGridTagModel lookupDataGridTagModel() {
056: return DataGridUtil.getDataGridTagModel(getJspContext());
057: }
058:
059: /**
060: * Create an indexed tag identifier given a state object and a base tag identifier. The <code>tagId</code>
061: * will have the index of the current item in the data grid attached as a suffix to the
062: * the given base identifier.
063: * @param state the {@link AbstractHtmlState} upon which the tag identifier will be set once created
064: * @param tagId the base tag identifier name
065: * @throws JspException
066: */
067: protected final void applyIndexedTagId(AbstractHtmlState state,
068: String tagId) throws JspException {
069: state.id = indexTagId(generateTagId(tagId));
070: }
071:
072: /**
073: * Create an un-indexed tag identifier for the given state object.
074: * @param state the {@link AbstractHtmlState} upon which the tag identifier will be set once created
075: * @param tagId the base tag identifier
076: * @throws JspException
077: */
078: protected final void applyTagId(AbstractHtmlState state,
079: String tagId) throws JspException {
080: state.id = generateTagId(tagId);
081: }
082:
083: /**
084: * Generate a tag ID.
085: * @param tagId the tag id
086: * @return the generated tag id
087: * @throws JspException if an error occurs creating the value of the tag id attribute
088: */
089: private final String generateTagId(String tagId)
090: throws JspException {
091: return setRequiredValueAttribute(tagId, "tagId");
092: }
093:
094: /**
095: * Generate an indexed tag ID. This method will use the
096: * {@link org.apache.beehive.netui.databinding.datagrid.api.rendering.DataGridTagModel#getCurrentIndex()} method
097: * to scope a given name to a particular row in the data grid.
098: * @param tagId the base tag id
099: * @return an index-scoped tag id
100: */
101: private final String indexTagId(String tagId) {
102: DataGridTagModel dataGridTagModel = lookupDataGridTagModel();
103: assert dataGridTagModel != null;
104:
105: int index = dataGridTagModel.getCurrentIndex();
106: assert index >= 0;
107:
108: return tagId + index;
109: }
110:
111: /**
112: * <p>
113: * Generate a name and id given a {@link AbstractHtmlState} object. Data grid callers may invoke this
114: * method with subclasses rendering markup containing tags that must set HTML tag IDs for use
115: * via JavaScript on the client.
116: * <br/>
117: * Assumptions:
118: * <ul>
119: * <li>The state.name must be fully formed or the "real name" of the form.</li>
120: * <li>The state.id is the tagId value set on the tag and <b>has not</b> be rewritten yet to form the "real id"</li>
121: * </ul>
122: * </p>
123: * @param state the HTML state whose tag id to set
124: * @param parentForm a {@link Form} tag if one contains this tag
125: * @return String a block of JavaScript if script must e rendered to the page in order to support
126: * lookups of HTML elements using a tag id. If returned, the String <b>must</b> be rendered
127: * to the output stream. <code>null</code> if no script must be rendered.
128: */
129: protected final String renderNameAndId(HttpServletRequest request,
130: AbstractHtmlState state, Form parentForm) {
131: // if id is not set then we need to exit
132: if (state.id == null)
133: return null;
134:
135: // check to see if this is an instance of a HTML Control
136: boolean ctrlState = (state instanceof AbstractHtmlControlState);
137:
138: // form keeps track of this so that it can add this control to it's focus map
139: if (parentForm != null && ctrlState) {
140: AbstractHtmlControlState hcs = (AbstractHtmlControlState) state;
141: if (hcs.name == null && parentForm.isFocusSet())
142: hcs.name = state.id;
143: parentForm.addTagID(state.id,
144: ((AbstractHtmlControlState) state).name);
145: }
146:
147: // rewrite the id, save the original value so it can be used in maps
148: String id = state.id;
149: state.id = getIdForTagId(id);
150:
151: // Legacy Java Script support -- This writes out a single table with both the id and names
152: // mixed. This is legacy support to match the pre beehive behavior.
153: String idScript = null;
154: if (TagConfig.isLegacyJavaScript()) {
155: ScriptRequestState srs = ScriptRequestState
156: .getScriptRequestState(request);
157: if (!ctrlState) {
158: idScript = srs.mapLegacyTagId(getScriptReporter(), id,
159: state.id);
160: } else {
161: AbstractHtmlControlState cState = (AbstractHtmlControlState) state;
162: if (cState.name != null)
163: idScript = srs.mapLegacyTagId(getScriptReporter(),
164: id, cState.name);
165: else
166: idScript = srs.mapLegacyTagId(getScriptReporter(),
167: id, state.id);
168: }
169: }
170:
171: // map the tagId to the real id
172: String name = null;
173: if (ctrlState) {
174: AbstractHtmlControlState cState = (AbstractHtmlControlState) state;
175: name = cState.name;
176: }
177:
178: String script = renderDefaultNameAndId(
179: (HttpServletRequest) request, state, id, name);
180: if (script != null) {
181: if (idScript != null)
182: idScript = idScript + script;
183: else
184: idScript = script;
185: }
186: return idScript;
187: }
188:
189: protected String renderDefaultNameAndId(HttpServletRequest request,
190: AbstractHtmlState state, String id, String name) {
191: // map the tagId to the real id
192: String script = null;
193: if (TagConfig.isDefaultJavaScript()) {
194: ScriptRequestState srs = ScriptRequestState
195: .getScriptRequestState(request);
196: script = srs.mapTagId(getScriptReporter(), id, state.id,
197: name);
198: }
199: return script;
200: }
201: }
|