KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > map > DataMap


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.map;
21
22 import java.io.PrintWriter JavaDoc;
23 import java.io.Serializable JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Collection JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.SortedMap JavaDoc;
31 import java.util.TreeMap JavaDoc;
32
33 import org.apache.cayenne.map.event.AttributeEvent;
34 import org.apache.cayenne.map.event.DbAttributeListener;
35 import org.apache.cayenne.map.event.DbEntityListener;
36 import org.apache.cayenne.map.event.DbRelationshipListener;
37 import org.apache.cayenne.map.event.EntityEvent;
38 import org.apache.cayenne.map.event.ObjAttributeListener;
39 import org.apache.cayenne.map.event.ObjEntityListener;
40 import org.apache.cayenne.map.event.ObjRelationshipListener;
41 import org.apache.cayenne.map.event.RelationshipEvent;
42 import org.apache.cayenne.project.Project;
43 import org.apache.cayenne.query.NamedQuery;
44 import org.apache.cayenne.query.Query;
45 import org.apache.cayenne.util.Util;
46 import org.apache.cayenne.util.XMLEncoder;
47 import org.apache.cayenne.util.XMLSerializable;
48 import org.apache.commons.lang.builder.ToStringBuilder;
49
50 /**
51  * Stores a collection of related mapping objects that describe database and object layers
52  * of an application. DataMap contains DbEntities mapping database tables, ObjEntities -
53  * mapping persistent Java classes, Procedures - mapping database stored procedures.
54  *
55  * @author Michael Shengaout
56  * @author Andrus Adamchik
57  * @author Craig Miskell
58  */

