001: /*
002: * $Header: /export/home/cvsroot/MyPersonalizerRepository/MyPersonalizer/Subsystems/Admin/Sources/es/udc/mypersonalizer/admin/http/controller/actions/propertyeditor/util/PropertyEditorHelper.java,v 1.1.1.1 2004/03/25 12:08:38 fbellas Exp $
003: * $Revision: 1.1.1.1 $
004: * $Date: 2004/03/25 12:08:38 $
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.admin.http.controller.actions.propertyeditor.util;
042:
043: import java.util.Collection;
044: import java.util.Iterator;
045: import java.util.ArrayList;
046: import java.util.Map;
047: import java.util.HashMap;
048: import java.util.Arrays;
049:
050: import javax.servlet.http.Cookie;
051: import javax.servlet.http.HttpServletRequest;
052:
053: import org.apache.struts.action.ActionForward;
054: import org.apache.struts.action.ActionMapping;
055: import org.apache.struts.util.MessageResources;
056:
057: import es.udc.mypersonalizer.kernel.util.exceptions.InstanceNotFoundException;
058: import es.udc.mypersonalizer.kernel.model.metainfo.MetaServiceRegistrySingleton;
059: import es.udc.mypersonalizer.kernel.model.metainfo.MetaService;
060: import es.udc.mypersonalizer.kernel.model.metainfo.MetaProperty;
061: import es.udc.mypersonalizer.kernel.model.metainfo.MetaPropertyNotFoundException;
062: import es.udc.mypersonalizer.kernel.model.metainfo.MetaCompoundProperty;
063: import es.udc.mypersonalizer.kernel.model.metainfo.MetaSimpleProperty;
064: import es.udc.mypersonalizer.kernel.model.properties.Property;
065: import es.udc.mypersonalizer.kernel.model.properties.CompoundProperty;
066: import es.udc.mypersonalizer.kernel.model.properties.PropertyNaming;
067: import es.udc.mypersonalizer.kernel.model.properties.PropertyNotFoundException;
068:
069: import es.udc.mypersonalizer.admin.http.view.viewobjects.propertyeditor.ViewProperty;
070: import es.udc.mypersonalizer.admin.http.controller.actions.util.ControllerHelper;
071:
072: /**
073: * Helper for the controller actions of the property editor.
074: *
075: * @author Abel Iago Toral Quiroga
076: * @since 1.0
077: */
078: public class PropertyEditorHelper {
079:
080: /**
081: * Tries to find a property included inside another one.
082: * @param rootProperty the root property.
083: * @param propertyStructureName the absolute name of the property to find
084: * without the property simple.
085: * @param propertySimpleName the property to find simple name.
086: * @throws PropertyNotFoundException if the property does not exist.
087: * @return the <code>Property</code>.
088: */
089: public static Property findProperty(Property rootProperty,
090: String propertyStructureName, String propertySimpleName)
091: throws PropertyNotFoundException {
092:
093: Property property = null;
094: if (propertyStructureName.equals("")) { // special case
095: property = rootProperty;
096: } else {
097: property = rootProperty.findProperty(propertyStructureName
098: + "." + propertySimpleName);
099: }
100:
101: return property;
102: }
103:
104: /**
105: * Finds meta-information of a service root property.
106: * @param serviceIdentifier the service identifier.
107: * @throws InstanceNotFoundException if can't access meta-information.
108: * @return the meta information of the root property of that service.
109: */
110: public static MetaProperty findMetaProperty(String serviceIdentifier)
111: throws InstanceNotFoundException {
112:
113: /* Get meta-service */
114: MetaService metaService = (MetaService) MetaServiceRegistrySingleton
115: .getInstance().getMetaService(serviceIdentifier);
116: if (metaService == null) {
117: new InstanceNotFoundException(serviceIdentifier,
118: MetaService.class.getName());
119: }
120:
121: /* Get and return meta-property */
122: return metaService.getMetaRootProperty();
123: }
124:
125: /**
126: * Tries to find the meta property associated with a property inside
127: * another one.
128: * @param rootMetaProperty the root meta property.
129: * @param propertyStructureName the absolute name of the property (not the
130: * meta property) without the property simple name.
131: * @param propertySimpleName the property simple name.
132: * @throws MetaPropertyNotFoundException if the meta property does not
133: * exist.
134: * @return the <code>MetaProperty</code> asociated with the
135: * <code>Property</code>.
136: */
137: public static MetaProperty findMetaProperty(
138: MetaProperty rootMetaProperty,
139: String propertyStructureName, String propertySimpleName)
140: throws MetaPropertyNotFoundException {
141:
142: /* Get meta-property structure name */
143: String metaPropertyStructureName = PropertyNaming
144: .toMetaPropertyName(propertyStructureName);
145:
146: /* Get the meta property */
147: MetaProperty metaProperty = null;
148: if (propertyStructureName.equals("")) { // special case : root property
149: metaProperty = rootMetaProperty;
150: } else if (metaPropertyStructureName.equals("")) {
151: metaProperty = rootMetaProperty
152: .findMetaProperty(propertySimpleName);
153: } else {
154: metaProperty = rootMetaProperty
155: .findMetaProperty(metaPropertyStructureName + "."
156: + propertySimpleName);
157: }
158:
159: return metaProperty;
160: }
161:
162: /**
163: * Tries to find the meta property associated with a property inside
164: * another one.
165: * @param serviceIdentifier the service identifier.
166: * @param propertyStructureName the absolute name of the property (not the
167: * meta property) without the property simple name.
168: * @param propertySimpleName the property simple name.
169: * @throws MetaPropertyNotFoundException if the meta property does not
170: * exist.
171: * @throws InstanceNotFoundException if can't access the meta-service.
172: * @return the <code>MetaProperty</code> asociated with the
173: * <code>Property</code>.
174: */
175: public static MetaProperty findMetaProperty(
176: String serviceIdentifier, String propertyStructureName,
177: String propertySimpleName)
178: throws MetaPropertyNotFoundException,
179: InstanceNotFoundException {
180:
181: MetaProperty rootMetaProperty = findMetaProperty(serviceIdentifier);
182: return findMetaProperty(rootMetaProperty,
183: propertyStructureName, propertySimpleName);
184: }
185:
186: /**
187: * Uses meta-information to know if a property is boolean or not.
188: * @param serviceIdentifier the service identifier.
189: * @param propertyStructureName the absolute name of the property (not the
190: * meta property) without the property simple name.
191: * @param propertySimpleName the property simple name.
192: * @throws MetaPropertyNotFoundException if the meta property does not
193: * exist.
194: * @throws InstanceNotFoundException if can't access the meta-service.
195: * @return <code>true</code> if it is boolean, <code>false</code> otherwise.
196: */
197: public static boolean isBoolean(String serviceIdentifier,
198: String propertyStructureName, String propertySimpleName)
199: throws MetaPropertyNotFoundException,
200: InstanceNotFoundException {
201:
202: MetaSimpleProperty metaSimpleProperty = (MetaSimpleProperty) findMetaProperty(
203: serviceIdentifier, propertyStructureName,
204: propertySimpleName);
205:
206: return (metaSimpleProperty.getJavaType().equals(Boolean.TRUE
207: .getClass()));
208: }
209:
210: /**
211: * Retrives information about a value of a <code>CompoundProperty</code>.
212: * @param parentProperty the compound property which one of its values
213: * will be processed.
214: * @param parentMetaCompoundProperty the meta property associated with
215: * the property.
216: * @param valueIndex the value of the property that will be processed.
217: * @throws PropertyNotFoundException if the property does not exist.
218: * @return a sorted Collection with <code>ViewProperty</code> objects
219: * describing each of the properties contained by the compound
220: * property value.
221: */
222: public static Collection getViewPropertiesList(
223: CompoundProperty parentProperty,
224: MetaProperty parentMetaCompoundProperty, int valueIndex)
225: throws PropertyNotFoundException {
226:
227: /* Get sub-properties of parent property */
228: Iterator iterator = parentMetaCompoundProperty
229: .getMetaProperties();
230:
231: /* Get sub-properties meta-info and values */
232: Collection viewPropertiesList = new ArrayList();
233: while (iterator.hasNext()) { // For each sub-property
234:
235: /* Get sub-property meta-information*/
236: MetaProperty currentMetaProperty = (MetaProperty) iterator
237: .next();
238: String currentPropertySimpleName = currentMetaProperty
239: .getSimpleName();
240: boolean isMultiValued = currentMetaProperty.isMultiValued();
241: boolean isCompound = (currentMetaProperty instanceof MetaCompoundProperty);
242:
243: /* Get sub-property */
244: /* NOTE : if can't find the property DO NOT throw an exception
245: * but let continue with the next property. This allows the
246: * PropertyAccessStrategy implementation remove properties
247: * that can't be edited.
248: */
249: Property currentProperty = null;
250: try {
251: currentProperty = parentProperty
252: .findProperty(valueIndex + "."
253: + currentPropertySimpleName);
254: } catch (Exception e) {
255: continue;
256: }
257:
258: /* Get value of sub-property as String if possible */
259: String currentPropertyValueAsString = "";
260: boolean isBoolean = false;
261: boolean hasValue = true;
262: if (!isCompound && !isMultiValued) {
263:
264: String[] currentPropertyValuesAsString = currentProperty
265: .getValuesAsString();
266:
267: if (currentPropertyValuesAsString.length > 0) {
268: currentPropertyValueAsString = currentPropertyValuesAsString[0];
269: }
270:
271: MetaSimpleProperty currentMetaSimpleProperty = (MetaSimpleProperty) currentMetaProperty;
272: isBoolean = currentMetaSimpleProperty.getJavaType()
273: .equals(Boolean.TRUE.getClass());
274:
275: } else if (isCompound && !isMultiValued) {
276:
277: /* This let's the property editor recognize the case of a
278: * compound property single-valued with has already been gived
279: * a value . So the JSP form lets the user remove it.
280: */
281:
282: /* Has a already a value? */
283: if (currentProperty.getValuesAsObject().length <= 0) {
284: currentPropertyValueAsString = null;
285: }
286: }
287:
288: /* Create view-object */
289: ViewProperty viewProperty = new ViewProperty(
290: currentPropertySimpleName,
291: currentPropertyValueAsString, isMultiValued,
292: isCompound, isBoolean);
293: viewPropertiesList.add(viewProperty);
294: }
295:
296: return sortViewProperties(viewPropertiesList);
297: }
298:
299: /**
300: * Constructs an <code>ActionForward</code> to
301: * <code>UpdateCompoundProperty</code> or
302: * <code>UpdateSimpleProperty</code> adding the needed parameters to the
303: * url path.
304: * @param mapping the mapping of the action that called this method.
305: * @param forwardName the logical name of the forward. It is used to
306: * retrive the url path for the desired action and will be, as
307: * indicated in <code>struts-config.xml</code>, UpdateSimpleProperty
308: * or UpdateCompoundProperty. It is also used to get the redirect
309: * attribute for this forward.
310: * @param peConfigurationIdentifier the property editor configuration
311: * identifier used in this use case of the property editor.
312: * @param serviceIdentifier the service identifier parameter for the
313: * action.
314: * @param propertyIdentifier the corresponding parameter to call the
315: * action.
316: * @param propertyStructureName the corresponding parameter to call the
317: * action.
318: * @param propertySimpleName the corresponding parameter to call the
319: * action.
320: * @return the <code>ActionForward</code> to the specified action with the
321: * indicated parameters attached to the url path.
322: */
323: public static ActionForward getReturnToUpdatePropertyForward(
324: ActionMapping mapping, String forwardName,
325: String peConfigurationIdentifier, String serviceIdentifier,
326: String propertyIdentifier, String propertyStructureName,
327: String propertySimpleName) {
328:
329: /* Get forward to UpdateCompoundProperty */
330: ActionForward forward = mapping.findForward(forwardName);
331:
332: /* Get url path and add parameters */
333: String urlPath = forward.getPath();
334: urlPath += "?peConfId=" + peConfigurationIdentifier;
335: urlPath += "&servId=" + serviceIdentifier;
336: urlPath += "&propId=" + propertyIdentifier;
337: urlPath += "&propertyStructureName=" + propertyStructureName;
338: urlPath += "&propertySimpleName=" + propertySimpleName;
339:
340: /* Update and return forward */
341: ActionForward forwardWithParameters = new ActionForward(
342: urlPath, forward.getRedirect());
343: return forwardWithParameters;
344: }
345:
346: /**
347: * Adds to a <code>Map</code> a property value with key its property
348: * absolute name without value indexes (like a meta-property name).
349: * @param updatedProperties a map with properties values.
350: * @param propertyStructureName The property name without the property
351: * simple name.
352: * @param propertySimpleName The property simple name.
353: * @param propertyValue the property value.
354: */
355: public static void addUpdatedProperty(Map updatedProperties,
356: String propertyStructureName, String propertySimpleName,
357: String propertyValue) {
358:
359: String metaPropertyStructureName = PropertyNaming
360: .toMetaPropertyName(propertyStructureName);
361: String updatedPropertyName = "";
362: if (metaPropertyStructureName.equals("")) {
363: updatedPropertyName = propertySimpleName;
364: } else {
365: updatedPropertyName = metaPropertyStructureName + "."
366: + propertySimpleName;
367: }
368: updatedProperties.put(updatedPropertyName, propertyValue);
369: }
370:
371: /**
372: * Creates a <code>Map</code> of formatted error messages with
373: * <code>errors.header</code> and <code>errors.footer</code> from a
374: * <code>Map</code> with a set of message keys.
375: * @param resources the message resources.
376: * @param messageKeys a map with the error messages. The key
377: * for each message is the simple name of the property that
378: * produced the error.
379: * @return a Map with formatted error messages. The key for each message
380: * is the property simple name that produced the error.
381: */
382: public static Map getFormattedErrorMessages(
383: MessageResources resources, Map messageKeys) {
384:
385: Map errors = new HashMap();
386: Iterator messagesIterator = messageKeys.keySet().iterator();
387: while (messagesIterator.hasNext()) {
388: String erroneousPropertySimpleName = (String) messagesIterator
389: .next();
390: String formattedErrorMessage = ControllerHelper
391: .getFormattedErrorMessage(resources,
392: (String) messageKeys
393: .get(erroneousPropertySimpleName));
394: errors.put(erroneousPropertySimpleName,
395: formattedErrorMessage);
396: }
397: return errors;
398: }
399:
400: /**
401: * Sorts lexicographically a <code>Collection</code> of
402: * <code>ViewProperty</code> objects using attribute simple name.
403: * @param viewProperties The <code>ViewProperty</code>'s to short.
404: * @return The same <code>Collection</code> but shorted.
405: */
406: public static Collection sortViewProperties(
407: Collection viewProperties) {
408:
409: Object[] viewPropertiesAsArray = viewProperties.toArray();
410: Arrays.sort(viewPropertiesAsArray,
411: new ViewPropertiesComparator());
412: return Arrays.asList(viewPropertiesAsArray);
413: }
414:
415: /**
416: * Adds the application name and applays URL rewriting if needed to a url.
417: * @param request The request to get the application name and session id.
418: * @param url The url to complete (context relative).
419: * @return the completed url with the application name and the url
420: * rewriting applied if needed.
421: */
422: public static String completeUrl(HttpServletRequest request,
423: String url) {
424:
425: /* Add application name */
426: String applicationName = request.getContextPath();
427: String completedUrl = applicationName + url;
428:
429: /* Applay URL rewriting if needed */
430: Cookie[] cookies = request.getCookies();
431: if (cookies == null || cookies.length == 0) {
432: completedUrl += (";jsessionid=" + request.getSession(false)
433: .getId());
434: }
435:
436: /* Return completed url*/
437: return completedUrl;
438: }
439: }
|