Source Code Cross Referenced for Instance.java in  » Database-ORM » Velosurf » velosurf » context » 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 » Velosurf » velosurf.context 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2003 The Apache Software Foundation.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *     http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package velosurf.context;
018:
019:        import java.sql.SQLException;
020:        import java.util.*;
021:
022:        import velosurf.model.Action;
023:        import velosurf.model.Attribute;
024:        import velosurf.model.Entity;
025:        import velosurf.sql.Database;
026:        import velosurf.sql.PooledPreparedStatement;
027:        import velosurf.util.Logger;
028:        import velosurf.util.StringLists;
029:        import velosurf.util.UserContext;
030:
031:        /** An Instance provides field values by their name.
032:         *
033:         *  @author <a href=mailto:claude.brisson@gmail.com>Claude Brisson</a>
034:         */
035:        public class Instance extends TreeMap<String, Object> {
036:
037:            /** Build an empty instance for the given entity.
038:             *  The method initialize(Entity) should be called afterwards.
039:             * @param entity Entity this instance is a realisation of
040:             */
041:            public Instance() {
042:            }
043:
044:            /** Build an empty instance for the given entity.
045:             *
046:             * @param entity Entity this instance is a realisation of
047:             * @deprecated
048:             */
049:            public Instance(Entity entity) {
050:                initialize(entity);
051:            }
052:
053:            /**
054:             * Builds a generic instance using <code>values</code>.
055:             * @param values
056:             */
057:            public Instance(Map<String, Object> values) {
058:                for (Object key : values.keySet()) {
059:                    put(Database.adaptContextCase((String) key), values
060:                            .get(key));
061:                }
062:            }
063:
064:            /** Initialization. Meant to be overloaded if needed.
065:             * @param entity
066:             */
067:            public void initialize(Entity entity) {
068:                this .entity = entity;
069:                db = this .entity.getDB();
070:                localized = this .entity.hasLocalizedColumns();
071:            }
072:
073:            /** Get this Instance's Entity.
074:             *
075:             * @return this Instance's Entity.
076:             */
077:            public EntityReference getEntity() {
078:                return new EntityReference(entity);
079:            }
080:
081:            /** <p>Returns an ArrayList of two-entries maps ('name' & 'value'), meant to be use in a #foreach loop to build form fields.</p>
082:             * <p>Example:</p>
083:             * <code>
084:             * #foreach ($field in $product.primaryKey)<br>
085:             * &nbsp;&nbsp;&lt;input type=hidden name='$field.name' value='$field.value'&gt;<br>
086:             * #end</code>
087:             * <p>Please note that this method won't be of any help if you are using column aliases.</p>
088:             *
089:             * @return an ArrayList of two-entries maps ('name' & 'value')
090:             */
091:            public List getPrimaryKey() {
092:                List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
093:                if (entity != null) {
094:                    for (Iterator i = entity.getPKCols().iterator(); i
095:                            .hasNext();) {
096:                        String key = (String) i.next();
097:                        Map<String, Object> map = new HashMap<String, Object>();
098:                        map.put("name", key);
099:                        map.put("value", getInternal(key));
100:                        result.add(map);
101:                    }
102:                }
103:                return result;
104:            }
105:
106:            /** <p>Generic getter, used to access this instance properties by their name.</p>
107:             * <p>Asked property is first searched in the Map, then among Attributes defined for the entity.</p>
108:             *
109:             * @param key key of the property to be returned
110:             * @return a String, an Instance, an AttributeReference or null if an error
111:             *      occurs
112:             */
113:            public Object get(Object k) {
114:                String key = resolveName((String) k);
115:                Object result = null;
116:                try {
117:                    result = super .get(key);
118:                    if (result == null) {
119:                        if (entity != null) {
120:                            Attribute attribute = entity.getAttribute(key);
121:                            if (attribute != null) {
122:                                switch (attribute.getType()) {
123:                                case Attribute.ROWSET:
124:                                    result = new AttributeReference(this ,
125:                                            attribute);
126:                                    // then cache it in the map, so that order and refinement will work later in the same context
127:                                    super .put(key, result);
128:                                    break;
129:                                case Attribute.ROW:
130:                                    result = attribute.fetch(this );
131:                                    if (attribute.getCaching()) {
132:                                        super .put(key, result);
133:                                    }
134:                                    break;
135:                                case Attribute.SCALAR:
136:                                    result = attribute.evaluate(this );
137:                                    if (attribute.getCaching()) {
138:                                        super .put(key, result);
139:                                    }
140:                                    break;
141:                                default:
142:                                    Logger.error("Unknown attribute type for "
143:                                            + entity.getName() + "." + key
144:                                            + "!");
145:                                }
146:                            } else {
147:                                Action action = entity.getAction(key);
148:                                if (action != null)
149:                                    result = Integer.valueOf(action
150:                                            .perform(this ));
151:                            }
152:                        }
153:                    } else if (localized && entity.isLocalized(key)) {
154:                        result = db.getUserContext()
155:                                .localize(result.toString());
156:                    }
157:                } catch (SQLException sqle) {
158:                    handleSQLException(sqle);
159:                }
160:                return result;
161:            }
162:
163:            /** Generic setter.
164:             *
165:             * @param key key of the property to be set
166:             * @param value corresponding value
167:             * @return previous value, or null
168:             */
169:            public synchronized Object put(String key, Object value) {
170:                key = resolveName(key);
171:                if (entity != null && entity.isColumn(key)) {
172:                    value = entity.filterIncomingValue(key, value);
173:                }
174:                return super .put(key, value);
175:            }
176:
177:            /** Global setter that will only set values the correspond to actual
178:             * columns (otherwise, use putAll(Map values)).
179:             *
180:             * @param values corresponding values
181:             */
182:
183:            public synchronized void setColumns(Map<String, Object> values) {
184:                if (entity == null) {
185:                    Logger
186:                            .warn("instance.putColumn(map) cannot be used when entity is null");
187:                    return;
188:                }
189:                for (Map.Entry<String, Object> entry : values.entrySet()) {
190:                    if (entity.isColumn(entity.resolveName(entry.getKey()))) {
191:                        put(entry.getKey(), entry.getValue());
192:                    }
193:                }
194:            }
195:
196:            /** Internal getter. First tries on the external object then on the Map interface.
197:             *
198:             * @param key key of the property to be returned
199:             * @return a String, an Instance, an AttributeReference or null if not found or if an error
200:             *      occurs
201:             */
202:            public Object getInternal(Object key) {
203:                Object ret = getExternal(key);
204:                if (ret == null)
205:                    ret = super .get(key);
206:                return ret;
207:            }
208:
209:            /** External getter. Meant to be overloaded in ExternalObjectWrapper.
210:             *
211:             * @param key key of the property to be returned
212:             * @return a String, an Instance, an AttributeReference or null if not found or if an error
213:             *      occurs
214:             */
215:            public Object getExternal(Object key) {
216:                return null;
217:            }
218:
219:            /**
220:             * Test equality of two instances.
221:             * @param o other instance
222:             * @return equality status
223:             */
224:            public boolean equals(Object o) {
225:                return super .equals(o);
226:            }
227:
228:            /** <p>Update the row associated with this Instance from passed values.</p>
229:             * <p>Velosurf will ensure all key columns are specified, to avoid an accidental massive update.</p>
230:             *
231:             * @return <code>true</code> if successfull, <code>false</code> if an error
232:             *     occurs (in which case $db.error can be checked).
233:             */
234:            public synchronized boolean update() {
235:                try {
236:                    if (entity == null) {
237:                        throw new SQLException(
238:                                "Cannot update an instance whose Entity is null.");
239:                    }
240:                    if (entity.isReadOnly()) {
241:                        throw new SQLException("Entity " + entity.getName()
242:                                + " is read-only.");
243:                    }
244:
245:                    List<String> updateClause = new ArrayList<String>();
246:                    List<String> whereClause = new ArrayList<String>();
247:                    List<Object> params = new ArrayList<Object>();
248:                    List<String> cols = new ArrayList<String>(entity
249:                            .getColumns());
250:                    cols.removeAll(entity.getPKCols());
251:                    for (String col : cols) {
252:                        Object value = getInternal(col);
253:                        if (value != null) {
254:                            updateClause.add(col + "=?");
255:                            if (entity.isObfuscated(col))
256:                                value = entity.deobfuscate(value);
257:                            params.add(value);
258:                        }
259:                    }
260:                    if (updateClause.size() == 0) {
261:                        Logger
262:                                .warn("update of instance '"
263:                                        + entity.getName()
264:                                        + "' all non-key columns are null - no update will be performed");
265:                        // return true anyway ?
266:                        return true;
267:                    }
268:                    for (String col : entity.getPKCols()) {
269:                        Object value = getInternal(col);
270:                        if (value == null)
271:                            throw new SQLException(
272:                                    "field '"
273:                                            + col
274:                                            + "' belongs to primary key and cannot be null!");
275:                        if (entity.isObfuscated(col))
276:                            value = entity.deobfuscate(value);
277:                        //                if (entity.isLocalized(col)) value = entity.unlocalize(value); ???
278:                        whereClause.add(col + "=?");
279:                        params.add(value);
280:                    }
281:                    String query = "update " + entity.getTableName() + " set "
282:                            + StringLists.join(updateClause, ",") + " where "
283:                            + StringLists.join(whereClause, " and ");
284:                    PooledPreparedStatement statement = db.prepare(query);
285:                    int nb = statement.update(params);
286:                    if (nb == 0) {
287:                        Logger
288:                                .warn("query \"" + query
289:                                        + "\" affected 0 row...");
290:                    } else if (nb > 1) { // ?!?! Referential integrities on key columns should avoid this...
291:                        throw new SQLException("query \"" + query
292:                                + "\" affected more than 1 rows!");
293:                    } else {
294:                        /* invalidate cache */
295:                        if (entity != null) {
296:                            entity.invalidateInstance(this );
297:                        }
298:                    }
299:                    return true;
300:                } catch (SQLException sqle) {
301:                    handleSQLException(sqle);
302:                    return false;
303:                }
304:            }
305:
306:            /** <p>Update the row associated with this Instance from actual values.</p>
307:             * <p>Velosurf will ensure all key columns are specified, to avoid an accidental massive update.</p>
308:             *
309:             * @param values values to be used for the update
310:             * @return <code>true</code> if successfull, <code>false</code> if an error
311:             *      occurs (in which case $db.error can be checked).
312:             */
313:            public synchronized boolean update(Map<String, Object> values) {
314:                if (values != null && values != this ) {
315:                    setColumns(values);
316:                }
317:                return update();
318:            }
319:
320:            /** <p>Delete the row associated with this Instance.</p>
321:             * <p>Velosurf will ensure all key columns are specified, to avoid an accidental massive update.</p>
322:             *
323:             * @return <code>true</code> if successfull, <code>false</code> if an error
324:             *     occurs (in which case $db.error can be checked).
325:             */
326:            public synchronized boolean delete() {
327:                try {
328:                    if (entity == null)
329:                        throw new SQLException(
330:                                "Instance.delete: Error: Entity is null!");
331:                    List<String> whereClause = new ArrayList<String>();
332:                    List<Object> params = new ArrayList<Object>();
333:                    for (String col : entity.getPKCols()) {
334:                        Object value = getInternal(col);
335:                        if (value == null)
336:                            throw new SQLException(
337:                                    "Instance.delete: Error: field '"
338:                                            + col
339:                                            + "' belongs to primary key and cannot be null!");
340:                        if (entity.isObfuscated(col))
341:                            value = entity.deobfuscate(value);
342:                        whereClause.add(col + "=?");
343:                        params.add(value);
344:                    }
345:                    String query = "delete from " + entity.getTableName()
346:                            + " where "
347:                            + StringLists.join(whereClause, " and ");
348:                    PooledPreparedStatement statement = db.prepare(query);
349:                    int nb = statement.update(params);
350:                    if (nb == 0) {
351:                        Logger
352:                                .warn("query \"" + query
353:                                        + "\" affected 0 row...");
354:                    } else if (nb > 1) // ?!?! Referential integrities on key columns should avoid this...
355:                        throw new SQLException("query \"" + query
356:                                + "\" affected more than 1 rows!");
357:                    else {
358:                        /* invalidate cache */
359:                        if (entity != null) {
360:                            entity.invalidateInstance(this );
361:                        }
362:                    }
363:                    return true;
364:                } catch (SQLException sqle) {
365:                    handleSQLException(sqle);
366:                    return false;
367:                }
368:            }
369:
370:            /** Insert a new row corresponding to this Instance.
371:             *
372:             * @return <code>true</code> if successfull, <code>false</code> if an error
373:             *     occurs (in which case $db.error can be checked).
374:             */
375:            public synchronized boolean insert() {
376:                try {
377:                    if (entity == null) {
378:                        throw new SQLException(
379:                                "Instance.insert: Error: Entity is null!");
380:                    }
381:
382:                    if (!entity.validate(this )) {
383:                        return false;
384:                    }
385:                    List<String> colsClause = new ArrayList<String>();
386:                    List<String> valsClause = new ArrayList<String>();
387:                    List<Object> params = new ArrayList<Object>();
388:                    List<String> cols = entity.getColumns();
389:                    for (String col : cols) {
390:                        Object value = getInternal(col);
391:                        if (value != null) {
392:                            colsClause.add(col);
393:                            valsClause.add("?");
394:                            if (entity.isObfuscated(col))
395:                                value = entity.deobfuscate(value);
396:                            params.add(value);
397:                        }
398:                    }
399:                    String query = "insert into " + entity.getTableName()
400:                            + " (" + StringLists.join(colsClause, ",")
401:                            + ") values (" + StringLists.join(valsClause, ",")
402:                            + ")";
403:                    PooledPreparedStatement statement = db.prepare(query);
404:                    statement.update(params);
405:                    List<String> keys = entity.getPKCols();
406:                    if (keys.size() == 1) {
407:                        /* What if the ID is not autoincremented? TODO check it. => reverse engineering of autoincrement, and set the value in the instance itself */
408:                        String keycol = keys.get(0);
409:                        long newid = statement.getLastInsertID();
410:                        db.getUserContext().setLastInsertedID(entity, newid);
411:                        if (getInternal(keycol) == null) {
412:                            put(keycol, entity.isObfuscated(keycol) ? entity
413:                                    .obfuscate(newid) : newid);
414:                        }
415:                    }
416:                    return true;
417:                } catch (SQLException sqle) {
418:                    handleSQLException(sqle);
419:                    return false;
420:                }
421:            }
422:
423:            /** Validate this instance against declared contraints.
424:             * @return a boolean stating whether this instance data are valid in regard to declared constraints
425:             */
426:            public boolean validate() {
427:                try {
428:                    return entity.validate(this );
429:                } catch (SQLException sqle) {
430:                    handleSQLException(sqle);
431:                    return false;
432:                }
433:            }
434:
435:            /** Handle an sql exception.
436:             *
437:             */
438:            private void handleSQLException(SQLException sqle) {
439:                Logger.log(sqle);
440:                db.setError(sqle.getMessage());
441:            }
442:
443:            protected String resolveName(String name) {
444:                if (entity != null) {
445:                    return entity.resolveName(name);
446:                } else if (db != null) {
447:                    return db.adaptCase(name);
448:                } else {
449:                    return name;
450:                }
451:            }
452:
453:            public boolean containsKey(Object key) {
454:                return super .containsKey(resolveName((String) key));
455:            }
456:
457:            public Object remove(Object key) {
458:                return super .remove(resolveName((String) key));
459:            }
460:
461:            /** This Instance's Entity.
462:             */
463:            protected Entity entity = null;
464:
465:            /** Is there a column to localize?
466:             */
467:            private boolean localized = false;
468:
469:            /** The main database connection.
470:             */
471:            protected Database db = null;
472:
473:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.