59 public class DataMap implements Serializable JavaDoc, XMLSerializable, MappingNamespace,
60         DbEntityListener, DbAttributeListener, DbRelationshipListener, ObjEntityListener,
61         ObjAttributeListener, ObjRelationshipListener {
62
63     /**
64      * Defines whether a DataMap supports client entities.
65      *
66      * @since 1.2
67      */

68     public static final String JavaDoc CLIENT_SUPPORTED_PROPERTY = "clientSupported";
69
70     /**
71      * Defines the name of the property for default client Java class package.
72      *
73      * @since 1.2
74      */

75     public static final String JavaDoc DEFAULT_CLIENT_PACKAGE_PROPERTY = "defaultClientPackage";
76
77     /**
78      * Defines the name of the property for default DB schema.
79      *
80      * @since 1.1
81      */

82     public static final String JavaDoc DEFAULT_SCHEMA_PROPERTY = "defaultSchema";
83
84     /**
85      * Defines the name of the property for default Java class package.
86      *
87      * @since 1.1
88      */

89     public static final String JavaDoc DEFAULT_PACKAGE_PROPERTY = "defaultPackage";
90
91     /**
92      * Defines the name of the property for default DB schema.
93      *
94      * @since 1.1
95      */

96     public static final String JavaDoc DEFAULT_SUPERCLASS_PROPERTY = "defaultSuperclass";
97
98     /**
99      * Defines the name of the property for default DB schema.
100      *
101      * @since 1.1
102      */

103     public static final String JavaDoc DEFAULT_LOCK_TYPE_PROPERTY = "defaultLockType";
104
105     protected String JavaDoc name;
106     protected String JavaDoc location;
107     protected MappingNamespace namespace;
108
109     protected String JavaDoc defaultSchema;
110     protected String JavaDoc defaultPackage;
111     protected String JavaDoc defaultSuperclass;
112     protected int defaultLockType;
113
114     protected boolean clientSupported;
115     protected String JavaDoc defaultClientPackage;
116
117     private SortedMap JavaDoc embeddablesMap;
118     private SortedMap JavaDoc entityListenersMap;
119     private SortedMap JavaDoc objEntityMap;
120     private SortedMap JavaDoc dbEntityMap;
121     private SortedMap JavaDoc procedureMap;
122     private SortedMap JavaDoc queryMap;
123
124     private List JavaDoc defaultEntityListeners;
125
126     /**
127      * Creates a new unnamed DataMap.
128      */

129     public DataMap() {
130         this(null);
131     }
132
133     /**
134      * Creates a new named DataMap.
135      */

136     public DataMap(String JavaDoc mapName) {
137         this(mapName, Collections.EMPTY_MAP);
138     }
139
140     public DataMap(String JavaDoc mapName, Map JavaDoc properties) {
141         embeddablesMap = new TreeMap JavaDoc();
142         entityListenersMap = new TreeMap JavaDoc();
143         objEntityMap = new TreeMap JavaDoc();
144         dbEntityMap = new TreeMap JavaDoc();
145         procedureMap = new TreeMap JavaDoc();
146         queryMap = new TreeMap JavaDoc();
147         defaultEntityListeners = new ArrayList JavaDoc(3);
148
149         setName(mapName);
150         initWithProperties(properties);
151     }
152
153     /**
154      * Performs DataMap initialization from a set of properties, using defaults for the
155      * missing properties.
156      *
157      * @since 1.1
158      */

159     public void initWithProperties(Map JavaDoc properties) {
160         // must init defaults even if properties are empty
161
if (properties == null) {
162             properties = Collections.EMPTY_MAP;
163         }
164
165         Object JavaDoc lockType = properties.get(DEFAULT_LOCK_TYPE_PROPERTY);
166         Object JavaDoc packageName = properties.get(DEFAULT_PACKAGE_PROPERTY);
167         Object JavaDoc schema = properties.get(DEFAULT_SCHEMA_PROPERTY);
168         Object JavaDoc superclass = properties.get(DEFAULT_SUPERCLASS_PROPERTY);
169         Object JavaDoc clientEntities = properties.get(CLIENT_SUPPORTED_PROPERTY);
170         Object JavaDoc clientPackageName = properties.get(DEFAULT_CLIENT_PACKAGE_PROPERTY);
171
172         this.defaultLockType = "optimistic".equals(lockType)
173                 ? ObjEntity.LOCK_TYPE_OPTIMISTIC
174                 : ObjEntity.LOCK_TYPE_NONE;
175
176         this.defaultPackage = (packageName != null) ? packageName.toString() : null;
177         this.defaultSchema = (schema != null) ? schema.toString() : null;
178         this.defaultSuperclass = (superclass != null) ? superclass.toString() : null;
179         this.clientSupported = (clientEntities != null) ? "true"
180                 .equalsIgnoreCase(clientEntities.toString()) : false;
181         this.defaultClientPackage = (clientPackageName != null) ? clientPackageName
182                 .toString() : null;
183     }
184
185     /**
186      * Returns a DataMap stripped of any server-side information, such as DbEntity
187      * mapping, or ObjEntities that are not allowed in the client tier. Returns null if
188      * this DataMap as a whole does not support client tier persistence.
189      *
190      * @since 1.2
191      */

192     public DataMap getClientDataMap(EntityResolver serverResolver) {
193         if (!isClientSupported()) {
194             return null;
195         }
196
197         DataMap clientMap = new DataMap(getName());
198
199         // create client entities for entities
200
Iterator JavaDoc entities = getObjEntities().iterator();
201         while (entities.hasNext()) {
202             ObjEntity entity = (ObjEntity) entities.next();
203             if (entity.isClientAllowed()) {
204                 clientMap.addObjEntity(entity.getClientEntity());
205             }
206         }
207
208         // create proxies for named queries
209
Iterator JavaDoc queries = getQueries().iterator();
210         while (queries.hasNext()) {
211             Query q = (Query) queries.next();
212             NamedQuery proxy = new NamedQuery(q.getName());
213             proxy.setName(q.getName());
214
215             // resolve metadata so that client can have access to it without knowing about
216
// the server query.
217
proxy.initMetadata(q.getMetaData(serverResolver));
218             clientMap.addQuery(proxy);
219         }
220
221         return clientMap;
222     }
223
224     /**
225      * Prints itself as a well-formed complete XML document. In comparison,
226      * {@link #encodeAsXML(XMLEncoder)}stores DataMap assuming it is a part of a bigger
227      * document.
228      *
229      * @since 1.1
230      */

231     public void encodeAsXML(PrintWriter JavaDoc pw) {
232         XMLEncoder encoder = new XMLEncoder(pw, "\t");
233         encoder.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
234         encodeAsXML(encoder);
235     }
236
237     /**
238      * Prints itself as XML to the provided PrintWriter.
239      *
240      * @since 1.1
241      */

242     public void encodeAsXML(XMLEncoder encoder) {
243         encoder.print("<data-map project-version=\"");
244         encoder.print(String.valueOf(Project.CURRENT_PROJECT_VERSION));
245         encoder.println("\">");
246
247         encoder.indent(1);
248
249         // properties
250
if (defaultLockType == ObjEntity.LOCK_TYPE_OPTIMISTIC) {
251             encoder.printProperty(DEFAULT_LOCK_TYPE_PROPERTY, "optimistic");
252         }
253
254         if (!Util.isEmptyString(defaultPackage)) {
255             encoder.printProperty(DEFAULT_PACKAGE_PROPERTY, defaultPackage);
256         }
257
258         if (!Util.isEmptyString(defaultSchema)) {
259             encoder.printProperty(DEFAULT_SCHEMA_PROPERTY, defaultSchema);
260         }
261
262         if (!Util.isEmptyString(defaultSuperclass)) {
263             encoder.printProperty(DEFAULT_SUPERCLASS_PROPERTY, defaultSuperclass);
264         }
265
266         if (clientSupported) {
267             encoder.printProperty(CLIENT_SUPPORTED_PROPERTY, "true");
268         }
269
270         if (!Util.isEmptyString(defaultClientPackage)) {
271             encoder.printProperty(DEFAULT_CLIENT_PACKAGE_PROPERTY, defaultClientPackage);
272         }
273
274         // embeddables
275
encoder.print(getEmbeddableMap());
276
277         // procedures
278
encoder.print(getProcedureMap());
279
280         // DbEntities
281
boolean hasDerived = false;
282         Iterator JavaDoc dbEntities = getDbEntityMap().entrySet().iterator();
283         while (dbEntities.hasNext()) {
284             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) dbEntities.next();
285             DbEntity dbe = (DbEntity) entry.getValue();
286
287             // skip derived, store them after regular DbEntities
288
if (dbe instanceof DerivedDbEntity) {
289                 hasDerived = true;
290             }
291             else {
292                 dbe.encodeAsXML(encoder);
293             }
294         }
295
296         // DerivedDbEntities
297
if (hasDerived) {
298             Iterator JavaDoc derivedDbEntities = getDbEntityMap().entrySet().iterator();
299             while (derivedDbEntities.hasNext()) {
300                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) derivedDbEntities.next();
301                 DbEntity dbe = (DbEntity) entry.getValue();
302
303                 // only store derived...
304
if (dbe instanceof DerivedDbEntity) {
305                     dbe.encodeAsXML(encoder);
306                 }
307             }
308         }
309
310         // others...
311
encoder.print(getObjEntityMap());
312         encodeDBRelationshipsAsXML(getDbEntityMap(), encoder);
313         encodeOBJRelationshipsAsXML(getObjEntityMap(), encoder);
314         encoder.print(getQueryMap());
315
316         encoder.indent(-1);
317         encoder.println("</data-map>");
318     }
319
320     // stores relationships of for the map of entities
321
private final void encodeDBRelationshipsAsXML(Map JavaDoc entityMap, XMLEncoder encoder) {
322         Iterator JavaDoc it = entityMap.entrySet().iterator();
323         while (it.hasNext()) {
324             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
325             Entity entity = (Entity) entry.getValue();
326             encoder.print(entity.getRelationships());
327         }
328     }
329
330     // stores relationships of for the map of entities
331
private final void encodeOBJRelationshipsAsXML(Map JavaDoc entityMap, XMLEncoder encoder) {
332         Iterator JavaDoc it = entityMap.entrySet().iterator();
333         while (it.hasNext()) {
334             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
335             ObjEntity entity = (ObjEntity) entry.getValue();
336             encoder.print(entity.getDeclaredRelationships());
337         }
338     }
339
340     public String JavaDoc toString() {
341         return new ToStringBuilder(this).append("name", getName()).toString();
342     }
343
344     /**
345      * Returns the name of this DataMap.
346      */

