Source Code Cross Referenced for JDBCCMP2xFieldBridge.java in  » EJB-Server-JBoss-4.2.1 » server » org » jboss » ejb » plugins » cmp » jdbc » bridge » 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 » EJB Server JBoss 4.2.1 » server » org.jboss.ejb.plugins.cmp.jdbc.bridge 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * JBoss, Home of Professional Open Source.
003:         * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004:         * as indicated by the @author tags. See the copyright.txt file in the
005:         * distribution for a full listing of individual contributors.
006:         *
007:         * This is free software; you can redistribute it and/or modify it
008:         * under the terms of the GNU Lesser General Public License as
009:         * published by the Free Software Foundation; either version 2.1 of
010:         * the License, or (at your option) any later version.
011:         *
012:         * This software is distributed in the hope that it will be useful,
013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015:         * Lesser General Public License for more details.
016:         *
017:         * You should have received a copy of the GNU Lesser General Public
018:         * License along with this software; if not, write to the Free
019:         * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021:         */
022:        package org.jboss.ejb.plugins.cmp.jdbc.bridge;
023:
024:        import java.lang.reflect.Field;
025:
026:        import javax.ejb.EJBException;
027:
028:        import org.jboss.deployment.DeploymentException;
029:        import org.jboss.ejb.EntityEnterpriseContext;
030:
031:        import org.jboss.ejb.plugins.cmp.jdbc.JDBCContext;
032:        import org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager;
033:        import org.jboss.ejb.plugins.cmp.jdbc.JDBCType;
034:        import org.jboss.ejb.plugins.cmp.jdbc.CMPFieldStateFactory;
035:        import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCCMPFieldMetaData;
036:
037:        /**
038:         * JDBCCMP2xFieldBridge is a concrete implementation of JDBCCMPFieldBridge for
039:         * CMP version 2.x. Instance data is stored in the entity persistence context.
040:         * Whenever a field is changed it is compared to the current value and sets
041:         * a dirty flag if the value has changed.
042:         *
043:         * Life-cycle:
044:         *      Tied to the EntityBridge.
045:         *
046:         * Multiplicity:
047:         *      One for each entity bean cmp field.
048:         *
049:         * @author <a href="mailto:dain@daingroup.com">Dain Sundstrom</a>
050:         * @author <a href="mailto:alex@jboss.org">Alex Loubyansky</a>
051:         * @version $Revision: 57209 $
052:         */
053:        public class JDBCCMP2xFieldBridge extends JDBCAbstractCMPFieldBridge {
054:            /** column name (used only at deployment time to check whether fields mapped to the same column) */
055:            private final String columnName;
056:
057:            /** CMP field this foreign key field is mapped to */
058:            private final JDBCCMP2xFieldBridge cmpFieldIAmMappedTo;
059:
060:            /** this is used for foreign key fields mapped to CMP fields (check ChainLink) */
061:            private ChainLink cmrChainLink;
062:
063:            // Constructors
064:
065:            public JDBCCMP2xFieldBridge(JDBCStoreManager manager,
066:                    JDBCCMPFieldMetaData metadata) throws DeploymentException {
067:                super (manager, metadata);
068:                cmpFieldIAmMappedTo = null;
069:                columnName = metadata.getColumnName();
070:            }
071:
072:            public JDBCCMP2xFieldBridge(JDBCStoreManager manager,
073:                    JDBCCMPFieldMetaData metadata,
074:                    CMPFieldStateFactory stateFactory,
075:                    boolean checkDirtyAfterGet) throws DeploymentException {
076:                this (manager, metadata);
077:                this .stateFactory = stateFactory;
078:                this .checkDirtyAfterGet = checkDirtyAfterGet;
079:            }
080:
081:            public JDBCCMP2xFieldBridge(JDBCCMP2xFieldBridge cmpField,
082:                    CMPFieldStateFactory stateFactory,
083:                    boolean checkDirtyAfterGet) throws DeploymentException {
084:                this ((JDBCStoreManager) cmpField.getManager(), cmpField
085:                        .getFieldName(), cmpField.getFieldType(), cmpField
086:                        .getJDBCType(), cmpField.isReadOnly(), // should always be false?
087:                        cmpField.getReadTimeOut(), cmpField
088:                                .getPrimaryKeyClass(), cmpField
089:                                .getPrimaryKeyField(), cmpField, null, // it should not be a foreign key
090:                        cmpField.getColumnName());
091:                this .stateFactory = stateFactory;
092:                this .checkDirtyAfterGet = checkDirtyAfterGet;
093:            }
094:
095:            /**
096:             * This constructor creates a foreign key field.
097:             */
098:            public JDBCCMP2xFieldBridge(JDBCStoreManager manager,
099:                    JDBCCMPFieldMetaData metadata, JDBCType jdbcType)
100:                    throws DeploymentException {
101:                super (manager, metadata, jdbcType);
102:                cmpFieldIAmMappedTo = null;
103:                columnName = metadata.getColumnName();
104:            }
105:
106:            /**
107:             * This constructor is used to create a foreign key field instance that is
108:             * a part of primary key field. See JDBCCMRFieldBridge.
109:             */
110:            public JDBCCMP2xFieldBridge(JDBCStoreManager manager,
111:                    String fieldName, Class fieldType, JDBCType jdbcType,
112:                    boolean readOnly, long readTimeOut, Class primaryKeyClass,
113:                    Field primaryKeyField,
114:                    JDBCCMP2xFieldBridge cmpFieldIAmMappedTo,
115:                    JDBCCMRFieldBridge myCMRField, String columnName)
116:                    throws DeploymentException {
117:                super (manager, fieldName, fieldType, jdbcType, readOnly,
118:                        readTimeOut, primaryKeyClass, primaryKeyField,
119:                        cmpFieldIAmMappedTo.getFieldIndex(),
120:                        cmpFieldIAmMappedTo.getTableIndex(),
121:                        cmpFieldIAmMappedTo.checkDirtyAfterGet,
122:                        cmpFieldIAmMappedTo.stateFactory);
123:                this .cmpFieldIAmMappedTo = cmpFieldIAmMappedTo;
124:                if (myCMRField != null) {
125:                    cmrChainLink = new CMRChainLink(myCMRField);
126:                    cmpFieldIAmMappedTo.addCMRChainLink(cmrChainLink);
127:                }
128:                this .columnName = columnName;
129:            }
130:
131:            // Public
132:
133:            public JDBCCMP2xFieldBridge getCmpFieldIAmMappedTo() {
134:                return cmpFieldIAmMappedTo;
135:            }
136:
137:            public ChainLink getCmrChainLink() {
138:                return cmrChainLink;
139:            }
140:
141:            public boolean isFKFieldMappedToCMPField() {
142:                return cmpFieldIAmMappedTo != null && this .cmrChainLink != null;
143:            }
144:
145:            public String getColumnName() {
146:                return columnName;
147:            }
148:
149:            // JDBCFieldBridge implementation
150:
151:            public Object getInstanceValue(EntityEnterpriseContext ctx) {
152:                FieldState fieldState = getLoadedState(ctx);
153:                return fieldState.getValue();
154:            }
155:
156:            public void setInstanceValue(EntityEnterpriseContext ctx,
157:                    Object value) {
158:                FieldState fieldState = getFieldState(ctx);
159:
160:                // update current value
161:                if (cmpFieldIAmMappedTo != null
162:                        && cmpFieldIAmMappedTo.isPrimaryKeyMember()) {
163:                    // if this field shares the column with the primary key field and new value
164:                    // changes the primary key then we are in an illegal state.
165:                    if (value != null) {
166:                        if (fieldState.isLoaded()
167:                                && fieldState.isValueChanged(value)) {
168:                            throw new IllegalStateException(
169:                                    "New value ["
170:                                            + value
171:                                            + "] of a foreign key field "
172:                                            + getFieldName()
173:                                            + " changed the value of a primary key field "
174:                                            + cmpFieldIAmMappedTo
175:                                                    .getFieldName() + "["
176:                                            + fieldState.value + "]");
177:                        } else {
178:                            fieldState.setValue(value);
179:                        }
180:                    }
181:                } else {
182:                    if (cmrChainLink != null
183:                            && JDBCEntityBridge.isEjbCreateDone(ctx)
184:                            && fieldState.isLoaded()
185:                            && fieldState.isValueChanged(value)) {
186:                        cmrChainLink.execute(ctx, fieldState, value);
187:                    }
188:
189:                    fieldState.setValue(value);
190:                }
191:
192:                // we are loading the field right now so it isLoaded
193:                fieldState.setLoaded();
194:            }
195:
196:            public void lockInstanceValue(EntityEnterpriseContext ctx) {
197:                getFieldState(ctx).lockValue();
198:            }
199:
200:            public boolean isLoaded(EntityEnterpriseContext ctx) {
201:                return getFieldState(ctx).isLoaded();
202:            }
203:
204:            /**
205:             * Has the value of this field changes since the last time clean was called.
206:             */
207:            public boolean isDirty(EntityEnterpriseContext ctx) {
208:                return !primaryKeyMember && !readOnly
209:                        && getFieldState(ctx).isDirty();
210:            }
211:
212:            /**
213:             * Mark this field as clean. Saves the current state in context, so it
214:             * can be compared when isDirty is called.
215:             */
216:            public void setClean(EntityEnterpriseContext ctx) {
217:                FieldState fieldState = getFieldState(ctx);
218:                fieldState.setClean();
219:
220:                // update last read time
221:                if (readOnly && readTimeOut != -1)
222:                    fieldState.lastRead = System.currentTimeMillis();
223:            }
224:
225:            public void resetPersistenceContext(EntityEnterpriseContext ctx) {
226:                if (isReadTimedOut(ctx)) {
227:                    JDBCContext jdbcCtx = (JDBCContext) ctx
228:                            .getPersistenceContext();
229:                    FieldState fieldState = (FieldState) jdbcCtx
230:                            .getFieldState(jdbcContextIndex);
231:                    if (fieldState != null)
232:                        fieldState.reset();
233:                }
234:            }
235:
236:            public boolean isReadTimedOut(EntityEnterpriseContext ctx) {
237:                // if we are read/write then we are always timed out
238:                if (!readOnly)
239:                    return true;
240:
241:                // if read-time-out is -1 then we never time out.
242:                if (readTimeOut == -1)
243:                    return false;
244:
245:                long readInterval = System.currentTimeMillis()
246:                        - getFieldState(ctx).lastRead;
247:                return readInterval >= readTimeOut;
248:            }
249:
250:            public Object getLockedValue(EntityEnterpriseContext ctx) {
251:                return getLoadedState(ctx).getLockedValue();
252:            }
253:
254:            public void updateState(EntityEnterpriseContext ctx, Object value) {
255:                getFieldState(ctx).updateState(value);
256:            }
257:
258:            protected void setDirtyAfterGet(EntityEnterpriseContext ctx) {
259:                getFieldState(ctx).setCheckDirty();
260:            }
261:
262:            // Private
263:
264:            private FieldState getLoadedState(EntityEnterpriseContext ctx) {
265:                FieldState fieldState = getFieldState(ctx);
266:                if (!fieldState.isLoaded()) {
267:                    manager.loadField(this , ctx);
268:                    if (!fieldState.isLoaded())
269:                        throw new EJBException("Could not load field value: "
270:                                + getFieldName());
271:                }
272:                return fieldState;
273:            }
274:
275:            private void addCMRChainLink(ChainLink nextCMRChainLink) {
276:                if (cmrChainLink == null) {
277:                    cmrChainLink = new DummyChainLink();
278:                }
279:                cmrChainLink.setNextLink(nextCMRChainLink);
280:            }
281:
282:            private FieldState getFieldState(EntityEnterpriseContext ctx) {
283:                JDBCContext jdbcCtx = (JDBCContext) ctx.getPersistenceContext();
284:                FieldState fieldState = (FieldState) jdbcCtx
285:                        .getFieldState(jdbcContextIndex);
286:                if (fieldState == null) {
287:                    fieldState = new FieldState(jdbcCtx);
288:                    jdbcCtx.setFieldState(jdbcContextIndex, fieldState);
289:                }
290:                return fieldState;
291:            }
292:
293:            // Inner
294:
295:            private class FieldState {
296:                /** entity's state this field state belongs to */
297:                private JDBCEntityBridge.EntityState entityState;
298:                /** current field value */
299:                private Object value;
300:                /** previous field state. NOTE: it might not be the same as previous field value */
301:                private Object state;
302:                /** locked field value */
303:                private Object lockedValue;
304:                /** last time the field was read */
305:                private long lastRead = -1;
306:
307:                public FieldState(JDBCContext jdbcCtx) {
308:                    this .entityState = jdbcCtx.getEntityState();
309:                }
310:
311:                /**
312:                 * Reads current field value.
313:                 * @return current field value.
314:                 */
315:                public Object getValue() {
316:                    //if(checkDirtyAfterGet)
317:                    //   setCheckDirty();
318:                    return value;
319:                }
320:
321:                /**
322:                 * Sets new field value and sets the flag that setter was called on the field
323:                 * @param newValue  new field value.
324:                 */
325:                public void setValue(Object newValue) {
326:                    this .value = newValue;
327:                    setCheckDirty();
328:                }
329:
330:                private void setCheckDirty() {
331:                    entityState.setCheckDirty(tableIndex);
332:                }
333:
334:                /**
335:                 * @return true if the field is loaded.
336:                 */
337:                public boolean isLoaded() {
338:                    return entityState.isLoaded(tableIndex);
339:                }
340:
341:                /**
342:                 * Marks the field as loaded.
343:                 */
344:                public void setLoaded() {
345:                    entityState.setLoaded(tableIndex);
346:                }
347:
348:                /**
349:                 * @return true if the field is dirty.
350:                 */
351:                public boolean isDirty() {
352:                    return isLoaded()
353:                            && !stateFactory.isStateValid(state, value);
354:                }
355:
356:                /**
357:                 * Compares current value to a new value. Note, it does not compare
358:                 * field states, just values.
359:                 * @param newValue  new field value
360:                 * @return true if field values are not equal.
361:                 */
362:                public boolean isValueChanged(Object newValue) {
363:                    return value == null ? newValue != null : !value
364:                            .equals(newValue);
365:                }
366:
367:                /**
368:                 * Resets masks and updates the state.
369:                 */
370:                public void setClean() {
371:                    entityState.setClean(tableIndex);
372:                    updateState(value);
373:                }
374:
375:                /**
376:                 * Updates the state to some specific value that might be different from the current
377:                 * field's value. This trick is needed for foreign key fields because they can be
378:                 * changed while not being loaded. When the owning CMR field is loaded this method is
379:                 * called with the loaded from the database value. Thus, we have correct state and locked value.
380:                 * @param value  the value loaded from the database.
381:                 */
382:                private void updateState(Object value) {
383:                    state = stateFactory.getFieldState(value);
384:                    lockedValue = value;
385:                }
386:
387:                /**
388:                 * Resets everything.
389:                 */
390:                public void reset() {
391:                    value = null;
392:                    state = null;
393:                    lastRead = -1;
394:                    entityState.resetFlags(tableIndex);
395:                }
396:
397:                public void lockValue() {
398:                    if (entityState.lockValue(tableIndex)) {
399:                        //log.debug("locking> " + fieldName + "=" + value);
400:                        lockedValue = value;
401:                    }
402:                }
403:
404:                public Object getLockedValue() {
405:                    return lockedValue;
406:                }
407:            }
408:
409:            /**
410:             * Represents a link in the chain. The execute method will doExecute each link
411:             * in the chain except for the link (originator) execute() was called on.
412:             */
413:            private abstract static class ChainLink {
414:                private ChainLink nextLink;
415:
416:                public ChainLink() {
417:                    nextLink = this ;
418:                }
419:
420:                public void setNextLink(ChainLink nextLink) {
421:                    nextLink.nextLink = this .nextLink;
422:                    this .nextLink = nextLink;
423:                }
424:
425:                public ChainLink getNextLink() {
426:                    return nextLink;
427:                }
428:
429:                public void execute(EntityEnterpriseContext ctx,
430:                        FieldState fieldState, Object newValue) {
431:                    nextLink.doExecute(this , ctx, fieldState, newValue);
432:                }
433:
434:                protected abstract void doExecute(ChainLink originator,
435:                        EntityEnterpriseContext ctx, FieldState fieldState,
436:                        Object newValue);
437:            }
438:
439:            /**
440:             * This chain link contains a CMR field a foreign key of which is mapped to a CMP field.
441:             */
442:            private static class CMRChainLink extends ChainLink {
443:                private final JDBCCMRFieldBridge cmrField;
444:
445:                public CMRChainLink(JDBCCMRFieldBridge cmrField) {
446:                    this .cmrField = cmrField;
447:                }
448:
449:                /**
450:                 * Going down the chain current related id is calculated and stored in oldRelatedId.
451:                 * When the next link is originator, the flow is going backward:
452:                 * - field state is updated with new vaue;
453:                 * - new related id is calculated;
454:                 * - old relationship is destroyed (if there is one);
455:                 * - new relationship is established (if it is valid).
456:                 *
457:                 * @param originator  ChainLink that started execution.
458:                 * @param ctx  EnterpriseEntityContext of the entity.
459:                 * @param fieldState  field's state.
460:                 * @param newValue  new field value.
461:                 */
462:                public void doExecute(ChainLink originator,
463:                        EntityEnterpriseContext ctx, FieldState fieldState,
464:                        Object newValue) {
465:                    // get old related id
466:                    Object oldRelatedId = cmrField.getRelatedIdFromContext(ctx);
467:
468:                    // invoke down the cmrChain
469:                    if (originator != getNextLink()) {
470:                        getNextLink().doExecute(originator, ctx, fieldState,
471:                                newValue);
472:                    }
473:
474:                    // update field state
475:                    fieldState.setValue(newValue);
476:
477:                    // get new related id
478:                    Object newRelatedId = cmrField.getRelatedIdFromContext(ctx);
479:
480:                    // destroy old relationship
481:                    if (oldRelatedId != null)
482:                        destroyRelations(oldRelatedId, ctx);
483:
484:                    // establish new relationship
485:                    if (newRelatedId != null)
486:                        createRelations(newRelatedId, ctx);
487:                }
488:
489:                private void createRelations(Object newRelatedId,
490:                        EntityEnterpriseContext ctx) {
491:                    try {
492:                        if (cmrField.isForeignKeyValid(newRelatedId)) {
493:                            cmrField.createRelationLinks(ctx, newRelatedId,
494:                                    false);
495:                        } else {
496:                            // set foreign key to a new value
497:                            cmrField.setForeignKey(ctx, newRelatedId);
498:                            // put calculated relatedId to the waiting list
499:                            if (ctx.getId() != null) {
500:                                JDBCCMRFieldBridge relatedCMRField = (JDBCCMRFieldBridge) cmrField
501:                                        .getRelatedCMRField();
502:                                relatedCMRField.addRelatedPKWaitingForMyPK(
503:                                        newRelatedId, ctx.getId());
504:                            }
505:                        }
506:                    } catch (Exception e) {
507:                        // no such object
508:                    }
509:                }
510:
511:                private void destroyRelations(Object oldRelatedId,
512:                        EntityEnterpriseContext ctx) {
513:                    JDBCCMRFieldBridge relatedCMRField = (JDBCCMRFieldBridge) cmrField
514:                            .getRelatedCMRField();
515:                    relatedCMRField.removeRelatedPKWaitingForMyPK(oldRelatedId,
516:                            ctx.getId());
517:                    try {
518:                        if (cmrField.isForeignKeyValid(oldRelatedId)) {
519:                            cmrField.destroyRelationLinks(ctx, oldRelatedId,
520:                                    true, false);
521:                        }
522:                    } catch (Exception e) {
523:                        // no such object
524:                    }
525:                }
526:            }
527:
528:            private static class DummyChainLink extends ChainLink {
529:                public void doExecute(ChainLink originator,
530:                        EntityEnterpriseContext ctx, FieldState fieldState,
531:                        Object newValue) {
532:                    // invoke down the cmrChain
533:                    if (originator != getNextLink()) {
534:                        getNextLink().doExecute(originator, ctx, fieldState,
535:                                newValue);
536:                    }
537:                    // update field state
538:                    fieldState.setValue(newValue);
539:                }
540:            }
541:        }
w__w__w_.___j___a_v__a2__s___.co___m__ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.