Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/objectstyle/cayenne/project/NamedObjectFactory.java


1   /* ====================================================================
2    * 
3    * The ObjectStyle Group Software License, Version 1.0 
4    *
5    * Copyright (c) 2002-2003 The ObjectStyle Group 
6    * and individual authors of the software.  All rights reserved.
7    *
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   * 1. Redistributions of source code must retain the above copyright
13   *    notice, this list of conditions and the following disclaimer. 
14   *
15   * 2. Redistributions in binary form must reproduce the above copyright
16   *    notice, this list of conditions and the following disclaimer in
17   *    the documentation and/or other materials provided with the
18   *    distribution.
19   *
20   * 3. The end-user documentation included with the redistribution, if
21   *    any, must include the following acknowlegement:  
22   *       "This product includes software developed by the 
23   *        ObjectStyle Group (http://objectstyle.org/)."
24   *    Alternately, this acknowlegement may appear in the software itself,
25   *    if and wherever such third-party acknowlegements normally appear.
26   *
27   * 4. The names "ObjectStyle Group" and "Cayenne" 
28   *    must not be used to endorse or promote products derived
29   *    from this software without prior written permission. For written 
30   *    permission, please contact andrus@objectstyle.org.
31   *
32   * 5. Products derived from this software may not be called "ObjectStyle"
33   *    nor may "ObjectStyle" appear in their names without prior written
34   *    permission of the ObjectStyle Group.
35   *
36   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39   * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
40   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47   * SUCH DAMAGE.
48   * ====================================================================
49   *
50   * This software consists of voluntary contributions made by many
51   * individuals on behalf of the ObjectStyle Group.  For more
52   * information on the ObjectStyle Group, please see
53   * <http://objectstyle.org/>.
54   *
55   */
56  package org.objectstyle.cayenne.project;
57  
58  import java.util.HashMap;
59  import java.util.Iterator;
60  import java.util.Map;
61  
62  import org.objectstyle.cayenne.access.DataDomain;
63  import org.objectstyle.cayenne.access.DataNode;
64  import org.objectstyle.cayenne.conf.Configuration;
65  import org.objectstyle.cayenne.dba.TypesMapping;
66  import org.objectstyle.cayenne.map.DataMap;
67  import org.objectstyle.cayenne.map.DbAttribute;
68  import org.objectstyle.cayenne.map.DbEntity;
69  import org.objectstyle.cayenne.map.DbRelationship;
70  import org.objectstyle.cayenne.map.DerivedDbAttribute;
71  import org.objectstyle.cayenne.map.DerivedDbEntity;
72  import org.objectstyle.cayenne.map.Entity;
73  import org.objectstyle.cayenne.map.ObjAttribute;
74  import org.objectstyle.cayenne.map.ObjEntity;
75  import org.objectstyle.cayenne.map.ObjRelationship;
76  import org.objectstyle.cayenne.map.Procedure;
77  import org.objectstyle.cayenne.map.ProcedureParameter;
78  import org.objectstyle.cayenne.map.Relationship;
79  
80  /** 
81   * Factory class that generates various Cayenne objects with 
82   * default names that are unique in their corresponding context. 
83   * Supports creation of the following
84   * objects:
85   * <ul>
86   *    <li>DataMap</li>
87   *    <li>ObjEntity</li>
88   *    <li>ObjAttribute</li>
89   *    <li>ObjRelationship</li>
90   *    <li>DbEntity</li>
91   *    <li>DerivedDbEntity</li>
92   *    <li>DbAttribute</li>
93   *    <li>DerivedDbAttribute</li>
94   *    <li>DbRelationship</li>
95   *    <li>DataNode</li>
96   *    <li>DataDomain</li>
97   *     <li>Procedure</li>
98   *    <li>ProcedureParameter</li>
99   * </ul>
100  * 
101  * This is a helper class used mostly by GUI and database 
102  * reengineering classes.
103  * 
104  * @author Andrei Adamchik
105  */
106 public abstract class NamedObjectFactory {
107     private static final Map factories = new HashMap();
108 
109     static {
110         factories.put(DataMap.class, new DataMapFactory());
111         factories.put(ObjEntity.class, new ObjEntityFactory());
112         factories.put(DbEntity.class, new DbEntityFactory());
113         factories.put(DerivedDbEntity.class, new DerivedDbEntityFactory());
114         factories.put(ObjAttribute.class, new ObjAttributeFactory());
115         factories.put(DbAttribute.class, new DbAttributeFactory());
116         factories.put(DerivedDbAttribute.class, new DerivedDbAttributeFactory());
117         factories.put(DataNode.class, new DataNodeFactory());
118         factories.put(DbRelationship.class, new DbRelationshipFactory(null, false));
119         factories.put(ObjRelationship.class, new ObjRelationshipFactory(null, false));
120         factories.put(DataDomain.class, new DataDomainFactory());
121         factories.put(Procedure.class, new ProcedureFactory());
122         factories.put(ProcedureParameter.class, new ProcedureParameterFactory());
123     }
124 
125     public static String createName(Class objectClass, Object namingContext) {
126         return ((NamedObjectFactory) factories.get(objectClass)).makeName(namingContext);
127     }
128 
129     /**
130      * Creates an object using an appropriate factory class.
131      * If no factory is found for the object, NullPointerException is 
132      * thrown. 
133      * 
134      * <p><i>Note that newly created object is not added to the parent.
135      * This behavior can be changed later.</i></p>
136      */
137     public static Object createObject(Class objectClass, Object namingContext) {
138         return ((NamedObjectFactory) factories.get(objectClass)).makeObject(
139             namingContext);
140     }
141 
142     /**
143      * Creates a relationship using an appropriate factory class.
144      * If no factory is found for the object, NullPointerException is 
145      * thrown. 
146      * 
147      * <p><i>Note that newly created object is not added to the parent.
148      * This behavior can be changed later.</i></p>
149      */
150     public static Relationship createRelationship(
151         Entity srcEnt,
152         Entity targetEnt,
153         boolean toMany) {
154         NamedObjectFactory factory =
155             (srcEnt instanceof ObjEntity)
156                 ? new ObjRelationshipFactory(targetEnt, toMany)
157                 : new DbRelationshipFactory(targetEnt, toMany);
158         return (Relationship) factory.makeObject(srcEnt);
159     }
160 
161     /**
162      * Creates a unique name for the new object and constructs
163      * this object.
164      */
165     protected synchronized String makeName(Object namingContext) {
166         int c = 1;
167         String name = null;
168         do {
169             name = nameBase() + c++;
170         }
171         while (isNameInUse(name, namingContext));
172 
173         return name;
174     }
175 
176     /**
177      * Creates a unique name for the new object and constructs
178      * this object.
179      */
180     protected Object makeObject(Object namingContext) {
181         return create(makeName(namingContext), namingContext);
182     }
183 
184     /** Returns a base default name, like "UntitledEntity", etc. */
185     protected abstract String nameBase();
186 
187     /** Internal factory method. Invoked after the name is figured out. */
188     protected abstract Object create(String name, Object namingContext);
189 
190     /** 
191      * Checks if the name is already taken by another sibling
192      * in the same context.
193      */
194     protected abstract boolean isNameInUse(String name, Object namingContext);
195 
196     // concrete factories
197     static class DataDomainFactory extends NamedObjectFactory {
198         protected String nameBase() {
199             return "UntitledDomain";
200         }
201 
202         protected Object create(String name, Object namingContext) {
203             return new DataDomain(name);
204         }
205 
206         protected boolean isNameInUse(String name, Object namingContext) {
207             Configuration config = (Configuration) namingContext;
208             return config.getDomain(name) != null;
209         }
210     }
211 
212     static class DataMapFactory extends NamedObjectFactory {
213         protected String nameBase() {
214             return "UntitledMap";
215         }
216 
217         protected Object create(String name, Object namingContext) {
218             return new DataMap(name);
219         }
220 
221         protected boolean isNameInUse(String name, Object namingContext) {
222             // null context is a situation when DataMap is a
223             // top level object of the project
224             if (namingContext == null) {
225                 return false;
226             }
227 
228             DataDomain domain = (DataDomain) namingContext;
229             return domain.getMap(name) != null;
230         }
231     }
232 
233     static class ObjEntityFactory extends NamedObjectFactory {
234         protected String nameBase() {
235             return "UntitledObjEntity";
236         }
237 
238         protected Object create(String name, Object namingContext) {
239             return new ObjEntity(name);
240         }
241 
242         protected boolean isNameInUse(String name, Object namingContext) {
243             DataMap map = (DataMap) namingContext;
244             return map.getObjEntity(name) != null;
245         }
246     }
247 
248     static class DbEntityFactory extends NamedObjectFactory {
249         protected String nameBase() {
250             return "UntitledDbEntity";
251         }
252 
253         protected Object create(String name, Object namingContext) {
254             return new DbEntity(name);
255         }
256 
257         protected boolean isNameInUse(String name, Object namingContext) {
258             DataMap map = (DataMap) namingContext;
259             return map.getDbEntity(name) != null;
260         }
261     }
262 
263     static class ProcedureParameterFactory extends NamedObjectFactory {
264         protected String nameBase() {
265             return "UntitledProcedureParameter";
266         }
267 
268         protected Object create(String name, Object namingContext) {
269             return new ProcedureParameter(name);
270         }
271 
272         protected boolean isNameInUse(String name, Object namingContext) {
273           
274             // it doesn't matter if we create a parameter with 
275             // a duplicate name.. parameters are positional anyway..
276             // still try to use unique names for visual consistency
277             Procedure procedure = (Procedure) namingContext;
278             Iterator it = procedure.getCallParameters().iterator();
279             while (it.hasNext()) {
280                 ProcedureParameter parameter = (ProcedureParameter) it.next();
281                 if (name.equals(parameter.getName())) {
282                     return true;
283                 }
284             }
285 
286             return false;
287         }
288     }
289 
290     static class ProcedureFactory extends NamedObjectFactory {
291         protected String nameBase() {
292             return "UntitledProcedure";
293         }
294 
295         protected Object create(String name, Object namingContext) {
296             return new Procedure(name);
297         }
298 
299         protected boolean isNameInUse(String name, Object namingContext) {
300             DataMap map = (DataMap) namingContext;
301             return map.getProcedure(name) != null;
302         }
303     }
304 
305     static class DerivedDbEntityFactory extends DbEntityFactory {
306         protected Object create(String name, Object namingContext) {
307             return new DerivedDbEntity(name);
308         }
309     }
310 
311     static class ObjAttributeFactory extends NamedObjectFactory {
312         protected String nameBase() {
313             return "UntitledAttr";
314         }
315 
316         protected Object create(String name, Object namingContext) {
317             return new ObjAttribute(name, null, (ObjEntity) namingContext);
318         }
319 
320         protected boolean isNameInUse(String name, Object namingContext) {
321             Entity ent = (Entity) namingContext;
322             return ent.getAttribute(name) != null;
323         }
324     }
325 
326     static class DbAttributeFactory extends ObjAttributeFactory {
327         protected Object create(String name, Object namingContext) {
328             return new DbAttribute(
329                 name,
330                 TypesMapping.NOT_DEFINED,
331                 (DbEntity) namingContext);
332         }
333     }
334 
335     static class DerivedDbAttributeFactory extends ObjAttributeFactory {
336         protected Object create(String name, Object namingContext) {
337             return new DerivedDbAttribute(
338                 name,
339                 TypesMapping.NOT_DEFINED,
340                 (DbEntity) namingContext,
341                 DerivedDbAttribute.ATTRIBUTE_TOKEN);
342         }
343     }
344 
345     static class DataNodeFactory extends NamedObjectFactory {
346         protected String nameBase() {
347             return "UntitledDataNode";
348         }
349 
350         protected Object create(String name, Object namingContext) {
351             return new DataNode(name);
352         }
353 
354         protected boolean isNameInUse(String name, Object namingContext) {
355             DataDomain domain = (DataDomain) namingContext;
356             return domain.getNode(name) != null;
357         }
358     }
359 
360     static class ObjRelationshipFactory extends NamedObjectFactory {
361         protected Entity target;
362         protected boolean toMany;
363 
364         public ObjRelationshipFactory(Entity target, boolean toMany) {
365             this.target = target;
366             this.toMany = toMany;
367         }
368 
369         protected Object create(String name, Object namingContext) {
370             return new ObjRelationship(name);
371         }
372 
373         protected boolean isNameInUse(String name, Object namingContext) {
374             Entity ent = (Entity) namingContext;
375             return ent.getRelationship(name) != null;
376         }
377 
378         /** 
379          * Returns generated name for the ObjRelationships. 
380          * For to-one case and entity name "xxxx" it generates name "toXxxx".
381          * For to-many case and entity name "Xxxx" it generates name "xxxxArray".
382          */
383         protected String nameBase() {
384             if (target == null) {
385                 return "UntitledRel";
386             }
387 
388             String name = target.getName();
389             return (toMany)
390                 ? Character.toLowerCase(name.charAt(0)) + name.substring(1) + "Array"
391                 : "to" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
392         }
393     }
394 
395     static class DbRelationshipFactory extends ObjRelationshipFactory {
396         public DbRelationshipFactory(Entity target, boolean toMany) {
397             super(target, toMany);
398         }
399 
400         protected Object create(String name, Object namingContext) {
401             return new DbRelationship(name);
402         }
403 
404         /** 
405          * Returns generated name for the DbRelationships. 
406          * For to-one case it generates name "TO_XXXX".
407          * For to-many case it generates name "XXXX_ARRAY". 
408          */
409         protected String nameBase() {
410             if (target == null) {
411                 return "UntitledRel";
412             }
413 
414             String name = target.getName();
415             return (toMany) ? name + "_ARRAY" : "TO_" + name;
416         }
417     }
418 }