347     public String JavaDoc getName() {
348         return name;
349     }
350
351     public void setName(String JavaDoc name) {
352         this.name = name;
353     }
354
355     /**
356      * Adds all Object and DB entities and Queries from another map to this map.
357      * Overwrites all existing entities and queries with the new ones.
358      * <p>
359      * <i>TODO: will need to implement advanced merge that allows different policies for
360      * overwriting entities / queries. </i>
361      * </p>
362      */

363     public void mergeWithDataMap(DataMap map) {
364         Iterator JavaDoc dbs = new ArrayList JavaDoc(map.getDbEntities()).iterator();
365         while (dbs.hasNext()) {
366             DbEntity ent = (DbEntity) dbs.next();
367             this.removeDbEntity(ent.getName());
368             this.addDbEntity(ent);
369         }
370
371         Iterator JavaDoc objs = new ArrayList JavaDoc(map.getObjEntities()).iterator();
372         while (objs.hasNext()) {
373             ObjEntity ent = (ObjEntity) objs.next();
374             this.removeObjEntity(ent.getName());
375             this.addObjEntity(ent);
376         }
377
378         Iterator JavaDoc queries = new ArrayList JavaDoc(map.getQueries()).iterator();
379         while (queries.hasNext()) {
380             Query query = (Query) queries.next();
381             this.removeQuery(query.getName());
382             this.addQuery(query);
383         }
384     }
385
386     /**
387      * Returns "location" property value. Location is abstract and can depend on how the
388      * DataMap was loaded. E.g. location can be a File on the filesystem or a location
389      * within a JAR.
390      */

391     public String JavaDoc getLocation() {
392         return location;
393     }
394
395     /**
396      * Sets "location" property.
397      */

398     public void setLocation(String JavaDoc location) {
399         this.location = location;
400     }
401
402     /**
403      * Returns a sorted unmodifiable map of ObjEntities contained in this DataMap, keyed
404      * by ObjEntity name.
405      */

406     public SortedMap JavaDoc getObjEntityMap() {
407         return Collections.unmodifiableSortedMap(objEntityMap);
408     }
409
410     /**
411      * Returns a sorted unmodifiable map of DbEntities contained in this DataMap, keyed by
412      * DbEntity name.
413      */

414     public SortedMap JavaDoc getDbEntityMap() {
415         return Collections.unmodifiableSortedMap(dbEntityMap);
416     }
417
418     /**
419      * Returns a named query associated with this DataMap.
420      *
421      * @since 1.1
422      */

423     public Query getQuery(String JavaDoc queryName) {
424         Query query = (Query) queryMap.get(queryName);
425         if (query != null) {
426             return query;
427         }
428
429         return namespace != null ? namespace.getQuery(queryName) : null;
430     }
431
432     /**
433      * Stores a query under its name.
434      *
435      * @since 1.1
436      */

