001: /*
002: * $Header: /export/home/cvsroot/MyPersonalizerRepository/MyPersonalizer/Subsystems/Kernel/Sources/es/udc/mypersonalizer/kernel/model/properties/Property.java,v 1.1.1.1 2004/03/25 12:08:37 fbellas Exp $
003: * $Revision: 1.1.1.1 $
004: * $Date: 2004/03/25 12:08:37 $
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.kernel.model.properties;
042:
043: /**
044: * Defines common operations to all <code>Property</code> implementations, and
045: * in principle, represents a particular personalizable aspect, even though,
046: * the concept is general enough to represent any kind of structured
047: * information. <code>Property</code> corresponds to the "Component"
048: * participant in the "Composite" pattern, that is, the root interface
049: * declaring all common operations to derived classes/interfaces. Concrete
050: * implementations will either be leaf or composite classes.
051: * <p>
052: * All properties have a <b>simple name</b>, that is, a <code>String</code>
053: * (example: "numberOfHeadlines") and a value (<b>univalued</b>) or a
054: * number of them (<b>multivalued</b>), even though the interface
055: * hides such a diference by using a <code>Object[]</code> when refering
056: * to the value (an array with only one element) or the values (an array
057: * with potentially more than one value). In case of multivalued properties,
058: * all values are supposed to be of the same type, and deep copies are never
059: * done when setting or getting values (this is the usual semantics in Java).
060: * <p>
061: * In case of leaf properties, also called <b>simple properties</b>, in
062: * general, their values are not properties (however, nothing prevents it,
063: * because properties, of course, are also objects). The type of all values
064: * must be the same. In case of composite classes, also called
065: * <b>compound properties</b>, each value is a
066: * {@link PropertyStructure}, which contains a number of properties,
067: * which in turn can be leaf or composite properties. All values must be
068: * a <code>PropertyStructure</code> with the same properties (with possibly
069: * different values). In both cases, when needing to represent a property
070: * not taking any value, the special value <code>Object[0]</code> (or a
071: * subtype) must be used, and <b>not</b> the <code>null</code> value.
072: * Properties taking the special value <code>Object[0]</code> are referred to
073: * as <b>optionally valued properties</b> along the documentation.
074: * <p>
075: * <code>Property</code> interface has been maximized in order to increase
076: * transparency, that is, it declares operations applicable to leaf and
077: * composite objects (even though some of them could have no sense, and
078: * in consequence, may be not implemented), and hides the difference between
079: * univalued and multivalued properties, both in leaf and compound properties.
080: * Two standard implementations of this interface are provided:
081: * {@link SimpleProperty} and {@link CompoundProperty}, with the standard
082: * semantics.
083: * <p>
084: * As an example of a univalued compound property, you might consider the
085: * personalizable properties of a news service. Such a property could be
086: * called "newsServiceProperties", and its only value would be a property
087: * structure with two simple properties, one for representing the number of
088: * headlines and the other one for representing the names of the news sources
089: * where to search. The former could be a univalued simple property with
090: * simple name "numberOfHeadlines" and its value would be an
091: * <code>Integer</code> (a particular case of <code>Object[]</code> with only
092: * one integer). The latter could be a multivalued simple property with
093: * simple name "sources" and its value would be an array of
094: * <code>String</code> (a particular case of <code>Object[]</code>). This
095: * example also allows to introduce the concept of <b>full property name</b>.
096: * The full names of these last properties would be
097: * "newsServiceProperties.0.numberOfHeadlines" and
098: * "newsServiceProperties.0.sources". Note that a "." is used for separating
099: * simple names, and that a "0" is used between "newsServiceProperties" and
100: * "numberOfHeadlines". This is because values are always treated as an array
101: * of <code>Object</code>. So, when refering to the ist-elment (starting from
102: * 0) of a compound property, a ".i" must be used for specifying such an
103: * element. In case of univalued compound properties, the array has only one
104: * element, so you must refer to it with ".0". Note that the interface does
105: * not allow you to refer to a concrete value of property. You must get or set
106: * all of them, maybe removing or adding values with some auxiliary data
107: * structure (probably a <code>java.util.List</code>). So, in the above
108: * example, it does not make sense the name "newsServiceProperties.0". A name
109: * may also be relative to another one (examples: "0.sources" is relative to
110: * "newsServiceProperties"). Note also that a full name never begins with a
111: * ".".
112: * <p>
113: * As an example of a multivalued compound property, you might consider the
114: * personalizable properties of a "saved searches" service, that is, a
115: * service that mantains a list of predefined searches. Each saved search
116: * could specify its name and a number of keywords to take into account when
117: * searching. The personalizable properties of such a service could be
118: * represented with a multivalued compound property, with simple name
119: * "savedSearchesProperties". Each value of such a property is a structure
120: * of two simple properties: (1) the saved search name (simple name:
121: * "savedSearchName") containing a <code>String</code> (a particular case of
122: * <code>Object[]</code> with only one </code>String</code>), and (2)
123: * the keywords (simple name: "keywords") containing a <code>String[]</code>
124: * (a particular case of <code>Object[]</code>). Assuming that the array
125: * has at least two elements, the full name
126: * "savedSearchesProperties.1.keywords" refers to the "keywords" property
127: * of the second value of the compound property "savedSearchesProperties".
128: * <p>
129: * Name resolution, finding a property from another one, is always relative
130: * to the second one. So, for example, considering the second example,
131: * if you want to refer to the property "keywords" of the second element
132: * of the multivalued compound property "savedSearchesProperties", you
133: * must use the relative name "1.keywords" when looking for such a property
134: * from "savedSearchesProperties".
135: * <p>
136: * Due to values will be specified and displayed as human-readable strings of
137: * characters (tipically in HTML forms), <code>Property</code> defines
138: * operations for setting the values from strings and viceversa.
139: * <p>
140: * <b>NOTE:</b> all implementation of this interface must redefine
141: * <code>hashCode()</code> and <code>equals(Object)</code> in order to handle
142: * property comparisons properly. Two properties are equal if their names
143: * and their values are equal.
144: *
145: * @author Fernando Bellas
146: * @since 1.0
147: */
148: public interface Property extends java.io.Serializable {
149:
150: /**
151: * Returns the simple name of the property.
152: *
153: * @return the simple name of the property
154: */
155: String getSimpleName();
156:
157: /**
158: * Sets the simple name of the property.
159: *
160: * @param simpleName the simple name of the property
161: */
162: void setSimpleName(String simpleName);
163:
164: /**
165: * Returns the values of the property as an array of <code>String</code>.
166: *
167: * @return the values of the property as an array of <code>String</code>
168: * @throws java.lang.UnsupportedOperationException if the operation is not
169: * supported by this property
170: */
171: String[] getValuesAsString();
172:
173: /**
174: * Sets the values of the property as an array of <code>String</code>.
175: * It is possible to pass an array of 0 elements.
176: * (<code>setValuesAsString(new String[0])</code> is legal).
177: *
178: * @param valuesAsString the values of the property as an array of
179: * <code>String</code>
180: * @throws java.lang.UnsupportedOperationException if the operation is not
181: * supported by this property
182: * @throws IllegalStringValuesException if one or more strings in
183: * <code>valuesAsString</code> are illegal
184: */
185: void setValuesAsString(String[] valuesAsString)
186: throws IllegalStringValuesException;
187:
188: /**
189: * Returns the values of the property as an array of <code>Object</code>.
190: *
191: * @return the values of the property as an array of <code>Object</code>
192: * @throws java.lang.UnsupportedOperationException if the operation is not
193: * supported by this property
194: */
195: Object[] getValuesAsObject();
196:
197: /**
198: * Sets the values of the property as an array of <code>Object</code>. It
199: * is possible to pass an array of 0 elements.
200: *
201: * @param values the values of the property as an array of
202: * <code>Object</code>
203: * @throws java.lang.IllegalArgumentException if the type of the values
204: * in the array <code>values</code> is not consistent (see
205: * concrete implementations)
206: * @throws java.lang.UnsupportedOperationException if the operation is not
207: * supported by this property
208: */
209: void setValuesAsObject(Object[] values);
210:
211: /**
212: * Returns the property specified by the relative name
213: * <code>relativeName</code>. The first simple name (the string before
214: * the first ".", if any) must be an index for refering to the ist-element.
215: * So, in the second example (see above), the relative name "1.keywords",
216: * applied to the multivalued compound property "savedSearchesProperties",
217: * returns the simple property "keywords" of the second value of
218: * "savedSearchesProperties".
219: * <p>
220: * If the relative name passed as a parameter is <code>""</code>, the
221: * method returns this same property.
222: *
223: * @param relativeName the relative name of the property
224: * @return the named property
225: * @throws java.lang.UnsupportedOperationException if the operation is not
226: * supported by this property
227: * @throws PropertyNotFoundException if there not exist a property with
228: * this name
229: */
230: Property findProperty(String relativeName)
231: throws PropertyNotFoundException;
232: }
|