001: /*
002: * $Header: /export/home/cvsroot/MyPersonalizerRepository/MyPersonalizer/Subsystems/Portal/Sources/es/udc/mypersonalizer/portal/controller/actions/personalization/ChangeServicePropertyAction.java,v 1.1.1.1 2004/03/25 12:08:40 fbellas Exp $
003: * $Revision: 1.1.1.1 $
004: * $Date: 2004/03/25 12:08:40 $
005: *
006: * =============================================================================
007: *
008: * Copyright (c) 2003, The MyPersonalizer Development Group
009: * (http://www.tic.udc.es/~fbellas/mypersonalizer/index.html) at
010: * University Of A Coruna
011: * All rights reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions are met:
015: *
016: * - Redistributions of source code must retain the above copyright notice,
017: * this list of conditions and the following disclaimer.
018: *
019: * - Redistributions in binary form must reproduce the above copyright notice,
020: * this list of conditions and the following disclaimer in the documentation
021: * and/or other materials provided with the distribution.
022: *
023: * - Neither the name of the University Of A Coruna nor the names of its
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
028: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
029: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
030: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
031: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
032: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
033: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
034: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
035: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
036: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
037: * POSSIBILITY OF SUCH DAMAGE.
038: *
039: */
040:
041: package es.udc.mypersonalizer.portal.controller.actions.personalization;
042:
043: import es.udc.mypersonalizer.portal.conventions.RequestParameterConventions;
044: import es.udc.mypersonalizer.kernel.model.actions.ActionProcessorSingleton;
045: import es.udc.mypersonalizer.kernel.model.repository.interfaces.CachedServiceReplyAccessor;
046: import es.udc.mypersonalizer.kernel.model.repository.interfaces.RepositoryAccessorFactory;
047: import es.udc.mypersonalizer.kernel.model.repository.interfaces.ServicePropertyKey;
048: import es.udc.mypersonalizer.kernel.util.exceptions.InstanceNotFoundException;
049: import es.udc.mypersonalizer.kernel.controller.actions.DefaultAction;
050: import es.udc.mypersonalizer.portal.controller.actions.content.NoActiveWorkspacesException;
051: import es.udc.mypersonalizer.portal.controller.session.KeyChecker;
052: import es.udc.mypersonalizer.portal.controller.session.SessionManager;
053: import es.udc.mypersonalizer.portal.controller.wizards.WizardEventFactory;
054: import es.udc.mypersonalizer.portal.model.types.WizardEvent;
055: import java.util.*;
056: import javax.servlet.http.HttpServletRequest;
057: import javax.servlet.http.HttpServletResponse;
058: import org.apache.struts.action.ActionForm;
059: import org.apache.struts.action.ActionForward;
060: import org.apache.struts.action.ActionMapping;
061: import org.apache.struts.action.DynaActionForm;
062:
063: /**
064: * This action performs an update on a ServiceProperty object, this is,
065: * changes a given configuration for a service. It collects information
066: * probably from a form in a JSP page. It calls the model action
067: * called <tt>ChangeServicePropertyAction</tt>, which must be registered in
068: * configuration. Because of a configuration change being able to provoke
069: * a different request from a service when invoked, this action also
070: * deletes the cached responses (if any) in the cache for this service.<p>
071: *
072: * It receives as a parameter a struts action form which must have been
073: * populated with any fields susceptible of being changed, as may have been
074: * defined in the metainformation for the concrete service. Note, nevertheless,
075: * that it is not necessary that all fields in the metainformation be included
076: * in the form.<p>
077: *
078: * It also needs to take the following parameters from the request:
079: * <ul>
080: * <li><tt>serviceIdentifier</tt>: The identifier for the service to which
081: * the property being changed belongs.</li>
082: * <li><tt>propertyIdentifier</tt>: The identifier (a number suitable to
083: * fit into a Long object) of the property being changed.</li>
084: * <li><tt>propertyUpdaterName</tt>: The name of the updater (see
085: * {@link es.udc.mypersonalizer.portal.model.wizards.PropertyUpdater})
086: * which <tt>update</tt> method will be applied to the service property.
087: * The action of this property updater establishes what is going to be
088: * made to the property: add, update, delete... The value of this parameter
089: * must coincide with one of the names for property updaters registered
090: * in configuration.</li>
091: * <li><tt>propertyStructureName</tt>: The identifier of the position
092: * of the needed structure in the property's tree. Some examples:
093: * <ul>
094: * <li><tt>0</tt>: Very used as a first stage for wizards, if we want
095: * to act on the root property contents, being this root property
096: * single-valued.</li>
097: * <li><tt>0.a.1</tt>: Which would mean we want to act on the values for
098: * the second (number 1) value of the multi-valued property
099: * <tt>a</tt>in the first value of the root property.</li>
100: * </ul></li>
101: * <li><tt>previousPropertyStructureNames</tt>: This is a helper parameter,
102: * which consists of a comma-separated list of the values that the
103: * <tt>propertyStructureName</tt> parameter had in all previous steps
104: * of a wizard, if this has more than one because of the existance of
105: * multi-valued properties. This helps, when any update is made at a
106: * particular level, to be able to get back to the correct
107: * previous level in the wizard. An example:
108: * <ul>
109: * <li><tt>0,0.a.1,0.a.1.x.0</tt>: We are at the fourth level of a
110: * wizard, and the previous levels we visited referred to the
111: * property structures <tt>0</tt>, <tt>0.a.1</tt> and <tt>0.a.1.x.0</tt>
112: * </li>
113: * </ul></li>
114: * <li><tt>simplePropertyNames</tt>: A comma-separated list of all the names
115: * of the fields entered from the form <u>and which should make their way
116: * to the repository</u>.</li>
117: * <li><tt>simplePropertyNamesNotToTrim</tt>: A subset of
118: * <tt>simplePropertyNames</tt>, which is also a comma-separated list of
119: * the fields which should not be trimmed (i.e. not removed
120: * their heading and trailing spaces).</li>
121: * </ul>
122: *
123: * This action requires a <tt>Success</tt> forward, which will point, either
124: * to, for example, the main page, or to the page responsible for the edition
125: * of the previous level of a wizard. The second case will be the adequate
126: * when this action is called as a result to the submission of data in the
127: * second, third, etc. level of a wizard, so that the user is returned to
128: * the previous level insted to the mainpage. This feature makes use of the
129: * <tt>previousPropertyStructureNames</tt> parameter.<p>
130: *
131: * @author Daniel Fernandez
132: * @since 1.0
133: */
134: public class ChangeServicePropertyAction extends DefaultAction {
135:
136: /**
137: * Name of the model action for changing a service property
138: * This is "ChangeServicePropertyAction".
139: */
140: private static final String CHANGE_SERVICE_PROPERTY_ACTION = "ChangeServicePropertyAction";
141:
142: protected ActionForward doExecute(ActionMapping mapping,
143: ActionForm form, HttpServletRequest request,
144: HttpServletResponse response) throws Exception {
145:
146: /*
147: * If there are no workspaces, this action cannot be executed.
148: */
149: if (!SessionManager.getUserHasWorkspaces(request)) {
150: throw new NoActiveWorkspacesException(
151: "Cannot change service property");
152: }
153:
154: ActionProcessorSingleton actionProcessorSingleton = ActionProcessorSingleton
155: .getInstance();
156:
157: /*
158: * No control Map is established from this class, and so all of
159: * them should come as request parameters and be read by the
160: * WizardEventFactory
161: */
162: Map controlParameters = new HashMap();
163:
164: /* We create the WizardEvent object with all the data */
165: WizardEvent changeServicePropertyEvent = WizardEventFactory
166: .createWizardEvent(request, form, controlParameters);
167:
168: /*
169: * This "serviceIdentifier" and "propertyIdentifier" parameters
170: * are needed here to create the ServicePropertyKey object which will
171: * be used to check the correctness of the property being changed.
172: */
173: String serviceIdentifier = changeServicePropertyEvent
174: .getServiceIdentifier();
175: Long propertyIdentifier = changeServicePropertyEvent
176: .getPropertyIdentifier();
177:
178: String previousPropertyStructureNamesParam = request
179: .getParameterValues(RequestParameterConventions.PREVIOUS_PROPERTY_STRUCTURE_NAMES)[0];
180:
181: /* Will be needed for checking */
182: ServicePropertyKey servicePropertyKey = new ServicePropertyKey(
183: serviceIdentifier, propertyIdentifier);
184:
185: /*
186: * First, we check that the ServiceProperty requested corresponds
187: * to one of the service property keys the user has in the current
188: * workspace layout.
189: */
190: if (KeyChecker.isValidServicePropertyKey(request,
191: servicePropertyKey)) {
192:
193: /* We execute the model action */
194: actionProcessorSingleton.execute(
195: CHANGE_SERVICE_PROPERTY_ACTION,
196: changeServicePropertyEvent);
197:
198: RepositoryAccessorFactory repositoryAccessorFactory = RepositoryAccessorFactory
199: .getInstance();
200:
201: /*
202: * As we need to remove any entries for this service from
203: * the cache, we need an accessor
204: */
205: CachedServiceReplyAccessor cachedServiceReplyAccessor = repositoryAccessorFactory
206: .createCachedServiceReplyAccessor();
207:
208: /*
209: * The cached responses for this service are removed, because
210: * configuration has changed.
211: */
212: cachedServiceReplyAccessor
213: .removeCachedServiceReply(servicePropertyKey);
214:
215: } else {
216: throw new InstanceNotFoundException(
217: ("[" + serviceIdentifier + "|" + propertyIdentifier + "]"),
218: "ServiceProperty");
219: }
220:
221: /* The action form is reset */
222: if (form != null) {
223: if (form instanceof DynaActionForm) {
224: ((DynaActionForm) form).initialize(mapping);
225: } else {
226: form.reset(mapping, request);
227: }
228: }
229:
230: /* We need to check where does the Success forward point to */
231: ActionForward forward = mapping
232: .findForward(DefaultAction.ACTION_SUCCESS_FORWARD);
233:
234: /*
235: * If we're not returning to the main page, we'll need to add some
236: * parameters to the request URL so as to display the correct
237: * information to the user (the previous wizard level) through,
238: * probably, a "FindServiceProperty" action.
239: */
240: if (!forward.getPath().equals(
241: DefaultAction.MAIN_PAGE_FORWARD_PATH)) {
242:
243: /*
244: * We pop the new "propertyStructureName" parameter value from
245: * the "previousPropertyStructureNames" list.
246: */
247: String propertyStructureName = getPropertyStructureName(previousPropertyStructureNamesParam);
248: String previousPropertyStructureNames = getPreviousPropertyStructureNames(previousPropertyStructureNamesParam);
249:
250: /* We build the adequate URL for the previous wizard level */
251: String parameters = "?"
252: + RequestParameterConventions.SERVICE_IDENTIFIER
253: + "="
254: + serviceIdentifier
255: + "&"
256: + RequestParameterConventions.PROPERTY_IDENTIFIER
257: + "="
258: + propertyIdentifier
259: + "&"
260: + RequestParameterConventions.PROPERTY_STRUCTURE_NAME
261: + "="
262: + propertyStructureName
263: + "&"
264: + RequestParameterConventions.PREVIOUS_PROPERTY_STRUCTURE_NAMES
265: + "=" + previousPropertyStructureNames;
266:
267: /* ...and modify the ActionForward */
268: forward = new ActionForward(forward.getName(), (forward
269: .getPath() + parameters), forward.getRedirect(),
270: forward.getContextRelative());
271:
272: }
273:
274: return forward;
275: }
276:
277: private String getPropertyStructureName(
278: String previousPropertyStructureNames) {
279:
280: String result = null;
281: if (previousPropertyStructureNames.equals("")) {
282: result = "";
283: } else {
284: try {
285: Integer.parseInt(previousPropertyStructureNames);
286: result = previousPropertyStructureNames;
287: } catch (NumberFormatException e) {
288: result = previousPropertyStructureNames
289: .substring(previousPropertyStructureNames
290: .lastIndexOf(".") + 1);
291: }
292: }
293: return result;
294:
295: }
296:
297: private String getPreviousPropertyStructureNames(
298: String previousPropertyStructureNames) {
299:
300: String result = null;
301: if (previousPropertyStructureNames.equals("")) {
302: result = "";
303: } else {
304: try {
305: Integer.parseInt(previousPropertyStructureNames);
306: result = "";
307: } catch (NumberFormatException e) {
308: result = previousPropertyStructureNames
309: .substring(0, previousPropertyStructureNames
310: .lastIndexOf(","));
311: }
312: }
313: return result;
314: }
315:
316: }
|