437     public void addQuery(Query query) {
438         if (query == null) {
439             throw new NullPointerException JavaDoc("Can't add null query.");
440         }
441
442         if (query.getName() == null) {
443             throw new NullPointerException JavaDoc("Query name can't be null.");
444         }
445
446         // TODO: change method signature to return replaced procedure and make sure the
447
// Modeler handles it...
448
Object JavaDoc existingQuery = queryMap.get(query.getName());
449         if (existingQuery != null) {
450             if (existingQuery == query) {
451                 return;
452             }
453             else {
454                 throw new IllegalArgumentException JavaDoc("An attempt to override entity '"
455                         + query.getName());
456             }
457         }
458
459         queryMap.put(query.getName(), query);
460     }
461
462     /**
463      * Removes a named query from the DataMap.
464      *
465      * @since 1.1
466      */

467     public void removeQuery(String JavaDoc queryName) {
468         queryMap.remove(queryName);
469     }
470
471     /**
472      * Removes all stored embeddable objects from the map.
473      *
474      * @since 3.0
475      */

476     public void clearEmbeddables() {
477         embeddablesMap.clear();
478     }
479
480     /**
481      * Removes all stored entity listeners from the map.
482      *
483      * @since 3.0
484      */

485     public void clearEntityListeners() {
486         entityListenersMap.clear();
487     }
488
489     /**
490      * @since 1.1
491      */

492     public void clearQueries() {
493         queryMap.clear();
494     }
495
496     /**
497      * @since 1.2
498      */

499     public void clearObjEntities() {
500         objEntityMap.clear();
501     }
502
503     /**
504      * @since 1.2
505      */

506     public void clearDbEntities() {
507         dbEntityMap.clear();
508     }
509
510     /**
511      * @since 1.2
512      */

513     public void clearProcedures() {
514         procedureMap.clear();
515     }
516
517     /**
518      * @since 1.1
519      */

520     public SortedMap JavaDoc getQueryMap() {
521         return Collections.unmodifiableSortedMap(queryMap);
522     }
523
524     /**
525      * Returns an unmodifiable collection of mapped queries.
526      *
527      * @since 1.1
528      */

529     public Collection JavaDoc getQueries() {
530         return Collections.unmodifiableCollection(queryMap.values());
531     }
532
533     /**
534      * Adds a default entity listener that should be notified of certain events on all
535      * entities.
536      */

537     public void addEntityListener(EntityListener listener) {
538         if (listener == null) {
539             throw new NullPointerException JavaDoc("Null EntityListener");
540         }
541
542         if (listener.getClassName() == null) {
543             throw new NullPointerException JavaDoc(
544                     "Attempt to add EntityListener with no class name.");
545         }
546
547         // TODO: change method signature to return replaced el and make sure the
548
// Modeler handles it...
549
Object JavaDoc existing = embeddablesMap.get(listener.getClassName());
550         if (existing != null) {
551             if (existing == listener) {
552                 return;
553             }
554             else {
555                 throw new IllegalArgumentException JavaDoc("An attempt to override listener '"
556                         + listener.getClassName());
557             }
558         }
559
560         entityListenersMap.put(listener.getClassName(), listener);
561     }
562
563     /**
564      * Removes an {@link EntityListener} descriptor with matching class name from entity
565      * listeners and default entity listeners.
566      *
567      * @since 3.0
568      */

569     public void removeEntityListener(String JavaDoc className) {
570         if (entityListenersMap.remove(className) != null) {
571             removeDefaultEntityListener(className);
572         }
573     }
574
575     /**
576      * Adds an embeddable object to the DataMap.
577      *
578      * @since 3.0
579      */

580     public void addEmbeddable(Embeddable embeddable) {
581         if (embeddable == null) {
582             throw new NullPointerException JavaDoc("Null embeddable");
583         }
584
585         if (embeddable.getClassName() == null) {
586             throw new NullPointerException JavaDoc(
587                     "Attempt to add Embeddable with no class name.");
588         }
589
590         // TODO: change method signature to return replaced entity and make sure the
591
// Modeler handles it...
592
Object JavaDoc existing = embeddablesMap.get(embeddable.getClassName());
593         if (existing != null) {
594             if (existing == embeddable) {
595                 return;
596             }
597             else {
598                 throw new IllegalArgumentException JavaDoc("An attempt to override embeddable '"
599                         + embeddable.getClassName());
600             }
601         }
602
603         embeddablesMap.put(embeddable.getClassName(), embeddable);
604     }
605
606     /**
607      * Adds a new ObjEntity to this DataMap.
608      */

609     public void addObjEntity(ObjEntity entity) {
610         if (entity.getName() == null) {
611             throw new NullPointerException JavaDoc("Attempt to add ObjEntity with no name.");
612         }
613
614         // TODO: change method signature to return replaced entity and make sure the
615
// Modeler handles it...
616
Object JavaDoc existingEntity = objEntityMap.get(entity.getName());
617         if (existingEntity != null) {
618             if (existingEntity == entity) {
619                 return;
620             }
621             else {
622                 throw new IllegalArgumentException JavaDoc("An attempt to override entity '"
623                         + entity.getName());
624             }
625         }
626
627         objEntityMap.put(entity.getName(), entity);
628         entity.setDataMap(this);
629     }
630
631     /**
632      * Adds a new DbEntity to this DataMap.
633      */

