001: /*
002: * $Header: /export/home/cvsroot/MyPersonalizerRepository/MyPersonalizer/Subsystems/Portal/Sources/es/udc/mypersonalizer/portal/controller/wizards/RequestPopulator.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.wizards;
042:
043: import java.util.ArrayList;
044: import java.util.HashMap;
045: import java.util.Iterator;
046: import java.util.List;
047: import java.util.Map;
048: import java.util.StringTokenizer;
049:
050: import javax.servlet.http.HttpServletRequest;
051:
052: import org.apache.commons.beanutils.BeanUtils;
053: import org.apache.struts.action.ActionForm;
054:
055: import es.udc.mypersonalizer.kernel.model.metainfo.MetaProperty;
056: import es.udc.mypersonalizer.kernel.model.metainfo.MetaService;
057: import es.udc.mypersonalizer.kernel.model.metainfo.MetaServiceRegistrySingleton;
058: import es.udc.mypersonalizer.kernel.model.properties.Property;
059: import es.udc.mypersonalizer.kernel.model.properties.PropertyStructure;
060: import es.udc.mypersonalizer.kernel.model.properties.SimpleProperty;
061: import es.udc.mypersonalizer.kernel.util.exceptions.InternalErrorException;
062: import es.udc.mypersonalizer.portal.conventions.RequestAttributeNames;
063: import es.udc.mypersonalizer.portal.conventions.RequestParameterConventions;
064:
065: /** This class, used by the controller actions which have to put part of a
066: * ServiceProperty into the request for a jsp to be able to show its
067: * contents. For example, it is used by
068: * <tt>EditUserRegistrationInformationAction</tt> to show the user's data and
069: * by <tt>FindServiceProperty</tt> to show service configuration information
070: * in the service wizards.<p>
071: *
072: * The way in which this property structures are set into the request
073: * follow this scheme:
074: * <ul>
075: * <li>For each simple property present in the property we're showing,
076: * a request attribute is created with its name and being its
077: * contents a String[] value.</li>
078: * <li>For each compound property present in the property we're showing,
079: * a request attribute is created with its name and being its
080: * contents a Map with the following entries:
081: * <ul>
082: * <li><tt>_addParameters</tt>: a String being the parameters
083: * needed to create a link to another level of a wizard
084: * in which a new value is added to this property.</li>
085: * <li><tt>values</tt>: a List, containing for each
086: * child property a Map with the following entries:
087: * <ul>
088: * <li><tt>_editParameters</tt>: a String being the
089: * parameters needed to create a link to another level
090: * of a wizard in which this value of the property
091: * is edited.</li>
092: * <li><tt>_removeParameters</tt>: a String being the
093: * parameters needed to create a link with which to remove
094: * this value of the property.</li>
095: * <li><tt>X</tt>: Being <tt>X</tt> the name of the child
096: * property, it is treated the same way as the parent
097: * property (i.e.: a String[] if it is simple or another
098: * compound structure if it is compound).</li>
099: * </ul>
100: * </li>
101: * </ul>
102: * </li>
103: * <li>If the property being displayed is the root property of a
104: * ServiceProperty, and this is compound and multi-valued, it will
105: * be put into the request an attribute named <tt>properties</tt> with
106: * an structure equivalent to the above explained for compound properties.
107: * </li>
108: * </ul>
109: *
110: * @author Daniel Fernandez
111: * @author Fernando Bellas
112: * @since 1.0
113: */
114: public class RequestPopulator {
115:
116: /**
117: * Name of the Map entry which will contain the parameters which will
118: * be added to the adequate URL to add a new value to a multi-valued
119: * property.
120: */
121: private static final String ADD_VALUE_URL_PARAMETERS_ENTRY_NAME = "_addParameters";
122:
123: /**
124: * Name of the Map entry which will contain the parameters which will
125: * be added to the adequate URL to modify an existing value in a
126: * multi-valued property.
127: */
128: private static final String EDIT_VALUE_URL_PARAMETERS_ENTRY_NAME = "_editParameters";
129:
130: /**
131: * Name of the Map entry which will contain the parameters which will
132: * be added to the adequate URL to remove an existing value in a
133: * multi-valued property.
134: */
135: private static final String REMOVE_VALUE_URL_PARAMETERS_ENTRY_NAME = "_removeParameters";
136:
137: /**
138: * Name of the property updater which must be applied to a property
139: * structure to remove it.
140: */
141: private static final String REMOVE_PROPERTY_STRUCTURE_UPDATER_NAME = "removePropertyStructure";
142:
143: /**
144: * Avoids instantiation of this class
145: */
146: private RequestPopulator() {
147: }
148:
149: /**
150: * Perform the analysis of the ServiceProperty provided and puts its data
151: * into the request as explained in the class definition.
152: *
153: * @param request the request object.
154: * @param actionForm the action form of the action calling this class.
155: * @param serviceIdentifier the service identifier.
156: * @param propertyIdentifier the service property identifier.
157: * @param propertyStructureName the property structure name which locates
158: * the action in a determinated point of the property tree.
159: * @param previousPropertyStructureNames the list of previous steps in the
160: * wizard.
161: * @param property the property.
162: * @throws InternalErrorException if any fatal errors happen.
163: */
164: public static void populateRequest(HttpServletRequest request,
165: ActionForm actionForm, String serviceIdentifier,
166: String propertyIdentifier, String propertyStructureName,
167: String previousPropertyStructureNames, Property property)
168: throws InternalErrorException {
169:
170: try {
171:
172: MetaServiceRegistrySingleton metaServiceRegistrySingleton = MetaServiceRegistrySingleton
173: .getInstance();
174:
175: MetaService metaService = metaServiceRegistrySingleton
176: .getMetaService(serviceIdentifier);
177:
178: /*
179: * So, we get the root property for the user registration
180: * information
181: */
182: MetaProperty metaRootProperty = metaService
183: .getMetaRootProperty();
184:
185: String metaPropertyName = getMetaPropertyName(propertyStructureName);
186: MetaProperty receivedMetaProperty = metaRootProperty;
187:
188: /* If we need to dig down the property tree, do it */
189: if (!metaPropertyName.equals("")) {
190: receivedMetaProperty = metaRootProperty
191: .findMetaProperty(metaPropertyName);
192: }
193:
194: if ((receivedMetaProperty.isMultiValued())
195: && (propertyStructureName.equals(""))) {
196:
197: /*
198: * We'return dealing with the root property
199: */
200: Map compoundStructure = getCompoundStructure(property,
201: receivedMetaProperty, serviceIdentifier,
202: propertyIdentifier, "", "",
203: propertyStructureName);
204:
205: request
206: .setAttribute(
207: RequestAttributeNames.ROOT_PROPERTY_STRUCTURE_ATTRIBUTE_NAME,
208: compoundStructure);
209:
210: } else {
211:
212: /*
213: * We must take just the property value we're
214: * dealing with.
215: */
216: PropertyStructure propertyStructure = (PropertyStructure) property
217: .getValuesAsObject()[getPropertyStructureNumber(propertyStructureName)];
218:
219: if (propertyStructureName.equals("")) {
220: propertyStructureName = "0";
221: }
222:
223: Map properties = propertyStructure.getAsMap();
224: Iterator propertiesIter = properties.values()
225: .iterator();
226:
227: Map formProperties = BeanUtils.describe(actionForm);
228:
229: while (propertiesIter.hasNext()) {
230:
231: Property currentProperty = (Property) propertiesIter
232: .next();
233: String propertyName = currentProperty
234: .getSimpleName();
235:
236: MetaProperty currentMetaProperty = metaRootProperty
237: .findMetaProperty(getMetaPropertyName(propertyStructureName
238: + "." + propertyName));
239:
240: boolean simple = (currentProperty instanceof SimpleProperty);
241:
242: if (simple) {
243:
244: if (formProperties.containsKey(propertyName)) {
245:
246: /*
247: * It's simple, so we'll just need a String[]
248: */
249: String[] values = currentProperty
250: .getValuesAsString();
251:
252: boolean multiValued = currentMetaProperty
253: .isMultiValued();
254:
255: if (!multiValued) {
256: if (values.length == 0) {
257: BeanUtils.setProperty(actionForm,
258: propertyName, "");
259: } else {
260: BeanUtils.setProperty(actionForm,
261: propertyName, values[0]);
262: }
263: } else {
264: BeanUtils.setProperty(actionForm,
265: propertyName, values);
266: }
267:
268: }
269:
270: } else {
271:
272: /*
273: * It's a compound property, and therefore
274: * we need to create a complex structure.
275: */
276: Map compoundStructure = getCompoundStructure(
277: currentProperty,
278: currentMetaProperty,
279: serviceIdentifier,
280: propertyIdentifier,
281: (propertyStructureName + "." + propertyName),
282: previousPropertyStructureNames,
283: propertyStructureName);
284:
285: request.setAttribute(propertyName,
286: compoundStructure);
287:
288: }
289: }
290:
291: }
292:
293: } catch (Exception e) {
294: throw new InternalErrorException(e);
295: }
296:
297: }
298:
299: private static Map getCompoundStructure(Property property,
300: MetaProperty metaProperty, String serviceIdentifier,
301: String propertyIdentifier, String propertyName,
302: String previousPropertyStructureNames,
303: String currentPropertyStructureName) throws Exception {
304:
305: Map compoundStructure = new HashMap();
306: List entriesList = new ArrayList();
307: Object[] values = property.getValuesAsObject();
308:
309: String previousPropertyStructureNamesParam = null;
310:
311: if (currentPropertyStructureName.equals("")) {
312: previousPropertyStructureNamesParam = "";
313: } else {
314: try {
315: Integer.parseInt(currentPropertyStructureName);
316: previousPropertyStructureNamesParam = currentPropertyStructureName;
317: } catch (NumberFormatException e) {
318: previousPropertyStructureNamesParam = previousPropertyStructureNames
319: + "," + currentPropertyStructureName;
320: }
321: }
322:
323: for (int i = 0; i < values.length; i++) {
324:
325: Map entryProperties = new HashMap();
326:
327: PropertyStructure entryPropertyStructure = (PropertyStructure) values[i];
328:
329: Map entryPropertyStructureProperties = entryPropertyStructure
330: .getAsMap();
331: Iterator entryPropertyStructurePropertiesIter = entryPropertyStructureProperties
332: .values().iterator();
333:
334: while (entryPropertyStructurePropertiesIter.hasNext()) {
335:
336: Property currentEntryProperty = (Property) entryPropertyStructurePropertiesIter
337: .next();
338: String entryPropertyName = currentEntryProperty
339: .getSimpleName();
340:
341: MetaProperty currentEntryMetaProperty = metaProperty
342: .findMetaProperty(entryPropertyName);
343:
344: boolean simpleEntry = (currentEntryProperty instanceof SimpleProperty);
345:
346: if (simpleEntry) {
347:
348: String[] entryValues = currentEntryProperty
349: .getValuesAsString();
350:
351: boolean multiValued = currentEntryMetaProperty
352: .isMultiValued();
353:
354: entryProperties.put(entryPropertyName, entryValues);
355:
356: } else {
357:
358: String followingPropertyName = null;
359: if (propertyName.equals("")) {
360: followingPropertyName = i + "."
361: + entryPropertyName;
362: } else {
363: followingPropertyName = propertyName + i + "."
364: + entryPropertyName;
365: }
366:
367: Map entryCompoundStructure = getCompoundStructure(
368: currentEntryProperty,
369: currentEntryMetaProperty,
370: serviceIdentifier, propertyIdentifier,
371: followingPropertyName,
372: previousPropertyStructureNames,
373: currentPropertyStructureName);
374:
375: entryProperties.put(entryPropertyName,
376: entryCompoundStructure);
377:
378: }
379:
380: }
381:
382: String propertyStructureNameParam = null;
383: if (propertyName.equals("")) {
384: propertyStructureNameParam = Integer.toString(i);
385: } else {
386: propertyStructureNameParam = propertyName + "." + i;
387: }
388:
389: String editParameters = RequestParameterConventions.SERVICE_IDENTIFIER
390: + "="
391: + serviceIdentifier
392: + "&"
393: + RequestParameterConventions.PROPERTY_IDENTIFIER
394: + "="
395: + propertyIdentifier
396: + "&"
397: + RequestParameterConventions.PROPERTY_STRUCTURE_NAME
398: + "="
399: + propertyStructureNameParam
400: + "&"
401: + RequestParameterConventions.PREVIOUS_PROPERTY_STRUCTURE_NAMES
402: + "=" + previousPropertyStructureNamesParam;
403:
404: entryProperties.put(EDIT_VALUE_URL_PARAMETERS_ENTRY_NAME,
405: editParameters);
406: entryProperties
407: .put(
408: REMOVE_VALUE_URL_PARAMETERS_ENTRY_NAME,
409: (editParameters
410: + "&"
411: + RequestParameterConventions.PROPERTY_UPDATER_NAME
412: + "="
413: + REMOVE_PROPERTY_STRUCTURE_UPDATER_NAME
414: + "&"
415: + RequestParameterConventions.SIMPLE_PROPERTY_NAMES
416: + "="
417: + "blank"
418: + "&"
419: + RequestParameterConventions.SIMPLE_PROPERTY_NAMES_NOT_TO_TRIM
420: + "=" + "" + "&" + "blank=0"));
421:
422: entriesList.add(entryProperties);
423:
424: }
425:
426: String addPropertyStructureNameParam = null;
427: if (propertyName.equals("")) {
428: addPropertyStructureNameParam = "0";
429: } else {
430: addPropertyStructureNameParam = propertyName + "." + "0";
431: }
432:
433: String addParameters = RequestParameterConventions.SERVICE_IDENTIFIER
434: + "="
435: + serviceIdentifier
436: + "&"
437: + RequestParameterConventions.PROPERTY_IDENTIFIER
438: + "="
439: + propertyIdentifier
440: + "&"
441: + RequestParameterConventions.PROPERTY_STRUCTURE_NAME
442: + "="
443: + addPropertyStructureNameParam
444: + "&"
445: + RequestParameterConventions.PREVIOUS_PROPERTY_STRUCTURE_NAMES
446: + "=" + previousPropertyStructureNamesParam;
447:
448: compoundStructure.put(ADD_VALUE_URL_PARAMETERS_ENTRY_NAME,
449: addParameters);
450:
451: compoundStructure.put("values", entriesList);
452:
453: return compoundStructure;
454:
455: }
456:
457: private static String getMetaPropertyName(String propertyName) {
458:
459: String result = "";
460:
461: StringTokenizer tokenizer = new StringTokenizer(propertyName,
462: ".");
463:
464: if (tokenizer.countTokens() > 1) {
465:
466: boolean first = true;
467: while (tokenizer.hasMoreTokens()) {
468: String token = tokenizer.nextToken();
469: try {
470: Integer.parseInt(token);
471: } catch (NumberFormatException e) {
472: if (!first) {
473: result += ".";
474: } else {
475: first = false;
476: }
477: result += token;
478: }
479: }
480:
481: }
482:
483: return result;
484:
485: }
486:
487: private static int getPropertyStructureNumber(
488: String propertyStructureName) throws NumberFormatException {
489: int lastDotIndex = propertyStructureName.lastIndexOf(".");
490: if (lastDotIndex >= 0) {
491: return Integer
492: .parseInt(propertyStructureName
493: .substring(propertyStructureName
494: .lastIndexOf(".") + 1));
495: } else {
496: try {
497: return Integer.parseInt(propertyStructureName);
498: } catch (NumberFormatException e) {
499: return 0;
500: }
501: }
502: }
503:
504: }
|