Source Code Cross Referenced for RelationshipProxy.java in  » Database-ORM » XORM » org » xorm » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » XORM » org.xorm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:          $Header: /cvsroot/xorm/xorm/src/org/xorm/RelationshipProxy.java,v 1.33 2004/02/05 23:04:55 seifertd Exp $
003:
004:          This file is part of XORM.
005:
006:          XORM is free software; you can redistribute it and/or modify
007:          it under the terms of the GNU General Public License as published by
008:          the Free Software Foundation; either version 2 of the License, or
009:          (at your option) any later version.
010:
011:          XORM is distributed in the hope that it will be useful,
012:          but WITHOUT ANY WARRANTY; without even the implied warranty of
013:          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014:          GNU General Public License for more details.
015:
016:          You should have received a copy of the GNU General Public License
017:          along with XORM; if not, write to the Free Software
018:          Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
019:         */
020:        package org.xorm;
021:
022:        import java.util.AbstractCollection;
023:        import java.util.ArrayList;
024:        import java.util.Collection;
025:        import java.util.HashMap;
026:        import java.util.Iterator;
027:        import java.util.logging.Logger;
028:        import javax.jdo.JDOFatalUserException;
029:
030:        import org.xorm.datastore.Column;
031:        import org.xorm.datastore.DataFetchGroup;
032:        import org.xorm.datastore.Row;
033:        import org.xorm.datastore.Table;
034:        import org.xorm.query.BoundExpression;
035:        import org.xorm.query.AndCondition;
036:        import org.xorm.query.Condition;
037:        import org.xorm.query.Operator;
038:        import org.xorm.query.QueryImpl;
039:        import org.xorm.query.Selector;
040:        import org.xorm.query.SimpleCondition;
041:
042:        /**
043:         * Represents a one-to-many or many-to-many relationship.  An instance
044:         * of RelationshipProxy is constructed in
045:         * InterfaceInvocationHandler.invokeCollectionGet().
046:         */
047:        public class RelationshipProxy extends CollectionProxy {
048:            protected static Logger logger = Logger
049:                    .getLogger("org.xorm.RelationshipProxy");
050:
051:            // The field on the owner object that references this collection
052:            protected boolean txnManaged;
053:            protected RelationshipMapping mapping;
054:            protected InterfaceInvocationHandler owner;
055:
056:            // Additional fields used for many-to-many tracking
057:            protected Collection deletedRows;
058:            protected Collection newRows;
059:
060:            // Arguments that need to be translated into parameters in a filtered
061:            // relationship query
062:            protected Object[] args = null;
063:
064:            /** Returns the underlying relationship mapping this represents. */
065:            public RelationshipMapping getRelationshipMapping() {
066:                return mapping;
067:            }
068:
069:            /** Returns the owner of this directional relationship. */
070:            public InterfaceInvocationHandler getOwner() {
071:                return owner;
072:            }
073:
074:            /** Creates a new proxy backed by the data in the rows collection. */
075:            public RelationshipProxy(InterfaceManager mgr,
076:                    RelationshipMapping mapping,
077:                    InterfaceInvocationHandler owner,
078:                    ClassMapping classMapping, Object[] args) {
079:                super (mgr, classMapping);
080:                this .mapping = mapping;
081:                this .owner = owner;
082:                this .txnManaged = owner.isTransactional();
083:                if (mapping.isMToN()) {
084:                    this .newRows = new ArrayList();
085:                    this .deletedRows = new ArrayList();
086:                }
087:                this .args = args;
088:                this .selector = getSelector();
089:            }
090:
091:            /** Overrides CollectionProxy implementation. */
092:            public Class getElementType() {
093:                return mapping.getSource().getElementClass();
094:            }
095:
096:            protected Selector getSelector() {
097:                Object ownerPKey = owner.getObjectId();
098:                if (ownerPKey instanceof  TransientKey) {
099:                    return null;
100:                }
101:
102:                Column columnToUse = null;
103:
104:                if (mapping.getSource().getColumn() != null) {
105:                    columnToUse = mapping.getSource().getColumn();
106:                } else if (mapping.getFilter() != null) {
107:                    // In this case, source wasn't specified, but target
108:                    // is always specified...and in this case should be
109:                    // the primary key column of the owner class (see
110:                    // ModelMapping.parseRelationship).
111:                    columnToUse = mapping.getTarget().getColumn();
112:                } else {
113:                    // How did we get here?  An exception should have been
114:                    // thrown in ModelMapping.parseRelationship
115:                    throw new JDOFatalUserException(I18N
116:                            .msg("E_collection_no_source"));
117:                }
118:
119:                Selector selector = new Selector(columnToUse.getTable(),
120:                        new SimpleCondition(columnToUse, Operator.EQUAL,
121:                                ownerPKey));
122:
123:                if (mapping.getFilter() != null) {
124:                    logger.fine("Filter: " + mapping.getFilter());
125:                    logger.fine("Imports: " + mapping.getImports());
126:                    logger.fine("Parameters: " + mapping.getParameters());
127:                    logger.fine("Variables: " + mapping.getVariables());
128:                    if (mapping.getParameters() != null
129:                            && !mapping.getParameters().equals("")
130:                            && (args == null || args.length == 0)) {
131:                        throw new NullPointerException(I18N
132:                                .msg("E_missing_arguments"));
133:                    }
134:
135:                    //logger.fine("Class Mapping Table: " + classMapping.getTable().getName());
136:                    Class filterTargetClass = classMapping.getMappedClass();
137:                    //logger.fine("Filter Target Class: " + filterTargetClass.getName());
138:
139:                    QueryImpl query = new QueryImpl(mgr);
140:                    query.setClass(filterTargetClass);
141:                    query.setFilter(mapping.getFilter());
142:
143:                    // We support the implicit "owner" parameter in filters.
144:                    // The owner refers to the object instance off which the
145:                    // collection field getter is being called.  We need to add
146:                    // it to the parameters that we set on the query.
147:                    String parameters = mapping.getParameters();
148:                    ClassMapping ownerClassMapping = owner.getClassMapping();
149:                    Class ownerClass = ownerClassMapping.getMappedClass();
150:                    String ownerClassName = ownerClass.getName();
151:                    //ownerClassName = ownerClassName.substring(ownerClassName.lastIndexOf('.') + 1);
152:                    //logger.fine("OwnerClassName: " + ownerClassName);
153:
154:                    if (mapping.getImports() != null) {
155:                        query.declareImports(mapping.getImports());
156:                    }
157:                    if (parameters == null || parameters.equals("")) {
158:                        // No parameters, just this owner param
159:                        parameters = ownerClassName + " owner";
160:                    } else {
161:                        // Append this owner param to the existing parameters
162:                        parameters += ", " + ownerClassName + " owner";
163:                    }
164:                    logger.fine("Modified Parameters: " + parameters);
165:                    query.declareParameters(parameters);
166:
167:                    if (mapping.getVariables() != null) {
168:                        query.declareVariables(mapping.getVariables());
169:                    }
170:
171:                    if (mapping.getOrdering() != null) {
172:                        query.setOrdering(mapping.getOrdering());
173:                    }
174:
175:                    query.compile();
176:                    //logger.fine("Filter Query: " + query);
177:
178:                    BoundExpression bound = query.getBoundExpression();
179:                    int paramCount = 0;
180:                    if (args != null) {
181:                        while (paramCount < args.length) {
182:                            bound.bindParameter(paramCount, args[paramCount]);
183:                            ++paramCount;
184:                        }
185:                    }
186:
187:                    // Always bind the implicit "owner" parameter
188:                    bound.bindParameter(paramCount++, owner.getProxy());
189:
190:                    //logger.fine(paramCount + " parameter(s) bound");
191:
192:                    /*
193:                    logger.info("Main Selector Table Before: " +
194:                                selector.getTable().getName());
195:                    logger.info("Main Selector Before: " + selector);
196:                     */
197:
198:                    Selector filterSelector = bound.getSelector();
199:
200:                    /*
201:                    logger.info("Filter Selector Table: " +
202:                                filterSelector.getTable().getName());
203:                    logger.info("Filter Selector: " + filterSelector);
204:                     */
205:
206:                    if (mapping.getSource().getColumn() != null) {
207:                        //logger.fine("Joining filter selector with running selector");
208:                        /*
209:                        Condition join = new SimpleCondition(mapping.getTarget().getColumn(), Operator.EQUAL, filterSelector);
210:                        selector.setCondition(new AndCondition(join, selector.getCondition()));
211:                         */
212:                        selector.merge(filterSelector, Operator.ANDC);
213:                    } else {
214:                        // This is a free-floating collection getter query.
215:                        // There is no link table, there is no source.
216:                        // Just use the filter as the selector.
217:                        //logger.fine("Replacing selector with filter selector");
218:                        selector = filterSelector;
219:                    }
220:
221:                    /*
222:                    logger.info("Main Selector Table After: " +
223:                                selector.getTable().getName());
224:                    logger.info("Main Selector After: " + selector);
225:                     */
226:                }
227:
228:                // This is a hack until there is real OrderedSet/List support.
229:                // key="order-by" can be specified in JDO metadata extensions
230:                String orderBy = mapping.getOrderBy();
231:                if (orderBy != null) {
232:                    int spacePos = orderBy.indexOf(' ');
233:                    String colName;
234:                    int orderingType = Selector.Ordering.ASCENDING;
235:                    if (spacePos != -1) {
236:                        colName = orderBy.substring(0, spacePos);
237:                        if ((spacePos + 1) < orderBy.length()) {
238:                            String type = orderBy.substring(spacePos + 1);
239:                            orderingType = "ASC".equalsIgnoreCase(type) ? Selector.Ordering.ASCENDING
240:                                    : Selector.Ordering.DESCENDING;
241:                        }
242:                    } else {
243:                        colName = orderBy;
244:                    }
245:                    Selector.Ordering[] ordering = new Selector.Ordering[1];
246:                    ordering[0] = new Selector.Ordering(selector.getTable()
247:                            .getColumnByName(colName), orderingType);
248:                    selector.setOrdering(ordering);
249:                }
250:
251:                DataFetchGroup dfg = null;
252:                FetchGroupManager fgm = mgr.getInterfaceManagerFactory()
253:                        .getFetchGroupManager();
254:                if (mapping.isMToN()) {
255:                    // For many-to-many mappings, select all from the join table,
256:                    // and then the default fetch group of the target table
257:                    dfg = new DataFetchGroup(selector.getTable().getColumns());
258:                    dfg.addSubgroup(mapping.getTarget().getColumn(), fgm
259:                            .getDataFetchGroup(classMapping));
260:                } else {
261:                    dfg = fgm.getDataFetchGroup(classMapping);
262:                }
263:                selector.require(dfg);
264:
265:                return selector;
266:            }
267:
268:            /**
269:             * Ensures that the proxy is registered in a transaction if necessary.
270:             */
271:            protected void forceTransaction() {
272:                if (owner.isPersistent()) {
273:                    TransactionImpl txn = (TransactionImpl) owner
274:                            .getInterfaceManager().currentTransaction();
275:                    if (txn.isActive()) {
276:                        txn.attachRelationship(this );
277:                        txnManaged = true;
278:                    } else {
279:                        throw new JDOFatalUserException(I18N
280:                                .msg("E_modify_collection"));
281:                    }
282:                }
283:            }
284:
285:            /** Adds the given object (proxy object) to the collection. */
286:            public boolean add(Object o) {
287:                // Sanity checking
288:                if (o == null)
289:                    throw new NullPointerException();
290:                if (!getElementType().isInstance(o)) {
291:                    throw new IllegalArgumentException(I18N.msg(
292:                            "E_element_type", getElementType().getName()));
293:                }
294:
295:                if (!txnManaged) {
296:                    forceTransaction();
297:                }
298:
299:                InterfaceInvocationHandler handler = InterfaceInvocationHandler
300:                        .getHandler(o);
301:                Row row = new Row(mapping.getSource().getColumn().getTable());
302:                row.setValue(mapping.getSource().getColumn(), owner
303:                        .getObjectId());
304:                row.setValue(mapping.getTarget().getColumn(), handler
305:                        .getObjectId());
306:                getRows().add(row);
307:                if (!owner.isDirty()) {
308:                    owner.makeDirty();
309:                }
310:                rowToProxy.put(row, o);
311:                if (mapping.isMToN()) {
312:                    markAsNew(row);
313:                }
314:
315:                // Transient objects that are added to a persistent relationship
316:                // become persistent.
317:                if (owner.isPersistent() && !handler.isPersistent()) {
318:                    handler.makePersistent(mgr);
319:                }
320:                return true;
321:            }
322:
323:            /** Removes the given object (proxy object) from the collection. */
324:            public boolean remove(Object o) {
325:                if (!txnManaged) {
326:                    forceTransaction();
327:                }
328:
329:                InterfaceInvocationHandler handler = InterfaceInvocationHandler
330:                        .getHandler(o);
331:                Object targetKey = handler.getObjectId();
332:
333:                // Find the row that matches the targetKey
334:                Iterator i = getRows().iterator();
335:                while (i.hasNext()) {
336:                    Row row = (Row) i.next();
337:                    if (targetKey.equals(row.getValue(mapping.getTarget()
338:                            .getColumn()))) {
339:                        if (mapping.isMToN()) {
340:                            markAsDeleted(row);
341:                        }
342:                        i.remove();
343:                        rowToProxy.remove(row);
344:                        if (!owner.isDirty()) {
345:                            owner.makeDirty();
346:                        }
347:                        return true;
348:                    }
349:                }
350:                return false; // not found
351:            }
352:
353:            /**
354:             * Removes all rows.  This is slightly more straightforward than
355:             * iterating through and removing each element (but that works too).
356:             */
357:            public void clear() {
358:                if (!txnManaged) {
359:                    forceTransaction();
360:                }
361:
362:                Iterator i = getRows().iterator();
363:                if (i.hasNext()) {
364:                    if (!owner.isDirty()) {
365:                        owner.makeDirty();
366:                    }
367:
368:                    while (i.hasNext()) {
369:                        Row row = (Row) i.next();
370:                        if (mapping.isMToN()) {
371:                            markAsDeleted(row);
372:                        }
373:                        i.remove();
374:                    }
375:                }
376:                rowToProxy.clear();
377:            }
378:
379:            /**
380:             * Removes any transactional context associated with this proxy,
381:             * clearing the list of new and deleted rows.
382:             */
383:            void exitTransaction(boolean commit) {
384:                txnManaged = false;
385:                if (mapping.isMToN()) {
386:                    if (!commit && rows != null) {
387:                        rows.removeAll(newRows);
388:                        rows.addAll(deletedRows);
389:                    }
390:                    newRows.clear();
391:                    deletedRows.clear();
392:                }
393:            }
394:
395:            /** Called when an object ID changes. */
396:            public void notifyIDChanged(Object oldID, Object newID) {
397:                // Go through Rows and look for references to oldID
398:                Iterator i = getRows().iterator();
399:                Column c1 = mapping.getTarget().getColumn();
400:                Column c2 = mapping.getSource().getColumn();
401:                while (i.hasNext()) {
402:                    Row row = (Row) i.next();
403:                    if (oldID.equals(row.getValue(c1))) {
404:                        row.setValue(c1, newID);
405:                    }
406:                    if (oldID.equals(row.getValue(c2))) {
407:                        row.setValue(c2, newID);
408:                    }
409:                }
410:                // TODO do we need to tell all contained items?
411:            }
412:
413:            public boolean dependsOn(InterfaceInvocationHandler other) {
414:                // See if any of the contents match
415:                Iterator i = new ProxyIterator();
416:                while (i.hasNext()) {
417:                    Object obj = i.next();
418:                    // Check if its key is new
419:                    InterfaceInvocationHandler handler = InterfaceInvocationHandler
420:                            .getHandler(obj);
421:                    Object idObj = handler.getObjectId();
422:                    if (idObj instanceof  TransientKey) {
423:                        // check depends on
424:                        if (handler.dependsOn(other)) {
425:                            return true;
426:                        }
427:                    }
428:                }
429:                return false;
430:            }
431:
432:            protected Column getKeyColumn() {
433:                return mapping.getTarget().getColumn();
434:            }
435:
436:            protected class RelationshipProxyIterator extends ProxyIterator {
437:                public void remove() {
438:                    if (!txnManaged) {
439:                        forceTransaction();
440:                    }
441:                    if (mapping.isMToN()) {
442:                        markAsDeleted(lastRow);
443:                    }
444:                    inner.remove();
445:                    if (!owner.isDirty()) {
446:                        owner.makeDirty();
447:                    }
448:                    rowToProxy.remove(lastRow);
449:                }
450:            }
451:
452:            public Iterator iterator() {
453:                return iterator = new RelationshipProxyIterator();
454:            }
455:
456:            // Methods for Many-to-Many support
457:            /** Marks a row for removal. */
458:            void markAsDeleted(Row row) {
459:                if (newRows.contains(row)) {
460:                    // NEW_DELETED in this case means just pretend it never happened
461:                    newRows.remove(row);
462:                } else {
463:                    deletedRows.add(row);
464:                }
465:            }
466:
467:            /** Marks a row as newly created. */
468:            void markAsNew(Row row) {
469:                if (deletedRows.contains(row)) {
470:                    deletedRows.remove(row);
471:                } else {
472:                    newRows.add(row);
473:                }
474:            }
475:
476:            /**
477:             * Retrieve the collection of rows that were created in the
478:             * current transaction. 
479:             */
480:            Collection getNewRows() {
481:                return newRows;
482:            }
483:
484:            /**
485:             * Retrieve the collection of rows that were removed in the
486:             * current transaction. 
487:             */
488:            Collection getDeletedRows() {
489:                return deletedRows;
490:            }
491:
492:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.