634     public void addDbEntity(DbEntity entity) {
635         if (entity.getName() == null) {
636             throw new NullPointerException JavaDoc("Attempt to add DbEntity with no name.");
637         }
638
639         // TODO: change method signature to return replaced entity and make sure the
640
// Modeler handles it...
641
Object JavaDoc existingEntity = dbEntityMap.get(entity.getName());
642         if (existingEntity != null) {
643             if (existingEntity == entity) {
644                 return;
645             }
646             else {
647                 throw new IllegalArgumentException JavaDoc("An attempt to override entity '"
648                         + entity.getName());
649             }
650         }
651
652         dbEntityMap.put(entity.getName(), entity);
653         entity.setDataMap(this);
654     }
655
656     /**
657      * Returns an unmodifiable collection of ObjEntities stored in this DataMap.
658      */

659     public Collection JavaDoc getObjEntities() {
660         return Collections.unmodifiableCollection(objEntityMap.values());
661     }
662
663     /**
664      * @since 3.0
665      */

666     public Map JavaDoc getEmbeddableMap() {
667         return Collections.unmodifiableMap(embeddablesMap);
668     }
669
670     /**
671      * Returns a collection of {@link Embeddable} mappings stored in the DataMap.
672      *
673      * @since 3.0
674      */

675     public Collection JavaDoc getEmbeddables() {
676         return Collections.unmodifiableCollection(embeddablesMap.values());
677     }
678
679     /**
680      * @since 3.0
681      */

682     public Embeddable getEmbeddable(String JavaDoc className) {
683         Embeddable e = (Embeddable) embeddablesMap.get(className);
684         if (e != null) {
685             return e;
686         }
687
688         return namespace != null ? namespace.getEmbeddable(className) : null;
689     }
690
691     /**
692      * @since 3.0
693      */

694     public Map JavaDoc getEntityListenersMap() {
695         return Collections.unmodifiableMap(entityListenersMap);
696     }
697
698     /**
699      * Returns a collection of {@link EntityListener} mappings stored in the DataMap.
700      *
701      * @since 3.0
702      */

703     public Collection JavaDoc getEntityListeners() {
704         return Collections.unmodifiableCollection(entityListenersMap.values());
705     }
706
707     /**
708      * @since 3.0
709      */

710     public EntityListener getEntityListener(String JavaDoc className) {
711         EntityListener e = (EntityListener) entityListenersMap.get(className);
712         if (e != null) {
713             return e;
714         }
715
716         return namespace != null ? namespace.getEntityListener(className) : null;
717     }
718
719     /**
720      * Returns an unmodifiable list of default {@link EntityListener} objects. Note that
721      * since the order of listeners is significant a list, not just a generic Collection
722      * is returned.
723      *
724      * @since 3.0
725      */

726     public List JavaDoc getDefaultEntityListeners() {
727         return Collections.unmodifiableList(defaultEntityListeners);
728     }
729
730     /**
731      * Adds a new EntityListener.
732      *
733      * @since 3.0
734      * @throws IllegalArgumentException if a listener for the same class name is already
735      * registered.
736      */

737     public void addDefaultEntityListener(EntityListener listener) {
738         Iterator JavaDoc it = defaultEntityListeners.iterator();
739         while (it.hasNext()) {
740             EntityListener next = (EntityListener) it.next();
741             if (listener.getClassName().equals(next.getClassName())) {
742                 throw new IllegalArgumentException JavaDoc("Duplicate default listener for "
743                         + next.getClassName());
744             }
745         }
746
747         defaultEntityListeners.add(listener);
748     }
749
750     /**
751      * Removes a listener matching class name.
752      *
753      * @since 3.0
754      */

755     public void removeDefaultEntityListener(String JavaDoc className) {
756         Iterator JavaDoc it = defaultEntityListeners.iterator();
757         while (it.hasNext()) {
758             EntityListener next = (EntityListener) it.next();
759             if (className.equals(next.getClassName())) {
760                 it.remove();
761                 break;
762             }
763         }
764     }
765
766     /**
767      * @since 3.0
768      */

769     public EntityListener getDefaultEntityListener(String JavaDoc className) {
770         Iterator JavaDoc it = defaultEntityListeners.iterator();
771         while (it.hasNext()) {
772             EntityListener next = (EntityListener) it.next();
773             if (className.equals(next.getClassName())) {
774                 return next;
775             }
776         }
777
778         return null;
779     }
780
781     /**
782      * Returns all DbEntities in this DataMap.
783      */

784     public Collection JavaDoc getDbEntities() {
785         return Collections.unmodifiableCollection(dbEntityMap.values());
786     }
787
788     /**
789      * Returns DbEntity matching the <code>name</code> parameter. No dependencies will
790      * be searched.
791      */

792     public DbEntity getDbEntity(String JavaDoc dbEntityName) {
793         DbEntity entity = (DbEntity) dbEntityMap.get(dbEntityName);
794
795         if (entity != null) {
796             return entity;
797         }
798
799         return namespace != null ? namespace.getDbEntity(dbEntityName) : null;
800     }
801
802     /**
803      * Returns an ObjEntity for a DataObject class name.
804      *
805      * @since 1.1
806      */

