Source Code Cross Referenced for Record.java in  » Database-ORM » ODAL » com » completex » objective » components » persistency » 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 » ODAL » com.completex.objective.components.persistency 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         *  Objective Database Abstraction Layer (ODAL)
0003:         *  Copyright (c) 2004, The ODAL Development Group
0004:         *  All rights reserved.
0005:         *  For definition of the ODAL Development Group please refer to LICENCE.txt file
0006:         *
0007:         *  Distributable under LGPL license.
0008:         *  See terms of license at gnu.org.
0009:         */package com.completex.objective.components.persistency;
0010:
0011:        import com.completex.objective.components.persistency.core.impl.LinkDependencyGraph;
0012:        import com.completex.objective.components.persistency.core.impl.LinkIterator;
0013:        import com.completex.objective.components.persistency.core.impl.query.QueryContext;
0014:        import com.completex.objective.components.persistency.transact.Transaction;
0015:        import com.completex.objective.components.persistency.type.BlobImpl;
0016:        import com.completex.objective.components.persistency.type.ClobImpl;
0017:
0018:        import java.io.*;
0019:        import java.sql.Blob;
0020:        import java.sql.Clob;
0021:        import java.sql.SQLException;
0022:        import java.util.*;
0023:
0024:        /**
0025:         * Representation of linked table structure. Each record is mapped to database table and optionally
0026:         * has links to another records.
0027:         *
0028:         * @author Gennady Krizhevsky
0029:         */
0030:        public class Record implements  Cloneable {
0031:            public static final DefaultToParametersPolicy DEFAULT_TO_PARAMETERS_POLICY = new DefaultToParametersPolicy();
0032:            public static final NotNullToParametersPolicy NOT_NULL_TO_PARAMETERS_POLICY = new NotNullToParametersPolicy();
0033:
0034:            public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
0035:
0036:            static final long serialVersionUID = 1L;
0037:            private MetaTable table;
0038:            private String tableName;
0039:            private String tableAlias;
0040:            private PersistentEntry[] entries;
0041:            private State state = State.NEW;
0042:            private boolean hasDirtyNonKeyFields;
0043:            private boolean skipInsertForKeysOnly;
0044:            private boolean autoPadChars;
0045:            private boolean notOverwriteWithNulls;
0046:            private LinkDependencyGraph dependencyGraph;
0047:            private Link link;
0048:            private boolean preserveOriginalValues;
0049:            private transient boolean forceModify;
0050:            private PersistentObject persistentObject;
0051:
0052:            /**
0053:             * @param table
0054:             */
0055:            public Record(MetaTable table) {
0056:                this (table, false);
0057:            }
0058:
0059:            /**
0060:             * @param table
0061:             * @param skipInsertForKeysOnly if true records with only primary columnName values modified will not be persisted
0062:             */
0063:            public Record(MetaTable table, boolean skipInsertForKeysOnly) {
0064:                this (table, skipInsertForKeysOnly, false);
0065:            }
0066:
0067:            /**
0068:             * @param table
0069:             * @param skipInsertForKeysOnly if true records with only primary columnName values modified will not be persisted
0070:             * @param autoPadChars          if true char fields will be right padded with spaces to column length
0071:             */
0072:            public Record(MetaTable table, boolean skipInsertForKeysOnly,
0073:                    boolean autoPadChars) {
0074:                setupNewRecord(table, autoPadChars, skipInsertForKeysOnly);
0075:            }
0076:
0077:            private void setupNewRecord(MetaTable table, boolean autoPadChars,
0078:                    boolean skipInsertForKeysOnly) {
0079:                if (table == null) {
0080:                    throw new RuntimeException("table may not be empty !!!");
0081:                }
0082:                this .table = table;
0083:                setTableName(null);
0084:                this .entries = new PersistentEntry[table.size()];
0085:                for (int i = 0; i < this .entries.length; i++) {
0086:                    this .entries[i] = new PersistentEntry(table.getColumn(i),
0087:                            this );
0088:                    this .entries[i].setAutoPadChars(autoPadChars);
0089:                }
0090:                this .skipInsertForKeysOnly = skipInsertForKeysOnly;
0091:                this .autoPadChars = autoPadChars;
0092:                createLinkIfNotExist();
0093:            }
0094:
0095:            private Link createLinkIfNotExist() {
0096:                if (link == null) {
0097:                    link = new Link(null, null, null);
0098:                }
0099:                return link;
0100:            }
0101:
0102:            /**
0103:             * Adds persistent entry using the parameter one as a template (entry is deep cloned)
0104:             * 
0105:             * @param entry
0106:             */
0107:            public void addPersistentEntry(PersistentEntry entry) {
0108:                addPersistentEntry(null, entry);
0109:            }
0110:
0111:            /**
0112:             * Adds persistent entry using the parameter one as a template
0113:             * 
0114:             * @param newColumnName if not null, sets a new column name for added entry
0115:             * @param entry
0116:             */
0117:            public void addPersistentEntry(String newColumnName,
0118:                    PersistentEntry entry) {
0119:                addPersistentEntry(newColumnName, entry, true);
0120:            }
0121:
0122:            /**
0123:             * Adds persistent entry using the parameter one as a template
0124:             * 
0125:             * @param newColumnName if not null, sets a new column name for added entry
0126:             * @param entry
0127:             * @param cloneEntry if true added entry deep cloned before adding, otherwise it is added as is
0128:             */
0129:            protected void addPersistentEntry(String newColumnName,
0130:                    PersistentEntry entry, boolean cloneEntry) {
0131:                if (table.isStaticFinal()) {
0132:                    MetaTable clonedTable = table.cloneDeepSafe();
0133:                    clonedTable.setStaticFinal(false);
0134:                    table = clonedTable;
0135:                }
0136:                int newSize = entries.length + 1;
0137:                int newLastIndex = newSize - 1;
0138:
0139:                MetaColumn column = entry.getColumn().cloneSafe();
0140:                column.setColumnIndex(newLastIndex);
0141:                if (newColumnName != null) {
0142:                    column.setColumnName(newColumnName);
0143:                }
0144:
0145:                table.addColumn(column);
0146:                PersistentEntry[] newEntries = new PersistentEntry[newSize];
0147:                System.arraycopy(entries, 0, newEntries, 0, entries.length);
0148:                if (cloneEntry) {
0149:                    newEntries[newLastIndex] = entry.cloneDeepSafe();
0150:                } else {
0151:                    newEntries[newLastIndex] = entry;
0152:                }
0153:                for (int i = 0; i < newEntries.length; i++) {
0154:                    PersistentEntry newEntry = newEntries[i];
0155:                    newEntry.setRecord(this );
0156:                }
0157:
0158:                entries = newEntries;
0159:            }
0160:
0161:            /**
0162:             * Sets parent <code>PersistentObject</code>
0163:             *
0164:             * @param persistentObject
0165:             */
0166:            void setPersistentObject(PersistentObject persistentObject) {
0167:                this .persistentObject = persistentObject;
0168:            }
0169:
0170:            /**
0171:             * Gets parent <code>PersistentObject</code>
0172:             *
0173:             * @return parent PersistentObject
0174:             */
0175:            public PersistentObject getPersistentObject() {
0176:                return persistentObject;
0177:            }
0178:
0179:            /**
0180:             * Returns <tt>Link</tt> reperesentation of this Record
0181:             *
0182:             * @return Link reperesentation of this Record
0183:             */
0184:            public Link toLink() {
0185:                return link;
0186:            }
0187:
0188:            /**
0189:             * Gets <tt>LinkDependencyGraph</tt>
0190:             *
0191:             * @return LinkDependencyGraph
0192:             */
0193:            public LinkDependencyGraph getDependencyGraph() {
0194:                return dependencyGraph;
0195:            }
0196:
0197:            /**
0198:             * Sets <tt>LinkDependencyGraph</tt>
0199:             *
0200:             * @param dependencyGraph
0201:             * @see LinkDependencyGraph
0202:             */
0203:            public void setDependencyGraph(LinkDependencyGraph dependencyGraph) {
0204:                this .dependencyGraph = dependencyGraph;
0205:            }
0206:
0207:            /**
0208:             * Assembles <tt>LinkDependencyGraph</tt>
0209:             *
0210:             * @param persistentObject
0211:             */
0212:            void assemble(AbstractPersistentObject persistentObject) {
0213:                if (dependencyGraph != null) {
0214:                    dependencyGraph.assemble(persistentObject);
0215:                }
0216:            }
0217:
0218:            /**
0219:             * Returns <tt>MetaTable</tt> associated with this Record
0220:             *
0221:             * @return MetaTable associated with this Record
0222:             */
0223:            public MetaTable getTable() {
0224:                return table;
0225:            }
0226:
0227:            /**
0228:             * Returns array of persistent entries
0229:             *
0230:             * @return PersistentEntry[] - array of persistent entries
0231:             * @see PersistentEntry
0232:             */
0233:            protected PersistentEntry[] getEntries() {
0234:                return entries;
0235:            }
0236:
0237:            /**
0238:             * @param state
0239:             * @see State
0240:             */
0241:            public void setState(State state) {
0242:                this .state = state;
0243:            }
0244:
0245:            /**
0246:             * @return Record state
0247:             * @see State
0248:             */
0249:            public State getState() {
0250:                return state;
0251:            }
0252:
0253:            /**
0254:             * @return true if Record has dirty non columnName fields
0255:             */
0256:            public boolean hasDirtyNonKeyFields() {
0257:                return hasDirtyNonKeyFields;
0258:            }
0259:
0260:            /**
0261:             * @param hasDirtyNonKeyFields
0262:             */
0263:            public void setHasDirtyNonKeyFields(boolean hasDirtyNonKeyFields) {
0264:                this .hasDirtyNonKeyFields = hasDirtyNonKeyFields;
0265:            }
0266:
0267:            /**
0268:             * @return true if the Record will not be persisted in case of columnName only fields are populated
0269:             */
0270:            public boolean isSkipInsertForKeysOnly() {
0271:                return skipInsertForKeysOnly;
0272:            }
0273:
0274:            /**
0275:             * @param skipInsertForKeysOnly
0276:             */
0277:            public void setSkipInsertForKeysOnly(boolean skipInsertForKeysOnly) {
0278:                this .skipInsertForKeysOnly = skipInsertForKeysOnly;
0279:            }
0280:
0281:            /**
0282:             * @return if char fields will be right padded with spaces to column length
0283:             */
0284:            public boolean isAutoPadChars() {
0285:                return autoPadChars;
0286:            }
0287:
0288:            /**
0289:             * Sets autoPadChars flag.
0290:             * If set to true, character fields will be right padded with spaces to column length
0291:             *
0292:             * @param autoPadChars if true char fields will be right padded with spaces to column length
0293:             */
0294:            public void setAutoPadChars(boolean autoPadChars) {
0295:                this .autoPadChars = autoPadChars;
0296:            }
0297:
0298:            /**
0299:             * @return if original values will be serialized when parent persistent object
0300:             *         gets serialized though Externalizeable interface methods
0301:             */
0302:            public boolean isPreserveOriginalValues() {
0303:                return preserveOriginalValues;
0304:            }
0305:
0306:            /**
0307:             * @param preserveOriginalValues if true original values will be serialized when parent persistent object
0308:             *                               gets serialized though Externalizeable interface methods
0309:             */
0310:            public void setPreserveOriginalValues(boolean preserveOriginalValues) {
0311:                this .preserveOriginalValues = preserveOriginalValues;
0312:            }
0313:
0314:            //
0315:            // Getters/Setter by columnName:
0316:            //
0317:
0318:            /**
0319:             * @param columnName
0320:             * @return true is value is null
0321:             */
0322:            public boolean isNull(String columnName) {
0323:                return getObject(columnName) == null;
0324:            }
0325:
0326:            /**
0327:             * @param columnName
0328:             * @return field value as Number
0329:             */
0330:            public Number getNumber(String columnName) {
0331:                Number value = null;
0332:                try {
0333:                    value = (Number) getObject(columnName);
0334:                } catch (ClassCastException e) {
0335:                    handleClassCastException(e, value, "Number");
0336:                }
0337:                return value;
0338:            }
0339:
0340:            /**
0341:             * Returns field value as Boolean
0342:             *
0343:             * @param columnName
0344:             * @return field value as Boolean
0345:             */
0346:            public Boolean getBoolean(String columnName) {
0347:                Boolean value = null;
0348:                try {
0349:                    value = (Boolean) getObject(columnName);
0350:                } catch (ClassCastException e) {
0351:                    handleClassCastException(e, value, "Boolean");
0352:                }
0353:                return value;
0354:            }
0355:
0356:            /**
0357:             * Returns field value as Date
0358:             *
0359:             * @param columnName
0360:             * @return field value as Date
0361:             */
0362:            public Date getDate(String columnName) {
0363:                Date value = null;
0364:                try {
0365:                    value = (Date) getObject(columnName);
0366:                } catch (ClassCastException e) {
0367:                    handleClassCastException(e, value, "Date");
0368:                }
0369:                return value;
0370:            }
0371:
0372:            /**
0373:             * Returns field value as String
0374:             *
0375:             * @param columnName
0376:             * @return field value as String
0377:             */
0378:            public String getString(String columnName) {
0379:                String value = null;
0380:                try {
0381:                    value = (String) getObject(columnName);
0382:                } catch (ClassCastException e) {
0383:                    handleClassCastException(e, value, "String");
0384:                }
0385:                return value;
0386:            }
0387:
0388:            /**
0389:             * Returns field value as Object
0390:             *
0391:             * @param columnName
0392:             * @return field value as Object
0393:             */
0394:            public Object getObject(String columnName) {
0395:                return entries[getIndex(columnName)].getValue();
0396:            }
0397:
0398:            /**
0399:             * Sets field value by column name
0400:             *
0401:             * @param columnName
0402:             * @param value
0403:             */
0404:            public void setObject(String columnName, Object value) {
0405:                setObject(getIndex(columnName), value);
0406:            }
0407:
0408:            /**
0409:             * @param columnName
0410:             * @return original value as Object
0411:             */
0412:            public Object getOriginalObject(String columnName) {
0413:                return entries[getIndex(columnName)].getOriginalValue();
0414:            }
0415:
0416:            //
0417:            // Getters/Setters by index:
0418:            //
0419:
0420:            /**
0421:             * @param index
0422:             * @return true is value is null
0423:             */
0424:            public boolean isNull(int index) {
0425:                return getObject(index) == null;
0426:            }
0427:
0428:            /**
0429:             * @param index
0430:             * @return field value as Number
0431:             */
0432:            public Number getNumber(int index) {
0433:                Number value = null;
0434:                try {
0435:                    Object obj = getObject(index);
0436:                    if (obj != null) {
0437:                        value = (Number) obj;
0438:                    }
0439:                } catch (ClassCastException e) {
0440:                    handleClassCastException(e, value, "Number");
0441:                }
0442:                return value;
0443:            }
0444:
0445:            /**
0446:             * @param index
0447:             * @return field value as Boolean
0448:             */
0449:            public Boolean getBoolean(int index) {
0450:                Boolean value = null;
0451:                try {
0452:                    Object obj = getObject(index);
0453:                    if (obj != null) {
0454:                        value = (Boolean) obj;
0455:                    }
0456:                } catch (ClassCastException e) {
0457:                    handleClassCastException(e, value, "Boolean");
0458:                }
0459:                return value;
0460:            }
0461:
0462:            /**
0463:             * Returns field value as Date
0464:             *
0465:             * @param index
0466:             * @return field value as Date
0467:             */
0468:            public Date getDate(int index) {
0469:                Date value = null;
0470:                try {
0471:                    Object obj = getObject(index);
0472:                    if (obj != null) {
0473:                        value = (Date) obj;
0474:                    }
0475:                } catch (ClassCastException e) {
0476:                    handleClassCastException(e, value, "Date");
0477:                }
0478:                return value;
0479:            }
0480:
0481:            /**
0482:             * Returns field value as String
0483:             *
0484:             * @param index
0485:             * @return field value as String
0486:             */
0487:            public String getString(int index) {
0488:                String value = null;
0489:                try {
0490:                    Object obj = getObject(index);
0491:                    if (obj != null) {
0492:                        value = obj.toString();
0493:                    }
0494:                } catch (ClassCastException e) {
0495:                    handleClassCastException(e, value, "String");
0496:                }
0497:                return value;
0498:            }
0499:
0500:            /**
0501:             * Returns field value as Object
0502:             *
0503:             * @param index
0504:             * @return field value as Object
0505:             */
0506:            public Object getObject(int index) {
0507:                validateIndex(index);
0508:                return entries[index].getValue();
0509:            }
0510:
0511:            /**
0512:             * Sets field value by index
0513:             *
0514:             * @param index
0515:             * @param value
0516:             */
0517:            public boolean setObject(int index, Object value) {
0518:                if (value == null && notOverwriteWithNulls) {
0519:                    return false;
0520:                }
0521:                if (different(getObject(index), value)) {
0522:                    PersistentEntry entry = entries[index];
0523:                    entry.setAutoPadChars(autoPadChars);
0524:                    moveRecordState(entry, value);
0525:                    return true;
0526:                }
0527:                return false;
0528:            }
0529:
0530:            /**
0531:             * @param index
0532:             * @return original value as Object
0533:             */
0534:            public Object getOriginalObject(int index) {
0535:                validateIndex(index);
0536:                return entries[index].getOriginalValue();
0537:            }
0538:
0539:            /**
0540:             * @param entry
0541:             * @param value
0542:             * @see State
0543:             */
0544:            private void moveRecordState(PersistentEntry entry, Object value) {
0545:                if (state == State.NEW_INITIALIZING) {
0546:                    if (entry != null) {
0547:                        entry.setValue(value, value);
0548:                        return;
0549:                    }
0550:                } else if (state == State.NEW || state == State.NEW_MODIFIED) {
0551:                    state = State.NEW_MODIFIED;
0552:                } else if (state == State.DELETED) {
0553:                    // Do nothing here
0554:                } else {
0555:                    // gets here if state is DATA_SAVED/DATA_MODIFIED
0556:                    state = State.DATA_MODIFIED;
0557:                }
0558:                if (entry != null) {
0559:                    entry.setValue(value);
0560:                }
0561:            }
0562:
0563:            /**
0564:             * Moves record state to the next appropriate position
0565:             *
0566:             * @see State
0567:             */
0568:            void moveRecordState() {
0569:                moveRecordState(null, null);
0570:            }
0571:
0572:            /**
0573:             * @param index
0574:             * @return PersistentEntry
0575:             */
0576:            public PersistentEntry getEntry(int index) {
0577:                validateIndex(index);
0578:                return entries[index];
0579:            }
0580:
0581:            /**
0582:             * @param columnName
0583:             * @return PersistentEntry
0584:             */
0585:            public PersistentEntry getEntry(String columnName) {
0586:                return entries[getIndex(columnName)];
0587:            }
0588:
0589:            private void handleClassCastException(Exception e,
0590:                    Object sourceValue, String targetClass) {
0591:                if (e instanceof  ClassCastException) {
0592:                    throw new RuntimeException(": Cannot cast value of class ["
0593:                            + (sourceValue != null ? sourceValue.getClass()
0594:                                    .getName() : "null") + "] to class ["
0595:                            + targetClass + "]: " + e.getMessage(), e);
0596:                }
0597:            }
0598:
0599:            /**
0600:             * @return number of persistent entries
0601:             */
0602:            public int size() {
0603:                return entries.length;
0604:            }
0605:
0606:            private void validateIndex(int index) {
0607:                if (index < 0 || index > entries.length) {
0608:                    throw new IndexOutOfBoundsException(
0609:                            "Cannot find column by index " + index);
0610:                }
0611:            }
0612:
0613:            /**
0614:             * @param columnName
0615:             * @return column index corresponding to column name
0616:             */
0617:            public int getIndex(String columnName) {
0618:                MetaColumn column = table.getColumn(columnName);
0619:                if (column == null) {
0620:                    throw new IllegalArgumentException(
0621:                            "Cannot find column by columnName " + columnName);
0622:                }
0623:                return column.getColumnIndex();
0624:            }
0625:
0626:            //
0627:            // Flags:
0628:            //
0629:
0630:            /**
0631:             * Traverses through of child objects of parent persistent object of this record
0632:             * and returns true if at least one of them is dirty. If persistent object is not complex - returns false
0633:             *
0634:             * @return true if at least one of child objects of parent persistent object of this record
0635:             *         is dirty
0636:             */
0637:            public boolean complexDirty() {
0638:                if (persistentObject != null && persistentObject.complex()) {
0639:                    if (dependencyGraph != null) {
0640:                        if (persistentObject.initializedComplex()) {
0641:                            return dependencyGraph.dirty();
0642:                        } else {
0643:                            throw new OdalRuntimePersistencyException(
0644:                                    "Complex object not initialized");
0645:                        }
0646:                    }
0647:                } else {
0648:                    return isDirty();
0649:                }
0650:                return false;
0651:            }
0652:
0653:            /**
0654:             * Returns true if one of the fields has been modified
0655:             *
0656:             * @return true if one of the fields is modified
0657:             */
0658:            public boolean isDirty() {
0659:                return state.isDirty();
0660:            }
0661:
0662:            /**
0663:             * @param index
0664:             * @return if field is modified
0665:             */
0666:            public boolean isFieldDirty(int index) {
0667:                validateIndex(index);
0668:                return entries[index].isDirty();
0669:            }
0670:
0671:            /**
0672:             * @param columnName
0673:             * @return if field is modified
0674:             */
0675:            public boolean isFieldDirty(String columnName) {
0676:                return entries[getIndex(columnName)].isDirty();
0677:            }
0678:
0679:            /**
0680:             * @param index
0681:             * @param dirty
0682:             */
0683:            public void setFieldDirty(int index, boolean dirty) {
0684:                validateIndex(index);
0685:                entries[index].setDirty(dirty);
0686:            }
0687:
0688:            /**
0689:             * @param columnName
0690:             * @param dirty
0691:             */
0692:            public void setFieldDirty(String columnName, boolean dirty) {
0693:                entries[getIndex(columnName)].setDirty(dirty);
0694:            }
0695:
0696:            /**
0697:             * Marks field as dirty
0698:             *
0699:             * @param index
0700:             */
0701:            public void markFieldDirty(int index) {
0702:                setFieldDirty(index, true);
0703:            }
0704:
0705:            /**
0706:             * Resets dirty flags
0707:             *
0708:             * @param index
0709:             */
0710:            public void unmarkFieldDirty(int index) {
0711:                setFieldDirty(index, false);
0712:            }
0713:
0714:            /**
0715:             * Marks all fields as dirty
0716:             */
0717:            public void markAllFieldsDirty() {
0718:                for (int i = 0; i < size(); i++) {
0719:                    markFieldDirty(i);
0720:                }
0721:            }
0722:
0723:            /**
0724:             * Resets dirty flags
0725:             */
0726:            public void unmarkAllFieldsDirty() {
0727:                for (int i = 0; i < size(); i++) {
0728:                    unmarkFieldDirty(i);
0729:                }
0730:                hasDirtyNonKeyFields = false;
0731:            }
0732:
0733:            /**
0734:             * Resets record state and dirty flags
0735:             */
0736:            public void resetAfterModify() {
0737:                for (int i = 0; i < size(); i++) {
0738:                    if (state == State.NEW_MODIFIED
0739:                            || state == State.NEW_INITIALIZING) {
0740:                        getEntry(i).setValue(getEntry(i).getValue(),
0741:                                getEntry(i).getValue());
0742:                    }
0743:                    unmarkFieldDirty(i);
0744:                }
0745:                hasDirtyNonKeyFields = false;
0746:                state = State.DATA_SAVED;
0747:            }
0748:
0749:            /**
0750:             * Returns true if this record came from or been saved to database
0751:             *
0752:             * @return true if this record came from or been saved to database
0753:             */
0754:            public boolean isInitialized() {
0755:                return state.isInitialized();
0756:            }
0757:
0758:            /**
0759:             * Return true this record has been deleted
0760:             *
0761:             * @return true this record has been deleted
0762:             */
0763:            public boolean isDeleted() {
0764:                return state.isDeleted();
0765:            }
0766:
0767:            /**
0768:             * Returns true if this record has been saved to database
0769:             *
0770:             * @return true if this record has been saved to database
0771:             */
0772:            public boolean isSaved() {
0773:                return state.isSaved();
0774:            }
0775:
0776:            /**
0777:             * Returns true if record values will not be overwritten by null values
0778:             *
0779:             * @return true if record values will not be overwritten by null values
0780:             */
0781:            public boolean isNotOverwriteWithNulls() {
0782:                return notOverwriteWithNulls;
0783:            }
0784:
0785:            /**
0786:             * @param notOverwriteWithNulls true if record values will not be overwritten by null values
0787:             */
0788:            public void setNotOverwriteWithNulls(boolean notOverwriteWithNulls) {
0789:                this .notOverwriteWithNulls = notOverwriteWithNulls;
0790:            }
0791:
0792:            /**
0793:             * Returns true is before and after values are different or
0794:             * the record is not yet initialized
0795:             *
0796:             * @param before
0797:             * @param after
0798:             * @return true is before and after values are different or the record is not yet initialized
0799:             */
0800:            protected boolean different(Object before, Object after) {
0801:                return different(this , before, after);
0802:            }
0803:
0804:            public static boolean different(Record record, Object before,
0805:                    Object after) {
0806:                if (record == null) {
0807:                    throw new IllegalArgumentException("Record is null");
0808:                }
0809:                if (!record.isInitialized()) {
0810:                    return true;
0811:                }
0812:                return PersistentEntry.different(before, after);
0813:            }
0814:
0815:            /**
0816:             * Right pads character fields to column length with spaces.
0817:             *
0818:             * @param index
0819:             * @param value
0820:             * @return Object
0821:             */
0822:            public Object v2c(int index, Object value) {
0823:                if (value == null) {
0824:                    return null;
0825:                }
0826:                return table.getColumn(index).v2c(value);
0827:            }
0828:
0829:            /**
0830:             * Right pads character fields to column length with spaces.
0831:             *
0832:             * @param columnName
0833:             * @param value
0834:             * @return Object
0835:             */
0836:            public Object v2c(String columnName, Object value) {
0837:                if (value == null) {
0838:                    return null;
0839:                }
0840:                return table.getColumn(columnName).v2c(value);
0841:            }
0842:
0843:            /**
0844:             * Return true if this record contains no persistent entries
0845:             *
0846:             * @return true if this record contains no persistent entries
0847:             */
0848:            public boolean isEmpty() {
0849:                return entries.length == 0;
0850:            }
0851:
0852:            /**
0853:             * Returns  <tt>Parameters</tt> object based on values and column types of the record for columns with indeces
0854:             * specified with "indeces" parameter. This method will populate parameters regardless of whether they are
0855:             * "dirty" flags or nulls
0856:             *
0857:             * @param indeces
0858:             * @return Parameters object based on values and column types of the record for columns with indeces
0859:             *         specified with "indeces" parameter
0860:             */
0861:            public Parameters toParameters(int[] indeces) {
0862:                Parameters parameters = new Parameters(indeces.length);
0863:                for (int i = 0; i < indeces.length; i++) {
0864:                    ColumnType columnType = getTable().getColumn(i).getType();
0865:                    parameters.add(columnType, getObject(indeces[i]));
0866:                }
0867:                return parameters;
0868:            }
0869:
0870:            /**
0871:             * Returns <tt>Parameters</tt> object based on values and column types of the record.
0872:             * This method will populate parameters only if corresponding fields are
0873:             * "dirty" and not nulls
0874:             *
0875:             * @param primaryKeyOnly if true only primary key columns are considered
0876:             * @return Parameters object based on values and column types of the record
0877:             */
0878:            public Parameters toNotNullParameters(boolean primaryKeyOnly) {
0879:                return toNotNullParameters(this , primaryKeyOnly);
0880:            }
0881:
0882:            /**
0883:             * Returns <tt>Parameters</tt> object based on values and column types of the record.
0884:             * This method will populate parameters only if corresponding fields are "dirty"
0885:             *
0886:             * @param primaryKeyOnly if true only primary key columns are considered
0887:             * @return Parameters object based on values and column types of the record
0888:             */
0889:            public Parameters toParameters(boolean primaryKeyOnly) {
0890:                return toParameters(this , primaryKeyOnly);
0891:            }
0892:
0893:            /**
0894:             * Returns <tt>Parameters</tt> object based on values and column types of the record .
0895:             * This method will populate parameters only if corresponding fields are
0896:             * "dirty" and not nulls
0897:             *
0898:             * @param record         <tt>Record</tt>
0899:             * @param primaryKeyOnly if true only primary key columns are considered
0900:             * @return Parameters object based on values and column types of the record
0901:             */
0902:            public static Parameters toNotNullParameters(Record record,
0903:                    boolean primaryKeyOnly) {
0904:                return toParameters(record, primaryKeyOnly,
0905:                        NOT_NULL_TO_PARAMETERS_POLICY);
0906:            }
0907:
0908:            /**
0909:             * Returns <tt>Parameters</tt> object based on values and column types of the record.
0910:             * This method will populate all parameters only if corresponding fields are "dirty"
0911:             *
0912:             * @param record         <tt>Record</tt>
0913:             * @param primaryKeyOnly if true only primary key columns are considered
0914:             * @return Parameters object based on values and column types of the record
0915:             */
0916:            public static Parameters toParameters(Record record,
0917:                    boolean primaryKeyOnly) {
0918:                return toParameters(record, primaryKeyOnly,
0919:                        DEFAULT_TO_PARAMETERS_POLICY);
0920:            }
0921:
0922:            /**
0923:             * Returns <tt>Parameters</tt> object based on values and column types of the record.
0924:             * This method will populate parameters with accord to <tt>ToParametersPolicy</tt>
0925:             *
0926:             * @param record         <tt>Record</tt>
0927:             * @param primaryKeyOnly if true only primary key columns are considered
0928:             * @param policy         <tt>ToParametersPolicy</tt> object
0929:             * @return Parameters object based on values and column types of the record and ctl parameter
0930:             * @see ToParametersPolicy
0931:             */
0932:            public static Parameters toParameters(Record record,
0933:                    boolean primaryKeyOnly, ToParametersPolicy policy) {
0934:                Parameters parameters;
0935:                MetaTable table = record.getTable();
0936:                if (primaryKeyOnly) {
0937:                    parameters = new Parameters(table.keySize());
0938:                    for (int pkIndex = 0; pkIndex < table.keySize(); pkIndex++) {
0939:                        int columnIndex = table
0940:                                .getColumnIndexByPrimaryKeyIndex(pkIndex);
0941:                        Object value = record.getObject(columnIndex);
0942:                        ColumnType type = table.getColumn(columnIndex)
0943:                                .getType();
0944:                        policy.add(columnIndex, type, value, parameters);
0945:                    }
0946:                } else {
0947:                    parameters = new Parameters(record.size());
0948:                    for (int i = 0; i < record.size(); i++) {
0949:                        if (record.isFieldDirty(i)) {
0950:                            Object value = record.getObject(i);
0951:                            ColumnType type = table.getColumn(i).getType();
0952:                            policy.add(i, type, value, parameters);
0953:                        }
0954:                    }
0955:                }
0956:                return parameters;
0957:            }
0958:
0959:            /**
0960:             * Get child link result w/o
0961:             * causing lazy retrieval to fire
0962:             *
0963:             * @param name
0964:             * @return Object
0965:             */
0966:            protected Object getChildObjectStraight(String name) {
0967:                Link link = getChild(name);
0968:                if (link == null) {
0969:                    return null;
0970:                } else {
0971:                    return link.getResult();
0972:                }
0973:            }
0974:
0975:            /**
0976:             * Gets child link result object
0977:             *
0978:             * @param name
0979:             * @return child link result object
0980:             * @throws SQLException if child retrieval from database failed
0981:             */
0982:            public Object getChildObject(String name) throws SQLException {
0983:                Link link = getChild(name);
0984:                if (link == null) {
0985:                    return null;
0986:                } else if (link.getResult() != null || link.isRetrieved()) {
0987:                    return link.getResult();
0988:                } else if (link.isLazyRetrieval()) {
0989:                    link.setRetrieved(true);
0990:                    QueryCtl query = (QueryCtl) link.getQuery();
0991:                    Persistency persistency = query.getPersistency();
0992:                    if (persistency == null) {
0993:                        return null;
0994:                    }
0995:                    Transaction currentTransaction = persistency
0996:                            .getTransactionManager().getCurrentTransaction();
0997:                    PersistencyChildManager childManager = ((PersistencyChildManager) persistency);
0998:                    QueryContext queryContext = childManager
0999:                            .getCurrentQueryContext();
1000:
1001:                    // With lazy loading queryContext may be null if the loading is done outside of the query scope:
1002:                    if (queryContext == null) {
1003:                        queryContext = QueryContext.NULL_QUERY_CONTEXT;
1004:                    }
1005:
1006:                    childManager.selectChild(currentTransaction,
1007:                            new PersistentObject(this ), name, link,
1008:                            queryContext);
1009:                    childManager.selectChildren(currentTransaction, link,
1010:                            queryContext);
1011:                    return link.getResult();
1012:                } else {
1013:                    return null;
1014:                }
1015:            }
1016:
1017:            public Link getChild(String name) {
1018:                return toLink().getChild(name);
1019:            }
1020:
1021:            public void clearNonInlinedChildren() {
1022:                toLink().clearNonInlinedChildren();
1023:            }
1024:
1025:            /**
1026:             * Create new Record object with attributes base on this record
1027:             *
1028:             * @return new Record object with attributes base on this record
1029:             */
1030:            public Record newRecord() {
1031:                Record record = newRecord0();
1032:                LinkedHashMap newChildren = toLink().newChildren(
1033:                        record.toLink());
1034:                record.toLink().setChildren(newChildren);
1035:                return record;
1036:            }
1037:
1038:            private Record newRecord0() {
1039:                Record record = new Record(table);
1040:                setupPrimitiveFields(this , record);
1041:                onClone(record);
1042:                return record;
1043:            }
1044:
1045:            public static void setupPrimitiveFields(Record recordFrom,
1046:                    Record recordTo) {
1047:                recordTo.tableName = recordFrom.tableName;
1048:                recordTo.skipInsertForKeysOnly = recordFrom.skipInsertForKeysOnly;
1049:                recordTo.hasDirtyNonKeyFields = recordFrom.hasDirtyNonKeyFields;
1050:                recordTo.autoPadChars = recordFrom.autoPadChars;
1051:                recordTo.notOverwriteWithNulls = recordFrom.notOverwriteWithNulls;
1052:                recordTo.preserveOriginalValues = recordFrom.preserveOriginalValues;
1053:                recordTo.forceModify = recordFrom.forceModify;
1054:            }
1055:
1056:            private void onClone(Record record) {
1057:                Link this Link = this .toLink();
1058:                Link newLink = record.toLink();
1059:                newLink.setDependencyIndex(this Link.getDependencyIndex());
1060:                newLink.setPath(this Link.getPath());
1061:            }
1062:
1063:            /**
1064:             * @return deep copy of this record
1065:             * @throws CloneNotSupportedException
1066:             */
1067:            public Object clone() throws CloneNotSupportedException {
1068:                Record record = (Record) super .clone();
1069:                for (int i = 0; i < this .entries.length; i++) {
1070:                    record.entries[i] = (PersistentEntry) this .getEntries()[i]
1071:                            .clone();
1072:                    record.entries[i].setRecord(record);
1073:                }
1074:                Link link = new Link();
1075:                link.copyAll(toLink());
1076:                record.link = link;
1077:                record.toLink().setChildren(toLink().cloneChildren());
1078:                return record;
1079:            }
1080:
1081:            //
1082:            // Facade for table:
1083:            //
1084:
1085:            /**
1086:             * @param columnKey
1087:             * @return MetaColumn
1088:             */
1089:            public MetaColumn getColumn(String columnKey) {
1090:                return table.getColumn(columnKey);
1091:            }
1092:
1093:            /**
1094:             * @param columnIndex
1095:             * @return MetaColumn
1096:             */
1097:            public MetaColumn getColumn(int columnIndex) {
1098:                return table.getColumn(columnIndex);
1099:            }
1100:
1101:            /**
1102:             * Returns column name
1103:             *
1104:             * @param columnKey
1105:             * @return column name
1106:             */
1107:            public String getColumnName(String columnKey) {
1108:                return getColumn(columnKey).getColumnName();
1109:            }
1110:
1111:            /**
1112:             * Returns column name
1113:             *
1114:             * @param columnIndex
1115:             * @return column name
1116:             */
1117:            public String getColumnName(int columnIndex) {
1118:                return getColumn(columnIndex).getColumnName();
1119:            }
1120:
1121:            /**
1122:             * Returns fully qualified column name: [table name].[column name]
1123:             *
1124:             * @param columnKey
1125:             * @return full column name
1126:             */
1127:            public String getFullColumnName(String columnKey) {
1128:                return getColumn(columnKey).getFullColumnName();
1129:            }
1130:
1131:            /**
1132:             * Returns column alias
1133:             *
1134:             * @param columnKey
1135:             * @return column alias
1136:             */
1137:            public String getColumnAlias(String columnKey) {
1138:                return getColumn(columnKey).getColumnAlias();
1139:            }
1140:
1141:            /**
1142:             * Returns column alias
1143:             *
1144:             * @param columnIndex
1145:             * @return column alias
1146:             */
1147:            public String getColumnAlias(int columnIndex) {
1148:                return getColumn(columnIndex).getColumnAlias();
1149:            }
1150:
1151:            /**
1152:             * Returns fully qualified column name: [table name].[column name]
1153:             *
1154:             * @param columnIndex
1155:             * @return full column name
1156:             */
1157:            public String getFullColumnName(int columnIndex) {
1158:                return getColumn(columnIndex).getFullColumnName();
1159:            }
1160:
1161:            /**
1162:             * Return List<Integer> of primary key indeces
1163:             *
1164:             * @return List of primary key indeces
1165:             */
1166:            public List getPrimaryKey() {
1167:                return table.getPrimaryKey();
1168:            }
1169:
1170:            /**
1171:             * Return List<Integer> of optimistic lock column indeces
1172:             *
1173:             * @return List of optimistic lock column indeces
1174:             */
1175:            public List getOptLockKey() {
1176:                return table.getOptLockKey();
1177:            }
1178:
1179:            /**
1180:             * Return number of record columns
1181:             *
1182:             * @return number of record columns
1183:             */
1184:            public int getColumnCount() {
1185:                return table.size();
1186:            }
1187:
1188:            /**
1189:             * Implementation of Externalizable interface
1190:             *
1191:             * @param out
1192:             * @throws IOException
1193:             * @see java.io.Externalizable
1194:             */
1195:            public void writeExternal(ObjectOutput out) throws IOException {
1196:                out.writeBoolean(isPreserveOriginalValues());
1197:                if (isPreserveOriginalValues()) {
1198:                    out.writeObject(state.getName());
1199:                }
1200:                for (int i = 0; i < entries.length; i++) {
1201:                    PersistentEntry entry = entries[i];
1202:                    writeObject(out, entry.getValue());
1203:                    if (isPreserveOriginalValues()) {
1204:                        out.writeBoolean(entry.isDirty());
1205:                        if (MetaColumn.isKey(entry.getColumn())) {
1206:                            writeObject(out, entry.getOriginalValue());
1207:                        }
1208:                    }
1209:                }
1210:                marshalChildren(out);
1211:                marshalDescendant(out);
1212:            }
1213:
1214:            protected void writeObject(ObjectOutput out, Object value)
1215:                    throws IOException {
1216:                try {
1217:                    if (value instanceof  Serializable) {
1218:                        out.writeObject(value);
1219:                    } else if (value instanceof  InputStream) {
1220:                        InputStream inputStream = ((InputStream) value);
1221:                        BlobImpl blob = new BlobImpl(inputStream, 0);
1222:                        out.writeObject(blob);
1223:                    } else if (value instanceof  Blob) {
1224:                        BlobImpl blob = new BlobImpl(((Blob) value)
1225:                                .getBinaryStream(), 0);
1226:                        out.writeObject(blob);
1227:                    } else if (value instanceof  Clob) {
1228:                        ClobImpl clob = new ClobImpl(((Clob) value)
1229:                                .getCharacterStream());
1230:                        out.writeObject(clob);
1231:                    } else { // It will fail in case value is not null:
1232:                        out.writeObject(value);
1233:                    }
1234:                } catch (SQLException e) {
1235:                    String typeString = value.getClass().getName();
1236:                    throw new IOException("Cannot convert value of type "
1237:                            + typeString + ": " + e);
1238:                }
1239:            }
1240:
1241:            protected Object readObject(ObjectInput in, ColumnType type)
1242:                    throws IOException, ClassNotFoundException {
1243:                Object value = null;
1244:                try {
1245:                    if (type.getValueClass() == InputStream.class) {
1246:                        value = in.readObject();
1247:                        if (value instanceof  BlobImpl) {
1248:                            byte[] data = ((BlobImpl) value).getBytes();
1249:                            byte[] bytes = data == null ? EMPTY_BYTE_ARRAY
1250:                                    : data;
1251:                            value = new ByteArrayInputStream(bytes);
1252:                        } else if (value instanceof  ClobImpl) {
1253:                            ClobImpl clob = ((ClobImpl) value);
1254:                            String data = clob.getData();
1255:                            byte[] bytes = data == null ? EMPTY_BYTE_ARRAY
1256:                                    : data.getBytes(clob.getCharsetName());
1257:                            value = new ByteArrayInputStream(bytes);
1258:                        }
1259:                    } else {
1260:                        value = in.readObject();
1261:                    }
1262:                } catch (SQLException e) {
1263:                    String typeString = value.getClass().getName();
1264:                    throw new IOException("Cannot convert value of type "
1265:                            + typeString + ": " + e);
1266:                }
1267:                return value;
1268:            }
1269:
1270:            /**
1271:             * Serializes child links
1272:             *
1273:             * @param out
1274:             * @throws IOException
1275:             */
1276:            protected void marshalChildren(ObjectOutput out) throws IOException {
1277:                out.writeBoolean(toLink().hasChildren());
1278:                if (toLink().hasChildren()) {
1279:                    out.writeObject(toLink());
1280:                }
1281:            }
1282:
1283:            /**
1284:             * Implementation of Externalizable interface
1285:             *
1286:             * @param in
1287:             * @throws IOException
1288:             * @throws ClassNotFoundException
1289:             * @see java.io.Externalizable
1290:             */
1291:            public void readExternal(ObjectInput in) throws IOException,
1292:                    ClassNotFoundException {
1293:                preserveOriginalValues = in.readBoolean();
1294:                if (isPreserveOriginalValues()) {
1295:                    String stateName = (String) in.readObject();
1296:                    state = State.name2state(stateName);
1297:                }
1298:                for (int i = 0; i < entries.length; i++) {
1299:                    PersistentEntry entry = entries[i];
1300:                    Object value = readObject(in, entry.getType()); // Read value
1301:                    Object originalValue = value;
1302:                    if (isPreserveOriginalValues()) {
1303:                        boolean dirty = in.readBoolean();
1304:                        if (MetaColumn.isKey(entry.getColumn())) {
1305:                            originalValue = readObject(in, entry.getType()); // Read original value
1306:                        }
1307:                        entry.setUnmarkedValue(originalValue, originalValue);
1308:                        entry.setValueIfDiff(value);
1309:                        entry.setDirty(dirty);
1310:                    } else {
1311:                        entry.setUnmarkedValue(value, originalValue);
1312:                    }
1313:                }
1314:                unmarshalChildren(in);
1315:                unmarshalDescendant(in);
1316:            }
1317:
1318:            /**
1319:             * Deserializes child links
1320:             *
1321:             * @param in
1322:             * @throws IOException
1323:             * @throws ClassNotFoundException
1324:             */
1325:            protected void unmarshalChildren(ObjectInput in)
1326:                    throws IOException, ClassNotFoundException {
1327:                boolean hasChildren = in.readBoolean();
1328:                if (hasChildren) {
1329:                    Link link = (Link) in.readObject();
1330:                    toLink().setChildren(link.getChildren());
1331:                    LinkedHashMap children = toLink().getChildren();
1332:                    //
1333:                    // Now re-initialize children - put elements that had been missed in serialization:
1334:                    //
1335:                    PersistentObject persistent = persistentObject;
1336:                    setupUnmarshalledChildren(persistent, children);
1337:                }
1338:            }
1339:
1340:            public static void setupUnmarshalledChildren(
1341:                    PersistentObject persistent, LinkedHashMap children) {
1342:                if (persistent != null) {
1343:                    PersistentObject master = persistent.master();
1344:                    if (master != null) {
1345:                        Record masterRecord = master.record();
1346:                        LinkedHashMap masterChildren = masterRecord.toLink()
1347:                                .getChildren();
1348:                        for (Iterator it = masterChildren.keySet().iterator(); it
1349:                                .hasNext();) {
1350:                            String columnName = (String) it.next();
1351:                            Link masterLink = (Link) masterChildren
1352:                                    .get(columnName);
1353:                            Link slaveLink = (Link) children.get(columnName);
1354:
1355:                            if (slaveLink != null) {
1356:                                slaveLink.setInlineMode(masterLink
1357:                                        .getInlineMode());
1358:                                slaveLink.setLifeCycleController(masterLink
1359:                                        .getLifeCycleController());
1360:                                slaveLink.setQuery(masterLink.getQuery()
1361:                                        .newQuery());
1362:                                slaveLink.setParentIndeces(masterLink
1363:                                        .getParentIndeces());
1364:                                slaveLink.setThisIndeces(masterLink
1365:                                        .getThisIndeces());
1366:                                slaveLink.setDependencyIndex(masterLink
1367:                                        .getDependencyIndex());
1368:                                slaveLink.setLazyRetrieval(masterLink
1369:                                        .isLazyRetrieval());
1370:                                slaveLink.setCascadeDelete(masterLink
1371:                                        .isCascadeDelete());
1372:                                slaveLink.setCascadeInsert(masterLink
1373:                                        .isCascadeInsert());
1374:                                slaveLink.setCascadeUpdate(masterLink
1375:                                        .isCascadeUpdate());
1376:                                slaveLink.setTreatNullAsRemove(masterLink
1377:                                        .isTreatNullAsRemove());
1378:                                slaveLink.setInsertBeforeParent(masterLink
1379:                                        .isInsertBeforeParent());
1380:                            } else {
1381:                                System.err
1382:                                        .println("   Could not find slave link by name "
1383:                                                + columnName);
1384:                            }
1385:                        }
1386:                    }
1387:                }
1388:            }
1389:
1390:            //    protected Map toMap() {
1391:            //        Map map = new HashMap();
1392:            //        ArrayList entryList = new ArrayList(entries.length);
1393:            //        map.put("entries", entryList);
1394:            //        for (int i = 0; i < entries.length; i++) {
1395:            //            PersistentEntry entry = entries[i];
1396:            //            entryList.add(entry.toMap());
1397:            //        }
1398:            //        map.put("children", toMapChildren());
1399:            //        map.put("descendant", toMapDescendant());
1400:            //        return map;
1401:            //    }
1402:            //
1403:            //    protected Map toMapChildren() {
1404:            //        Map map = new HashMap();
1405:            //        map.put("hasChildren", Boolean.valueOf(toLink().hasChildren()));
1406:            //        return map;
1407:            //    }
1408:
1409:            //    protected Map toMapDescendant() {
1410:            //        return null;
1411:            //    }
1412:
1413:            /**
1414:             * Method to be implemented in descendants to add to objects being serialized thorugh
1415:             * writeExternal(ObjectOutput out) method
1416:             *
1417:             * @param out
1418:             * @throws IOException
1419:             */
1420:            protected void marshalDescendant(ObjectOutput out)
1421:                    throws IOException {
1422:            }
1423:
1424:            /**
1425:             * Method to be implemented in descendants to add to objects being serialized thorugh
1426:             * readExternal(ObjectOutput out) method
1427:             *
1428:             * @param in
1429:             * @throws IOException
1430:             * @throws ClassNotFoundException
1431:             */
1432:            protected void unmarshalDescendant(ObjectInput in)
1433:                    throws IOException, ClassNotFoundException {
1434:            }
1435:
1436:            /**
1437:             * Copies only dirty and updateable fields from source record to this record.
1438:             * If updateableFields Set is null then all dirty fields will be copied
1439:             *
1440:             * @param source           source record
1441:             * @param updateableFields set of updateable column names
1442:             */
1443:            public void copyDirty(Record source, Set updateableFields) {
1444:                copy(source, updateableFields, true);
1445:            }
1446:
1447:            /**
1448:             * Copies updateable fields from source record to this record.
1449:             * If updateableFields Set is null then all dirty fields will be copied.
1450:             * If dirtyFieldsOnly flag is true then only dirty fields are copied
1451:             *
1452:             * @param source           source record
1453:             * @param updateableFields set of updateable column names
1454:             * @param dirtyFieldsOnly  if true only dirty fields are copied
1455:             */
1456:            public void copy(Record source, Set updateableFields,
1457:                    boolean dirtyFieldsOnly) {
1458:                copy(source, updateableFields, dirtyFieldsOnly, false);
1459:            }
1460:
1461:            /**
1462:             * Copies updateable fields from source record to this record.
1463:             * If updateableFields Set is null then all dirty fields will be copied.
1464:             * If dirtyFieldsOnly flag is true then only dirty fields are copied
1465:             * If preserveStates is true then source record fields "dirty" states are passed unchanged
1466:             * from source record to this record even if the values are the same
1467:             *
1468:             * @param source           source record
1469:             * @param updateableFields set of updateable column names
1470:             * @param dirtyFieldsOnly  if true only dirty fields are copied
1471:             * @param preserveStates   if true then field "dirty" states are passed unchanged
1472:             *                         from source record to this record even if the values are the same
1473:             */
1474:            void copy(Record source, Set updateableFields,
1475:                    boolean dirtyFieldsOnly, boolean preserveStates) {
1476:                if (source.size() != this .size()) {
1477:                    throw new IllegalArgumentException("Size of input ["
1478:                            + source
1479:                            + "] is not equal to size of this object [" + this 
1480:                            + "]");
1481:                }
1482:
1483:                for (int i = 0; i < source.size(); i++) {
1484:                    if (isUpdateable(getColumn(i).getColumnName(),
1485:                            updateableFields)
1486:                            && (source.isFieldDirty(i) || !dirtyFieldsOnly)) {
1487:                        if (preserveStates) {
1488:                            getEntry(i).setValue(source.getEntry(i).getValue(),
1489:                                    source.getEntry(i).getOriginalValue());
1490:                            setFieldDirty(i, source.isFieldDirty(i));
1491:                        } else {
1492:                            setObject(i, source.getObject(i));
1493:                        }
1494:                    }
1495:                }
1496:                if (preserveStates) {
1497:                    setState(source.getState());
1498:                }
1499:            }
1500:
1501:            /**
1502:             * Copies updateable fields from source record to this record.
1503:             * If updateableFields Set is null then all dirty fields will be copied.
1504:             * If dirtyFieldsOnly flag is true then only dirty fields are copied
1505:             * Source record fields "dirty" states are passed unchanged
1506:             * from source record to this record even if the values are the same
1507:             *
1508:             * @param source           source record
1509:             * @param updateableFields set of updateable column names
1510:             * @param dirtyFieldsOnly  if true only dirty fields are copied
1511:             *                         from source record to this record even if the values are the same
1512:             */
1513:            void copyPreseveStates(Record source, Set updateableFields,
1514:                    boolean dirtyFieldsOnly) {
1515:                copy(source, updateableFields, dirtyFieldsOnly, true);
1516:            }
1517:
1518:            /**
1519:             * Copies all fields from source record to this record.
1520:             * Source record fields "dirty" states are passed unchanged
1521:             * from source record to this record even if the values are the same
1522:             *
1523:             * @param source source record
1524:             *               from source record to this record even if the values are the same
1525:             */
1526:            void copyPreseveStates(Record source) {
1527:                copy(source, null, false, true);
1528:            }
1529:
1530:            private boolean isUpdateable(String columnName, Set updateableFields) {
1531:                if (updateableFields != null) {
1532:                    return updateableFields.contains(columnName);
1533:                } else {
1534:                    return true;
1535:                }
1536:            }
1537:
1538:            //
1539:            //
1540:            //
1541:
1542:            /**
1543:             * Gets table name. If set it will supercede the underlying MetaTable one when used to build SQL statements.
1544:             *
1545:             * @return table name
1546:             */
1547:            public String getTableName() {
1548:                return tableName;
1549:            }
1550:
1551:            /**
1552:             * Sets table name which will supercede the underlying MetaTable one when used to build SQL statements.
1553:             *
1554:             * @param tableName
1555:             */
1556:            public void setTableName(String tableName) {
1557:                if (tableName == null || tableName.length() == 0) {
1558:                    this .tableName = table.getTableName();
1559:                } else {
1560:                    this .tableName = tableName;
1561:                }
1562:            }
1563:
1564:            public String getTableAlias() {
1565:                return tableAlias;
1566:            }
1567:
1568:            public void setTableAlias(String tableAlias) {
1569:                this .tableAlias = tableAlias;
1570:            }
1571:
1572:            /**
1573:             * Returns string representation of underlying MetaTable
1574:             *
1575:             * @return string representation of underlying MetaTable
1576:             */
1577:            public String tableToString() {
1578:                return table == null ? null : table.toString();
1579:            }
1580:
1581:            /**
1582:             * Compares field values of this record to another one passed as parameter.
1583:             *
1584:             * @param record
1585:             * @return true if field values of this record are equal to one passed as parameter.
1586:             */
1587:            public boolean fieldsEqual(Record record) {
1588:                if (record == null || this .size() != record.size()) {
1589:                    return false;
1590:                }
1591:
1592:                for (int i = 0; i < size(); i++) {
1593:                    if (getObject(i) == null) {
1594:                        if (record.getObject(i) != null) {
1595:                            return false;
1596:                        }
1597:                    } else if (!getObject(i).equals(record.getObject(i))) {
1598:                        return false;
1599:                    }
1600:                }
1601:                return true;
1602:            }
1603:
1604:            /**
1605:             * Add child link with specific name
1606:             *
1607:             * @param link
1608:             * @throws NullPointerException if link has no name set
1609:             * @see Link
1610:             */
1611:            public void addChild(Link link) {
1612:                toLink().addChild(link);
1613:            }
1614:
1615:            /**
1616:             * Returns record <tt>LinkIterator</tt>
1617:             *
1618:             * @return <tt>LinkIterator</tt>
1619:             */
1620:            public LinkIterator linkIterator() {
1621:                return toLink().linkIterator();
1622:            }
1623:
1624:            /**
1625:             * Returns true if this record has child links
1626:             *
1627:             * @return true if this record has child links
1628:             */
1629:            public boolean hasChildren() {
1630:                return toLink().hasChildren();
1631:            }
1632:
1633:            /**
1634:             * Sets result value to link with specific name name
1635:             *
1636:             * @param name  name of child link
1637:             * @param value
1638:             * @see Link#setResult(Object)
1639:             * @see Link#getName()
1640:             */
1641:            public void setChildObject(String name, Object value) {
1642:                toLink().setChildObject(name, value);
1643:            }
1644:
1645:            /**
1646:             * Experimental
1647:             *
1648:             * @return InlineLink[]
1649:             */
1650:            public Link[] getInlineLinks() {
1651:                return toLink().inlineLinks();
1652:            }
1653:
1654:            public String toString() {
1655:                StringBuffer buffer = new StringBuffer("{entries = [");
1656:                if (entries != null) {
1657:                    for (int i = 0; i < size(); i++) {
1658:                        if (i > 0) {
1659:                            buffer.append(" ");
1660:                        }
1661:                        buffer.append(entries[i]);
1662:                    }
1663:                }
1664:                buffer.append("]");
1665:                buffer.append(" tableName = ").append(tableName);
1666:                buffer.append(" state = ").append(state);
1667:                buffer.append(" hasDirtyNonKeyFields = ").append(
1668:                        hasDirtyNonKeyFields);
1669:                buffer.append(" skipInsertForKeysOnly = ").append(
1670:                        skipInsertForKeysOnly);
1671:                buffer.append(" forceModify = ").append(forceModify);
1672:                buffer.append(" autoPadChars = ").append(autoPadChars);
1673:                buffer.append("}");
1674:
1675:                return buffer.toString();
1676:            }
1677:
1678:            public boolean equalsByValues(Record thatRecord) {
1679:                if (super .equals(thatRecord)) {
1680:                    return true;
1681:                }
1682:
1683:                if (this .size() == thatRecord.size()) {
1684:                    for (int i = 0; i < this .size(); i++) {
1685:                        boolean rc = true;
1686:                        if ((this .getObject(i) == null && thatRecord
1687:                                .getObject(i) != null)
1688:                                || (this .getObject(i) != null && thatRecord
1689:                                        .getObject(i) == null)) {
1690:                            rc = false;
1691:                        } else if (this .getObject(i) != null) {
1692:                            rc = this .getObject(i).equals(
1693:                                    thatRecord.getObject(i));
1694:                        }
1695:                        if (!rc) {
1696:                            return false;
1697:                        }
1698:                    }
1699:                    return true;
1700:                } else {
1701:                    return false;
1702:                }
1703:            }
1704:
1705:            /**
1706:             * Returns true if the record has to be modified even if none of the field is dirty
1707:             *
1708:             * @return true if the record has to be modified even if none of the field is dirty
1709:             */
1710:            public boolean isForceModify() {
1711:                return forceModify;
1712:            }
1713:
1714:            /**
1715:             * Indicates if the record has to be modified even if none of the field is dirty
1716:             *
1717:             * @param forceModify indicates if the record has to be modified even if none of the field is dirty
1718:             */
1719:            public void setForceModify(boolean forceModify) {
1720:                this .forceModify = forceModify;
1721:            }
1722:
1723:            public int[] toPrimaryKeyIndeces() {
1724:                return this .table.toPrimaryKeyIndeces();
1725:            }
1726:
1727:            /**
1728:             * Policy interface that determines how to translate this record to <tt>Parameters</tt>
1729:             *
1730:             * @see Parameters
1731:             */
1732:            public static interface ToParametersPolicy {
1733:                /**
1734:                 * Adds record value to <tt>Parameters</tt>
1735:                 *
1736:                 * @param columnIndex
1737:                 * @param type
1738:                 * @param value
1739:                 * @param parameters
1740:                 * @return <tt>Parameter</tt> added
1741:                 */
1742:                Parameter add(int columnIndex, ColumnType type, Object value,
1743:                        Parameters parameters);
1744:            }
1745:
1746:            /**
1747:             * Default ToParametersCtl implementation. Adds all the record values to <tt>Parameters</tt>
1748:             */
1749:            public static class DefaultToParametersPolicy implements 
1750:                    ToParametersPolicy {
1751:                /**
1752:                 * Adds all record values to <tt>Parameters</tt>
1753:                 *
1754:                 * @param columnIndex
1755:                 * @param type
1756:                 * @param value
1757:                 * @param parameters
1758:                 * @return <tt>Parameter</tt> added
1759:                 */
1760:                public Parameter add(int columnIndex, ColumnType type,
1761:                        Object value, Parameters parameters) {
1762:                    return parameters.add(type, value);
1763:                }
1764:            }
1765:
1766:            /**
1767:             * ToParametersCtl implementation that adds only not null record values to <tt>Parameters</tt>
1768:             */
1769:            public static class NotNullToParametersPolicy extends
1770:                    DefaultToParametersPolicy {
1771:                /**
1772:                 * Adds only not null record values to <tt>Parameters</tt>
1773:                 *
1774:                 * @param columnIndex
1775:                 * @param type
1776:                 * @param value
1777:                 * @param parameters
1778:                 * @return <tt>Parameter</tt> added
1779:                 */
1780:                public Parameter add(int columnIndex, ColumnType type,
1781:                        Object value, Parameters parameters) {
1782:                    if (value != null) {
1783:                        return super.add(columnIndex, type, value, parameters);
1784:                    } else {
1785:                        return null;
1786:                    }
1787:                }
1788:            }
1789:
1790:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.