KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > pref > Domain


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56 package org.objectstyle.cayenne.pref;
57
58 import java.util.ArrayList JavaDoc;
59 import java.util.Collection JavaDoc;
60 import java.util.Collections JavaDoc;
61 import java.util.HashMap JavaDoc;
62 import java.util.Iterator JavaDoc;
63 import java.util.List JavaDoc;
64 import java.util.Map JavaDoc;
65
66 import org.objectstyle.cayenne.CayenneRuntimeException;
67 import org.objectstyle.cayenne.DataObjectUtils;
68 import org.objectstyle.cayenne.access.DataContext;
69 import org.objectstyle.cayenne.exp.Expression;
70 import org.objectstyle.cayenne.exp.ExpressionFactory;
71 import org.objectstyle.cayenne.map.DbAttribute;
72 import org.objectstyle.cayenne.map.DbEntity;
73 import org.objectstyle.cayenne.query.SelectQuery;
74 import org.objectstyle.cayenne.util.Util;
75
76 /**
77  * Preferences "domain" is logical area for preferences storage. Domains are organized in
78  * a tree hierarchy allowing cascading preferences lookup.
79  *
80  * @author Andrei Adamchik
81  */

82 public class Domain extends _Domain {
83
84     /**
85      * Renames this domain. If there is a sibling domain with same name, such sibling is
86      * renamed using generated unique name. This operation essentially substitutes one
87      * domain subtree with another.
88      */

89     public void rename(String JavaDoc newName) {
90         if (Util.nullSafeEquals(getName(), newName)) {
91             return;
92         }
93
94         Domain parent = getParentDomain();
95         if (parent == null) {
96             setName(newName);
97             return;
98         }
99
100         Domain other = parent.getSubdomain(newName, false);
101         if (other != null && other != this) {
102             String JavaDoc otherName = null;
103             for (int i = 1; i < 1000; i++) {
104                 if (parent.getSubdomain(newName + i, false) == null) {
105                     otherName = newName + i;
106                     break;
107                 }
108             }
109
110             if (otherName == null) {
111                 throw new PreferenceException("Can't rename an existing domain '"
112                         + newName
113                         + "'.");
114             }
115
116             other.setName(otherName);
117         }
118         setName(newName);
119     }
120
121     /**
122      * Returns a direct child of this domain that should handle preferences for all
123      * instances of a given Java class. Creates such subdomain if it doesn't exist.
124      */

125     public Domain getSubdomain(Class JavaDoc javaClass) {
126         return getSubdomain(javaClass.getName());
127     }
128
129     /**
130      * Returns named subdomain. Creates such subdomain if it doesn't exist. Named
131      * subdomains are useful when preferences have to be assigned based on a more
132      * fine-grained criteria than a Java class. E.g. a class Project can have preferences
133      * subdomain for each project location.
134      */

135     public Domain getSubdomain(String JavaDoc subdomainName) {
136         return getSubdomain(subdomainName, true);
137     }
138
139     public Domain getSubdomain(String JavaDoc subdomainName, boolean create) {
140         List JavaDoc subdomains = getSubdomains();
141
142         if (subdomains.size() > 0) {
143             List JavaDoc matching = ExpressionFactory.matchExp(
144                     Domain.NAME_PROPERTY,
145                     subdomainName).filterObjects(subdomains);
146             if (matching.size() > 0) {
147                 return (Domain) matching.get(0);
148             }
149         }
150
151         if (!create) {
152             return null;
153         }
154
155         Domain childSubdomain = (Domain) getDataContext().createAndRegisterNewObject(
156                 Domain.class);
157         addToSubdomains(childSubdomain);
158         childSubdomain.setName(subdomainName);
159
160         if (getLevel() == null) {
161             throw new CayenneRuntimeException("Null level, can't create child");
162         }
163
164         int level = getLevel().intValue() + 1;
165         childSubdomain.setLevel(new Integer JavaDoc(level));
166         getDataContext().commitChanges();
167
168         return childSubdomain;
169     }
170
171     /**
172      * Returns all generic preferences for the domain.
173      */

174     public List JavaDoc getDetails() {
175         Collection JavaDoc domainPrefs = getPreferences();
176
177         if (domainPrefs.isEmpty()) {
178             // return mutable list
179
return new ArrayList JavaDoc(1);
180         }
181
182         List JavaDoc details = new ArrayList JavaDoc(domainPrefs.size());
183         Iterator JavaDoc it = domainPrefs.iterator();
184         while (it.hasNext()) {
185             DomainPreference preference = (DomainPreference) it.next();
186             details.add(preference.getPreference());
187         }
188         return details;
189     }
190
191     /**
192      * Returns a preference object used to read/write properties.
193      */

194     public PreferenceDetail getDetail(String JavaDoc key, boolean create) {
195         return getDetail(key, null, create);
196     }
197
198     /**
199      * Returns all stored PreferenceDetails for a given class in this Domain.
200      */

201     public Collection JavaDoc getDetails(Class JavaDoc javaClass) {
202         // extract preference ids, and then fetch matching prefrences...
203
Collection JavaDoc preferences = getPreferences();
204         if (preferences.isEmpty()) {
205             return Collections.EMPTY_LIST;
206         }
207
208         Collection JavaDoc ids = new ArrayList JavaDoc(preferences.size());
209         Iterator JavaDoc it = preferences.iterator();
210         while (it.hasNext()) {
211             DomainPreference pref = (DomainPreference) it.next();
212             ids.add(DataObjectUtils.pkForObject(pref));
213         }
214
215         DataContext context = getDataContext();
216         DbEntity entity = context.getEntityResolver().lookupDbEntity(javaClass);
217         DbAttribute pk = (DbAttribute) entity.getPrimaryKey().get(0);
218
219         Expression qualifier = Expression.fromString("db:" + pk.getName() + " in $ids");
220         Map JavaDoc params = Collections.singletonMap("ids", ids);
221         SelectQuery query = new SelectQuery(javaClass, qualifier
222                 .expWithParameters(params));
223         return context.performQuery(query);
224     }
225
226     /**
227      * Returns preference details keyed using their master key.
228      */

229     public Map JavaDoc getDetailsMap(Class JavaDoc javaClass) {
230         Collection JavaDoc details = getDetails(javaClass);
231         Map JavaDoc map = new HashMap JavaDoc();
232
233         if (details.isEmpty()) {
234             return map;
235         }
236
237         Iterator JavaDoc it = details.iterator();
238         while (it.hasNext()) {
239             PreferenceDetail detail = (PreferenceDetail) it.next();
240             map.put(detail.getKey(), detail);
241         }
242
243         return map;
244     }
245
246     /**
247      * Locates a PreferenceDetail in a current Domain for a given key and Java class. If
248      * no such preference found, and "create" is true, a new preference is created. If an
249      * existing preference class does not match supplied class, PreferenceException is
250      * thrown.
251      */

252     public PreferenceDetail getDetail(String JavaDoc key, Class JavaDoc javaClass, boolean create) {
253         DomainPreference preferenceLink = getDomainPreference(key);
254
255         if (preferenceLink == null) {
256
257             if (!create) {
258                 return null;
259             }
260
261             preferenceLink = (DomainPreference) getDataContext()
262                     .createAndRegisterNewObject(DomainPreference.class);
263             preferenceLink.setDomain(this);
264             preferenceLink.setKey(key);
265             getDataContext().commitChanges();
266         }
267
268         return (javaClass == null) ? preferenceLink.getPreference() : preferenceLink
269                 .getPreference(javaClass, create);
270     }
271
272     /**
273      * Looks up a preference for key in the domain hierarchy.
274      */

275     DomainPreference getDomainPreference(String JavaDoc key) {
276         // query sorts preferences by subdomain level, so the first object is the lowest
277
// one
278
Map JavaDoc params = new HashMap JavaDoc();
279         params.put("key", key);
280         params.put("domain", this);
281         List JavaDoc results = getDataContext().performQuery(
282                 "DomainPreferenceForKey",
283                 params,
284                 false);
285         return (results.size() < 1) ? null : (DomainPreference) results.get(0);
286     }
287 }
288
289
Popular Tags