807     public ObjEntity getObjEntityForJavaClass(String JavaDoc javaClassName) {
808         if (javaClassName == null) {
809             return null;
810         }
811
812         Iterator JavaDoc it = getObjEntityMap().entrySet().iterator();
813         while (it.hasNext()) {
814             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
815             ObjEntity entity = (ObjEntity) entry.getValue();
816             if (javaClassName.equals(entity.getClassName())) {
817                 return entity;
818             }
819         }
820
821         return null;
822     }
823
824     /**
825      * Returns an ObjEntity for a given name. If it is not found in this DataMap, it will
826      * search a parent EntityNamespace.
827      */

828     public ObjEntity getObjEntity(String JavaDoc objEntityName) {
829         ObjEntity entity = (ObjEntity) objEntityMap.get(objEntityName);
830         if (entity != null) {
831             return entity;
832         }
833
834         return namespace != null ? namespace.getObjEntity(objEntityName) : null;
835     }
836
837     /**
838      * Returns all ObjEntities mapped to the given DbEntity.
839      */

840     public Collection JavaDoc getMappedEntities(DbEntity dbEntity) {
841         if (dbEntity == null) {
842             return Collections.EMPTY_LIST;
843         }
844
845         Collection JavaDoc allEntities = (namespace != null)
846                 ? namespace.getObjEntities()
847                 : getObjEntities();
848
849         if (allEntities.isEmpty()) {
850             return Collections.EMPTY_LIST;
851         }
852
853         Collection JavaDoc result = new ArrayList JavaDoc();
854         Iterator JavaDoc iter = allEntities.iterator();
855         while (iter.hasNext()) {
856             ObjEntity objEnt = (ObjEntity) iter.next();
857             if (objEnt.getDbEntity() == dbEntity) {
858                 result.add(objEnt);
859             }
860         }
861
862         return result;
863     }
864
865     /**
866      * Removes an {@link Embeddable} descriptor with matching class name.
867      *
868      * @since 3.0
869      */

870     public void removeEmbeddable(String JavaDoc className) {
871         // TODO: andrus, 1/25/2007 - clean up references like removeDbEntity does.
872
embeddablesMap.remove(className);
873     }
874
875     /**
876      * "Dirty" remove of the DbEntity from the data map.
877      */

878     public void removeDbEntity(String JavaDoc dbEntityName) {
879         removeDbEntity(dbEntityName, false);
880     }
881
882     /**
883      * Removes DbEntity from the DataMap. If <code>clearDependencies</code> is true, all
884      * DbRelationships that reference this entity are also removed. ObjEntities that rely
885      * on this entity are cleaned up.
886      *
887      * @since 1.1
888      */

889     public void removeDbEntity(String JavaDoc dbEntityName, boolean clearDependencies) {
890         DbEntity dbEntityToDelete = (DbEntity) dbEntityMap.remove(dbEntityName);
891
892         if (dbEntityToDelete != null && clearDependencies) {
893             Iterator JavaDoc dbEnts = this.getDbEntities().iterator();
894             while (dbEnts.hasNext()) {
895                 DbEntity dbEnt = (DbEntity) dbEnts.next();
896                 // take a copy since we're going to modifiy the entity
897
Iterator JavaDoc rels = new ArrayList JavaDoc(dbEnt.getRelationships()).iterator();
898                 while (rels.hasNext()) {
899                     DbRelationship rel = (DbRelationship) rels.next();
900                     if (dbEntityName.equals(rel.getTargetEntityName())) {
901                         dbEnt.removeRelationship(rel.getName());
902                     }
903                 }
904             }
905
906             // Remove all obj relationships referencing removed DbRelationships.
907
Iterator JavaDoc objEnts = this.getObjEntities().iterator();
908             while (objEnts.hasNext()) {
909                 ObjEntity objEnt = (ObjEntity) objEnts.next();
910                 if (objEnt.getDbEntity() == dbEntityToDelete) {
911                     objEnt.clearDbMapping();
912                 }
913                 else {
914                     Iterator JavaDoc iter = objEnt.getRelationships().iterator();
915                     while (iter.hasNext()) {
916                         ObjRelationship rel = (ObjRelationship) iter.next();
917                         Iterator JavaDoc dbRels = rel.getDbRelationships().iterator();
918                         while (dbRels.hasNext()) {
919                             DbRelationship dbRel = (DbRelationship) dbRels.next();
920                             if (dbRel.getTargetEntity() == dbEntityToDelete) {
921                                 rel.clearDbRelationships();
922                                 break;
923                             }
924                         }
925                     }
926                 }
927             }
928         }
929     }
930
931     /**
932      * "Dirty" remove of the ObjEntity from the data map.
933      */

934     public void removeObjEntity(String JavaDoc objEntityName) {
935         removeObjEntity(objEntityName, false);
936     }
937
938     /**
939      * Removes ObjEntity from the DataMap. If <code>clearDependencies</code> is true,
940      * all ObjRelationships that reference this entity are also removed.
941      *
942      * @since 1.1
943      */

