Source Code Cross Referenced for SFieldMeta.java in  » Database-ORM » SimpleORM » simpleorm » core » 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 » SimpleORM » simpleorm.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package simpleorm.core;
002:
003:        import simpleorm.properties.*;
004:
005:        import java.util.HashMap;
006:        import java.sql.ResultSet;
007:        import java.io.*;
008:        import java.sql.*;
009:
010:        /*
011:         * Copyright (c) 2002 Southern Cross Software Queensland (SCSQ).  All rights
012:         * reserved.  See COPYRIGHT.txt included in this distribution.
013:         */
014:
015:        /** Each instance defines the meta data for a field in an {@link
016:         SRecordMeta}.  Subclasses are used for specific data types, with
017:         {@link SFieldObject} being the most generic.  Like JDBC, type
018:         conversions are made automatically.<p>
019:        
020:         Internally, the types are stored accurately.  Ie. the
021:         <code>SRecordInstance.fieldValues</code> objects are the exact
022:         types as declared (String, Integer, Employee etc.)  However,
023:         generous automatic conversions are performed both when accessing
024:         these from the application and when getting and setting columns in
025:         the database.<p>
026:        
027:         See SSimpleORMProperties for a descripiton of how properties are
028:         used with fields.<p>*/
029:
030:        public abstract class SFieldMeta extends SPropertyMap implements 
031:                Serializable {
032:            /** The record that this field belongs to. */
033:            SRecordMeta sRecordMeta;
034:
035:            /** The indext into SRecordMeta.fields. */
036:            int fieldIndex;
037:
038:            /** Is part of a primary key, may also be a foreign key.  ### Propertyize.*/
039:            transient boolean isPrimaryKey = false;
040:
041:            /** Can only be read, not set. Mainly SCOLUMN_NAME */
042:            transient boolean isReadOnly = false;
043:
044:            /** Not null means this field is a foreign key member of the
045:             SFieldReference.  Overlapping foreign keys are not supported so
046:             this is a scalar.  (The semantics of setField are vague
047:             Overlapping keys.)  Strict inverse of
048:             <code>SFieldReference.foreignKeyFields</code>.*/
049:            transient SFieldReference sFieldReference = null;
050:
051:            /** If sFieldRefrence != null, then this refers to the corresponding
052:             key field in the referenced table. */
053:            transient SFieldMeta referencedKeyField = null;
054:
055:            /** The last key value generated for this
056:             <code>SGENERATED_KEY</code> field in this JVM.  Used by the
057:             default driver as a hack to minimize collisions with the SELECT
058:             MAX method.  Synchronize all access.*/
059:            transient private long lastGeneratedKeyValue = 0;
060:
061:            /** Creates a new field for <code>sRecord</code> corresponding to
062:             <code>columnName</code>.  <code>pvalues</code> are an arbitrary
063:             list of properties that can be associated with this
064:             field. <code>fieldName</code> is only used for the fieldMap and
065:             defaults to the <code>columnName</code> or prefix for
066:             references. */
067:            SFieldMeta(SRecordMeta sRecord, String columnName,
068:                    String fieldName, SPropertyValue[] pvalues) {
069:                //SLog.slog.debug("  SFieldMeta " + sRecord + columnName);
070:                this .sRecordMeta = sRecord;
071:
072:                setPropertyValues(pvalues);
073:                String colName = (String) putDefaultProperty(SCon.SCOLUMN_NAME,
074:                        columnName);
075:                String fldName = (String) putDefaultProperty(SCon.SFIELD_NAME,
076:                        fieldName);
077:
078:                /// Check no duplicate column names, can happen for references.
079:                for (int mx = 0; mx < sRecord.sFieldMetas.size(); mx++) {
080:                    SFieldMeta fm = (SFieldMeta) sRecord.sFieldMetas.get(mx);
081:                    String xcol = fm.getString(SCon.SCOLUMN_NAME);
082:                    if (xcol != null && xcol.equals(colName))
083:                        throw new SException.Error("Duplicate Column Name "
084:                                + colName);
085:                }
086:
087:                /// Set up new record.
088:                sRecordMeta.sFieldMetas.add(this );
089:                fieldIndex = sRecordMeta.sFieldMetas.size() - 1;
090:                sRecordMeta.sFieldNames.add(fldName);
091:                sRecordMeta.fieldMap.put(fldName, this );
092:                if (getBoolean(SCon.SPRIMARY_KEY)) {
093:                    isPrimaryKey = true;
094:                    sRecordMeta.keySFieldMetas.add(this );
095:                }
096:                if (getProperty(SCon.SCOLUMN_QUERY) != null)
097:                    isReadOnly = true;
098:                if (sRecordMeta.keySFieldMetas.size() == 0)
099:                    throw new SException.Error("No Primary Key declared for "
100:                            + sRecordMeta + " (Must be first fields)");
101:                // Important for Employee.Manager refs Employee
102:            }
103:
104:            /** Common case for all fields but References. */
105:            SFieldMeta(SRecordMeta sRecord, String columnName,
106:                    SPropertyValue[] pvalues) {
107:                this (sRecord, columnName, columnName, pvalues);
108:            }
109:
110:            /** Clone this key field to be a foreign key to <code>rmeta</code>
111:             of the same type.*/
112:            abstract SFieldMeta makeForeignKey(SRecordMeta rmeta,
113:                    String prefix, SPropertyValue[] pvals);
114:
115:            /** Return default SDATA_TYPE property. */
116:            abstract String defaultDataType();
117:
118:            /** Dispatched from SRecordInstance.getObject(), this is specialized
119:             for references etc. */
120:            Object getFieldValue(SRecordInstance instance, long sqy_flags) {
121:                if (!instance.isValid())
122:                    throw new SException.Error(
123:                            "Cannot access destroyed record " + instance);
124:                if (instance.deleted)
125:                    throw new SException.Error(
126:                            "Attempt to access Deleted record " + instance);
127:                if (sRecordMeta != instance.getMeta()) // ie. identical
128:                    throw new SException.Error("Field " + this  + " is not in "
129:                            + instance.getMeta());
130:                // Maybe trigger lazy read of object later.
131:
132:                if ((instance.bitSets[fieldIndex] & SCon.INS_VALID) == 0
133:                        && !(this  instanceof  SFieldReference))
134:                    throw new SException.Error("Cannot access unqueried field "
135:                            + this  + " in " + instance);
136:                Object res = getRawFieldValue(instance, sqy_flags);
137:                if (SLog.slog.enableFields())
138:                    SLog.slog.fields("Got " + instance.toStringDefault() + "."
139:                            + this  + " == " + res);
140:                return res;
141:            }
142:
143:            /** Specialized in SFieldReference */
144:            Object getRawFieldValue(SRecordInstance instance, long sqy_flags) {
145:                return instance.fieldValues[fieldIndex];
146:            }
147:
148:            /** Does generic checks before calling field type specific handler.
149:             See SRecordInstance.setObject for a description fo the full
150:             flow.<p>
151:             
152:             The internal flow is:-
153:             <xmp>
154:             SRecordInstance.setString(field, value)
155:             SRecordInstance.setObject(field, value)
156:             SFieldMeta.setFieldValue(this)
157:             - Generic validation incl. Not primary key.
158:             - Check if changed.
159:             SField*.convertToField(value)
160:             SFieldMeta|Reference.setRawFieldValue(instance, value)
161:             </xmp> 
162:             
163:             * Note that setRawFieldValue is also called directly for keys etc. 
164:             * 
165:             **/
166:
167:            void setFieldValue(SRecordInstance instance, Object rawValue) {
168:
169:                // ### INS_VALID & UPDATABLE tests are missing?
170:
171:                /// Check instance valid for setting this field.
172:                if (instance.fieldValues == null)
173:                    throw new SException.Error(
174:                            "Cannot access destroyed record " + instance);
175:                if (instance.deleted)
176:                    throw new SException.Error("Cannot access deleted record "
177:                            + instance);
178:                if (sRecordMeta != instance.getMeta()) // ie. identical
179:                    throw new SException.Error("Field " + this  + " is not in "
180:                            + instance.getMeta());
181:                if (isPrimaryKey && instance.isAttached()) // See SRecordMeta createDetached.
182:                    throw new SException.Error(
183:                            "Cannot change primary key field " + this  + " in "
184:                                    + instance);
185:                if (sFieldReference != null)
186:                    throw new SException.Error(
187:                            "Cannot directly update foreign key  " + this 
188:                                    + " in " + instance + ". Update "
189:                                    + sFieldReference + " instead.");
190:                // If users could directly update the foreign keys they could
191:                // make the relationship between foreign keys and the references
192:                // inconsistent.  When findOrCreate becomes truely lazy, the
193:                // overheads in creating the referenced object will be
194:                // negligible.  However, this may change if overlapping foreign
195:                // keys are implemented.
196:
197:                checkUpdatable(instance);
198:
199:                /// Convert rawValue if necessary.
200:                Object convValue = null;
201:                try {
202:                    convValue = convertToField(rawValue);
203:                } catch (Exception ex) {
204:                    throw new SException.Data("Converting " + rawValue
205:                            + " for " + instance + "." + this , ex);
206:                }
207:
208:                /// Now do any user validations.
209:                instance.validateField(this , convValue);
210:
211:                /// Set the field value if different.
212:                Object fvalue = instance.fieldValues[fieldIndex];
213:                if ((instance.bitSets[fieldIndex] & SCon.INS_VALID) == 0
214:                        || (convValue == null && fvalue != null)
215:                        || (convValue != null && (fvalue == null || !convValue
216:                                .equals(fvalue)))) {
217:                    rawSetFieldValue(instance, convValue);
218:                    instance.setDirty();
219:                }
220:            }
221:
222:            /** Specialized for SReferences.*/
223:            void checkUpdatable(SRecordInstance instance) {
224:                if ((instance.bitSets[fieldIndex] & SCon.INS_READ_ONLY) != 0)
225:                    throw new SException.Error("Not queried for updating "
226:                            + this  + " in " + instance);
227:            }
228:
229:            /** Specialized for References.  Called from 1. setFieldValue(),
230:             which sets the record dirty, 2. setPrimaryKey() for which we do
231:             not want the record marked dirty,
232:             3. SFieldReference.rawSetFieldValue() (recursively) in which
233:             case setFieldValue() should have already marked the record
234:             dirty. */
235:            void rawSetFieldValue(SRecordInstance instance, Object value) {
236:                if (SLog.slog.enableFields())
237:                    SLog.slog.fields("Set " + instance + "." + this  + " = "
238:                            + value);
239:                if (isReadOnly)
240:                    throw new SException.Error(
241:                            "Attempt to set read only field " + instance + "."
242:                                    + this  + " to " + value);
243:                instance.fieldValues[fieldIndex] = value;
244:                instance.bitSets[fieldIndex] |= (byte) (SCon.INS_DIRTY | SCon.INS_VALID);
245:            }
246:
247:            /** Issues a JDBC get*() on the result set for the field and converts the database type
248:             to the appropriate internal type, eg, Double for a double field. The first
249:             column has sqlIndex==1. */
250:            abstract Object queryFieldValue(ResultSet rs, int sqlIndex)
251:                    throws Exception;
252:
253:            /** Converts the parameter from the users type to the correct internal Object type for this
254:             field.  Returns the object if no conversion necessary.  Used by
255:             <code>SRecordInstance.setObject</code> etc.*/
256:            abstract Object convertToField(Object raw) throws Exception;
257:
258:            /**
259:             * Places a value in a prepared statement in the database representation
260:             * used during SRecordInstance.flush.  
261:             * Can convert between internal values and database values, eg. TRUE to "Y".
262:             * 
263:             * (This does NOT need to handle NULL values (those are handled seperately by SRecordInstance))
264:             */
265:            void writeFieldValue(PreparedStatement ps, int sqlIndex,
266:                    Object value) {
267:                try {
268:                    ps.setObject(sqlIndex, writeFieldValue(value));
269:                } catch (Exception ex) {
270:                    throw new SException.JDBC(ex);
271:                }
272:            }
273:
274:            /**
275:             * Converts a single value from internal representation to database representation.
276:             * Used primarily by the writeFieldValue above, but also used for converting optimistic lock
277:             * values in SRecordInstance.flush.<p>
278:             * 
279:             * Overidden by SFieldBoolean.  (not by SFieldString). 
280:             *
281:             * NOTE: This does NOT need to handle NULL values (those are handled seperately by SRecordInstance)
282:             */
283:            Object writeFieldValue(Object value) {
284:                return value;
285:            }
286:
287:            /** Lists the record and column name only.  Useful in traces. */
288:            public String toString() {
289:                return "[F " + SUte.cleanClass(sRecordMeta.userClass) + "."
290:                        + getString(SCon.SCOLUMN_NAME) + "]";
291:            }
292:
293:            /** Lists all the details of the field. */
294:            public String toLongerString() {
295:                return "["
296:                        + this 
297:                        + (isPrimaryKey ? " PKey" : "")
298:                        + (sFieldReference != null ? (" sFldRef "
299:                                + sFieldReference + " RefedKey " + referencedKeyField)
300:                                : "") + "]";
301:            }
302:
303:            /**
304:             * Accessor to get the SRecordMeta of this field
305:             */
306:            public SRecordMeta getSRecordMeta() {
307:                return sRecordMeta;
308:            }
309:
310:            /*
311:             public Object validate(Object newValue) throws SValidationException{}
312:             // Framework.
313:             */
314:
315:            /**
316:             This is used to fudge version numbers in databases that do not
317:             properly suport them.  It is rough and fails if there are
318:             multiple JVMs, or the user switches schemas in Oracle etc.  (I
319:             had used it as a backup of Oracle etc.  but that was not a good
320:             idea.)
321:             */
322:            synchronized long nextGeneratedValue(long minimum) {
323:                if (lastGeneratedKeyValue < minimum)
324:                    lastGeneratedKeyValue = minimum;
325:                else
326:                    ++lastGeneratedKeyValue;
327:                return lastGeneratedKeyValue;
328:            }
329:
330:            /**
331:             * Same purpose as corresponding method on SRecordMeta.
332:             * <p>This method is implemented to return the pre-existing SFieldMeta object
333:             */
334:            protected Object readResolve() throws ObjectStreamException {
335:                Object substituted = sRecordMeta.sFieldMetas.get(fieldIndex);
336:                return substituted;
337:            }
338:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.