944     public void removeObjEntity(String JavaDoc objEntityName, boolean clearDependencies) {
945         ObjEntity entity = (ObjEntity) objEntityMap.remove(objEntityName);
946
947         if (entity != null && clearDependencies) {
948
949             // remove relationships that point to this entity
950
Iterator JavaDoc entities = getObjEntities().iterator();
951             while (entities.hasNext()) {
952                 ObjEntity ent = (ObjEntity) entities.next();
953                 // take a copy since we're going to modifiy the entity
954
Iterator JavaDoc rels = new ArrayList JavaDoc(ent.getRelationships()).iterator();
955                 while (rels.hasNext()) {
956                     ObjRelationship rel = (ObjRelationship) rels.next();
957                     if (objEntityName.equals(rel.getTargetEntityName())
958                             || objEntityName.equals(rel.getTargetEntityName())) {
959                         ent.removeRelationship(rel.getName());
960                     }
961                 }
962             }
963         }
964     }
965
966     /**
967      * Returns stored procedures associated with this DataMap.
968      */

969     public Collection JavaDoc getProcedures() {
970         return Collections.unmodifiableCollection(procedureMap.values());
971     }
972
973     /**
974      * Returns a Procedure for a given name or null if no such procedure exists. If
975      * Procedure is not found in this DataMap, a parent EntityNamcespace is searched.
976      */

977     public Procedure getProcedure(String JavaDoc procedureName) {
978         Procedure procedure = (Procedure) procedureMap.get(procedureName);
979         if (procedure != null) {
980             return procedure;
981         }
982
983         return namespace != null ? namespace.getProcedure(procedureName) : null;
984     }
985
986     /**
987      * Adds stored procedure to the list of procedures. If there is another procedure
988      * registered under the same name, throws an IllegalArgumentException.
989      */

990     public void addProcedure(Procedure procedure) {
991         if (procedure.getName() == null) {
992             throw new NullPointerException JavaDoc("Attempt to add procedure with no name.");
993         }
994
995         // TODO: change method signature to return replaced procedure and make sure the
996
// Modeler handles it...
997
Object JavaDoc existingProcedure = procedureMap.get(procedure.getName());
998         if (existingProcedure != null) {
999             if (existingProcedure == procedure) {
1000                return;
1001            }
1002            else {
1003                throw new IllegalArgumentException JavaDoc("An attempt to override procedure '"
1004                        + procedure.getName());
1005            }
1006        }
1007
1008        procedureMap.put(procedure.getName(), procedure);
1009        procedure.setDataMap(this);
1010    }
1011
1012    public void removeProcedure(String JavaDoc name) {
1013        procedureMap.remove(name);
1014    }
1015
1016    /**
1017     * Returns a sorted unmodifiable map of Procedures in this DataMap keyed by name.
1018     */

1019    public SortedMap JavaDoc getProcedureMap() {
1020        return Collections.unmodifiableSortedMap(procedureMap);
1021    }
1022
1023    /**
1024     * Returns a parent namespace where this DataMap resides. Parent EntityNamespace is
1025     * used to establish relationships with entities in other DataMaps.
1026     *
1027     * @since 1.1
1028     */

1029    public MappingNamespace getNamespace() {
1030        return namespace;
1031    }
1032
1033    /**
1034     * Sets a parent namespace where this DataMap resides. Parent EntityNamespace is used
1035     * to establish relationships with entities in other DataMaps.
1036     *
1037     * @since 1.1
1038     */

1039    public void setNamespace(MappingNamespace namespace) {
1040        this.namespace = namespace;
1041    }
1042
1043    /**
1044     * @since 1.1
1045     */

1046    public int getDefaultLockType() {
1047        return defaultLockType;
1048    }
1049
1050    /**
1051     * @since 1.1
1052     */

1053    public void setDefaultLockType(int defaultLockType) {
1054        this.defaultLockType = defaultLockType;
1055    }
1056
1057    /**
1058     * @since 1.2
1059     */

1060    public boolean isClientSupported() {
1061        return clientSupported;
1062    }
1063
1064    /**
1065     * @since 1.2
1066     */

1067    public void setClientSupported(boolean clientSupport) {
1068        this.clientSupported = clientSupport;
1069    }
1070
1071    /**
1072     * Returns default client package.
1073     *
1074     * @since 1.2
1075     */

1076    public String JavaDoc getDefaultClientPackage() {
1077        return defaultClientPackage;
1078    }
1079
1080    /**
1081     * @since 1.2
1082     */

1083    public void setDefaultClientPackage(String JavaDoc defaultClientPackage) {
1084        this.defaultClientPackage = defaultClientPackage;
1085    }
1086
1087    /**
1088     * @since 1.1
1089     */

1090    public String JavaDoc getDefaultPackage() {
1091        return defaultPackage;
1092    }
1093
1094    /**
1095     * @since 1.1
1096     */

1097    public void setDefaultPackage(String JavaDoc defaultPackage) {
1098        this.defaultPackage = defaultPackage;
1099    }
1100
1101    /**
1102     * @since 1.1
1103     */

1104    public String JavaDoc getDefaultSchema() {
1105        return defaultSchema;
1106    }
1107
1108    /**
1109     * @since 1.1
1110     */

1111    public void setDefaultSchema(String JavaDoc defaultSchema) {
1112        this.defaultSchema = defaultSchema;
1113    }
1114
1115    /**
1116     * @since 1.1
1117     */

1118    public String JavaDoc getDefaultSuperclass() {
1119        return defaultSuperclass;
1120    }
1121
1122    /**
1123     * @since 1.1
1124     */

1125    public void setDefaultSuperclass(String JavaDoc defaultSuperclass) {
1126        this.defaultSuperclass = defaultSuperclass;
1127    }
1128
1129    /**
1130     * DbEntity property changed. May be name, attribute or relationship added or removed,
1131     * etc. Attribute and relationship property changes are handled in respective
1132     * listeners.
1133     *
1134     * @since 1.2
1135     */

1136    public void dbEntityChanged(EntityEvent e) {
1137        Entity entity = e.getEntity();
1138        if (entity instanceof DbEntity) {
1139            ((DbEntity) entity).dbEntityChanged(e);
1140
1141            // finish up the name change here because we
1142
// do not have direct access to the dbEntityMap
1143
if (e.isNameChange()) {
1144                // remove the entity from the map with the old name
1145
dbEntityMap.remove(e.getOldName());
1146
1147                // add the entity back in with the new name
1148
dbEntityMap.put(e.getNewName(), entity);
1149
1150                // important - clear parent namespace:
1151
MappingNamespace ns = getNamespace();
1152                if (ns instanceof EntityResolver) {
1153                    ((EntityResolver) ns).clearCache();
1154                }
1155            }
1156        }
1157    }
1158
1159    /** New entity has been created/added. */
1160    public void dbEntityAdded(EntityEvent e) {
1161        // does nothing currently
1162
}
1163
1164    /** Entity has been removed. */
1165    public void dbEntityRemoved(EntityEvent e) {
1166        // does nothing currently
1167
}
1168
1169    /** Attribute property changed. */
1170    public void dbAttributeChanged(AttributeEvent e) {
1171        Entity entity = e.getEntity();
1172        if (entity instanceof DbEntity) {
1173            ((DbEntity) entity).dbAttributeChanged(e);
1174        }
1175    }
1176
1177    /** New attribute has been created/added. */
1178    public void dbAttributeAdded(AttributeEvent e) {
1179        // does nothing currently
1180
}
1181
1182    /** Attribute has been removed. */
1183    public void dbAttributeRemoved(AttributeEvent e) {
1184        // does nothing currently
1185
}
1186
1187    /** Relationship property changed. */
1188    public void dbRelationshipChanged(RelationshipEvent e) {
1189        Entity entity = e.getEntity();
1190        if (entity instanceof DbEntity) {
1191            ((DbEntity) entity).dbRelationshipChanged(e);
1192        }
1193    }
1194
1195    /** Relationship has been created/added. */
1196    public void dbRelationshipAdded(RelationshipEvent e) {
1197        // does nothing currently
1198
}
1199
1200    /** Relationship has been removed. */
1201    public void dbRelationshipRemoved(RelationshipEvent e) {
1202        // does nothing currently
1203
}
1204
1205    /**
1206     * ObjEntity property changed. May be name, attribute or relationship added or
1207     * removed, etc. Attribute and relationship property changes are handled in respective
1208     * listeners.
1209     *
1210     * @since 1.2
1211     */

1212    public void objEntityChanged(EntityEvent e) {
1213        Entity entity = e.getEntity();
1214        if (entity instanceof ObjEntity) {
1215            ((ObjEntity) entity).objEntityChanged(e);
1216
1217            // finish up the name change here because we
1218
// do not have direct access to the objEntityMap
1219
if (e.isNameChange()) {
1220                // remove the entity from the map with the old name
1221
objEntityMap.remove(e.getOldName());
1222
1223                // add the entity back in with the new name
1224
objEntityMap.put(e.getNewName(), entity);
1225
1226                // important - clear parent namespace:
1227
MappingNamespace ns = getNamespace();
1228                if (ns instanceof EntityResolver) {
1229                    ((EntityResolver) ns).clearCache();
1230                }
1231            }
1232        }
1233    }
1234
1235    /** New entity has been created/added. */
1236    public void objEntityAdded(EntityEvent e) {
1237        // does nothing currently
1238
}
1239
1240    /** Entity has been removed. */
1241    public void objEntityRemoved(EntityEvent e) {
1242        // does nothing currently
1243
}
1244
1245    /** Attribute property changed. */
1246    public void objAttributeChanged(AttributeEvent e) {
1247        // does nothing currently
1248
}
1249
1250    /** New attribute has been created/added. */
1251    public void objAttributeAdded(AttributeEvent e) {
1252        // does nothing currently
1253
}
1254
1255    /** Attribute has been removed. */
1256    public void objAttributeRemoved(AttributeEvent e) {
1257        // does nothing currently
1258
}
1259
1260    /** Relationship property changed. */
1261    public void objRelationshipChanged(RelationshipEvent e) {
1262        // does nothing currently
1263
}
1264
1265    /** Relationship has been created/added. */
1266    public void objRelationshipAdded(RelationshipEvent e) {
1267        // does nothing currently
1268
}
1269
1270    /** Relationship has been removed. */
1271    public void objRelationshipRemoved(RelationshipEvent e) {
1272        // does nothing currently
1273
}
1274}
1275
Popular Tags