Source Code Cross Referenced for MapImpl.java in  » Database-ORM » beankeeper » hu » netmind » persistence » 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 » beankeeper » hu.netmind.persistence 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * Copyright (C) 2007 NetMind Consulting Bt.
003:         *
004:         * This library is free software; you can redistribute it and/or
005:         * modify it under the terms of the GNU Lesser General Public
006:         * License as published by the Free Software Foundation; either
007:         * version 3 of the License, or (at your option) any later version.
008:         *
009:         * This library is distributed in the hope that it will be useful,
010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012:         * Lesser General Public License for more details.
013:         *
014:         * You should have received a copy of the GNU Lesser General Public
015:         * License along with this library; if not, write to the Free Software
016:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
017:         */package hu.netmind.persistence;
018:
019:        import java.util.*;
020:        import hu.netmind.persistence.parser.*;
021:        import hu.netmind.persistence.event.*;
022:        import org.apache.log4j.Logger;
023:
024:        /**
025:         * Custom map implementation based on lazy lists. Map is <strong>not</strong>
026:         * thread-safe.
027:         * @author Brautigam Robert
028:         * @version Revision: $Revision$
029:         */
030:        public class MapImpl extends AbstractMap implements  Container {
031:            private static Logger logger = Logger.getLogger(MapImpl.class);
032:
033:            private StoreContext context;
034:            private List originalList;
035:            private TimeControl originalTimeControl;
036:            private ClassInfo parentInfo;
037:            private Object parent;
038:            private String parentAttributeName;
039:            private Long lastSerial;
040:            private ContainerItemClass itemClass;
041:
042:            private Map addedItems;
043:            private Map removedItems;
044:            private boolean cleared = false;
045:            private int modCount = 0;
046:
047:            /**
048:             * Initialize with a default list.
049:             */
050:            public void init(StoreContext context, ClassInfo classInfo,
051:                    Object obj, String attributeName, String itemClassName,
052:                    Long lastSerial, TimeControl timeControl) {
053:                this .context = context;
054:                this .originalList = null;
055:                this .originalTimeControl = new TimeControl(timeControl);
056:                this .parentInfo = classInfo;
057:                this .parent = obj;
058:                this .parentAttributeName = attributeName;
059:                this .lastSerial = lastSerial;
060:                this .itemClass = new ContainerItemClass(itemClassName);
061:                // Model
062:                reload();
063:            }
064:
065:            public String getItemClassName() {
066:                return itemClass.getItemClassName();
067:            }
068:
069:            public void reload() {
070:                // Initialize internal change structures
071:                modCount++;
072:                cleared = false;
073:                addedItems = new HashMap();
074:                removedItems = new HashMap();
075:                // Load list
076:                if (getItemClassName() == null) {
077:                    // No list
078:                    originalList = new Vector();
079:                } else {
080:                    originalList = context.getStore().find(
081:                            "find item(" + getItemClassName() + ")"
082:                                    + " where parent("
083:                                    + parentInfo.getSourceEntry().getFullName()
084:                                    + ")" + "." + parentAttributeName
085:                                    + " contains item and parent = ?",
086:                            new Object[] { parent }, originalTimeControl, null);
087:                    // Modify the select statements.
088:                    String subTableName = parentInfo
089:                            .getSubTableName(parentAttributeName);
090:                    LazyList lazy = (LazyList) originalList;
091:                    for (int i = 0; i < lazy.getStmts().size(); i++) {
092:                        QueryStatement stmt = (QueryStatement) lazy.getStmts()
093:                                .get(i);
094:                        // First search for the table term of the subtable
095:                        Expression expr = stmt.getQueryExpression();
096:                        TableTerm subTableTerm = expr
097:                                .getTableTerm(subTableName);
098:                        // Add this term to selected terms
099:                        stmt.getSelectTerms()
100:                                .add(
101:                                        new ReferenceTerm(subTableTerm,
102:                                                "container_key"));
103:                        // Add the correct order by
104:                        stmt.getOrderByList().add(
105:                                0,
106:                                new OrderBy(new ReferenceTerm(subTableTerm,
107:                                        "container_key"), OrderBy.ASCENDING));
108:                        // Correct static string
109:                        stmt.setStaticRepresentation(stmt
110:                                .getStaticRepresentation()
111:                                + " and mapkey");
112:                    }
113:                }
114:            }
115:
116:            /**
117:             * Returns whether the container changes internally since last save().
118:             */
119:            public boolean hasChanged() {
120:                return (addedItems.size() > 0) || (removedItems.size() > 0)
121:                        || (cleared);
122:            }
123:
124:            /**
125:             * Save the container to database.
126:             */
127:            public void save(Transaction transaction, Long currentSerial,
128:                    Set waitingObjects, List events) {
129:                // If the list was cleared before, then clear the current values
130:                if (cleared) {
131:                    HashMap keyAttributes = new HashMap();
132:                    keyAttributes.put("persistence_id", new Long(context
133:                            .getObjectTracker().getIdentifier(parent)));
134:                    keyAttributes.put("persistence_end", new Long(
135:                            DateSerialUtil.getMaxSerial()));
136:                    keyAttributes.put("persistence_txend", new Long(
137:                            DateSerialUtil.getMaxSerial()));
138:                    HashMap removeAttributes = new HashMap();
139:                    removeAttributes.put("persistence_txend", currentSerial);
140:                    removeAttributes.put("persistence_txendid", transaction
141:                            .getSerial());
142:                    context.getDatabase().save(transaction,
143:                            parentInfo.getSubTableName(parentAttributeName),
144:                            keyAttributes, removeAttributes);
145:                    transaction.addRemoveTable(parentInfo
146:                            .getSubTableName(parentAttributeName));
147:                    // Notify listeners
148:                    events.add(new ClearedContainerEvent(parent,
149:                            parentAttributeName));
150:                }
151:                // Remove removed items first
152:                Iterator removedItemsIterator = removedItems.entrySet()
153:                        .iterator();
154:                while (removedItemsIterator.hasNext()) {
155:                    Map.Entry entry = (Map.Entry) removedItemsIterator.next();
156:                    // Remove object from the list
157:                    HashMap keyAttributes = new HashMap();
158:                    keyAttributes.put("persistence_id", new Long(context
159:                            .getObjectTracker().getIdentifier(parent)));
160:                    keyAttributes.put("persistence_end", new Long(
161:                            DateSerialUtil.getMaxSerial()));
162:                    keyAttributes.put("persistence_txend", new Long(
163:                            DateSerialUtil.getMaxSerial()));
164:                    keyAttributes.put("container_key", entry.getKey()
165:                            .toString());
166:                    HashMap removeAttributes = new HashMap();
167:                    removeAttributes.put("persistence_txend", currentSerial);
168:                    removeAttributes.put("persistence_txendid", transaction
169:                            .getSerial());
170:                    context.getDatabase().save(transaction,
171:                            parentInfo.getSubTableName(parentAttributeName),
172:                            keyAttributes, removeAttributes);
173:                    transaction.addRemoveTable(parentInfo
174:                            .getSubTableName(parentAttributeName));
175:                    // Notify listeners
176:                    events.add(new RemovedItemEvent(parent,
177:                            parentAttributeName, new SimpleMapEntry(entry)));
178:                }
179:                // Add added items
180:                Iterator addedItemsIterator = addedItems.entrySet().iterator();
181:                while (addedItemsIterator.hasNext()) {
182:                    Map.Entry entry = (Map.Entry) addedItemsIterator.next();
183:                    ObjectWrapper wrapper = (ObjectWrapper) entry.getValue();
184:                    Object value = wrapper.getObject();
185:                    // Item does not exist then put it in the save list
186:                    if (!context.getObjectTracker().exists(value))
187:                        waitingObjects.add(context.getObjectTracker()
188:                                .getWrapper(value));
189:                    // Add item
190:                    HashMap itemAttributes = new HashMap();
191:                    itemAttributes.put("persistence_id", new Long(context
192:                            .getObjectTracker().getIdentifier(parent)));
193:                    itemAttributes.put("persistence_start", new Long(
194:                            DateSerialUtil.getMaxSerial()));
195:                    itemAttributes.put("persistence_end", new Long(
196:                            DateSerialUtil.getMaxSerial()));
197:                    itemAttributes.put("persistence_txendid", new Long(0));
198:                    itemAttributes.put("persistence_txstartid", transaction
199:                            .getSerial());
200:                    itemAttributes.put("persistence_txstart", currentSerial);
201:                    itemAttributes.put("persistence_txend", new Long(
202:                            DateSerialUtil.getMaxSerial()));
203:                    itemAttributes.put("container_key", entry.getKey()
204:                            .toString());
205:                    itemAttributes.put("value", new Long(context
206:                            .getObjectTracker().getIdentifier(value)));
207:                    context.getDatabase().insert(transaction,
208:                            parentInfo.getSubTableName(parentAttributeName),
209:                            itemAttributes);
210:                    transaction.addSaveTable(parentInfo
211:                            .getSubTableName(parentAttributeName));
212:                    // Notify listeners
213:                    events.add(new AddedItemEvent(parent, parentAttributeName,
214:                            new SimpleMapEntry(entry)));
215:                }
216:                // Reload the changed list. Note, that the list should not
217:                // be referenced until the Store.save() operation completes, because
218:                // the list will not contain nonexisting object currently.
219:                originalTimeControl = new TimeControl(currentSerial,
220:                        transaction.getSerial(), true);
221:                lastSerial = currentSerial;
222:            }
223:
224:            /**
225:             * Get the serial number of last modification.
226:             */
227:            public Long getLastSerial() {
228:                return lastSerial;
229:            }
230:
231:            /**
232:             * Retain all container elements inside the other container.
233:             */
234:            public boolean retainAll(Object c) {
235:                // Go through all elements, if it's not contained in c,
236:                // then remove (using the iterator!)
237:                boolean changed = false;
238:                Iterator iterator = entrySet().iterator();
239:                if (logger.isDebugEnabled())
240:                    logger.debug("map retain all: " + toString() + " from "
241:                            + c.toString());
242:                while (iterator.hasNext()) {
243:                    Map.Entry entry = (Map.Entry) iterator.next();
244:                    if (!((Map) c).containsKey(entry.getKey())) {
245:                        logger.debug("trying to remove key: " + entry.getKey());
246:                        iterator.remove();
247:                        changed = true;
248:                    }
249:                }
250:                return changed;
251:            }
252:
253:            /**
254:             * Add all items in the other container.
255:             */
256:            public boolean addAll(Object c) {
257:                putAll((Map) c);
258:                return true;
259:            }
260:
261:            /*
262:             * Map implementation.
263:             */
264:
265:            public void clear() {
266:                // Clear content and mark cleared flag
267:                cleared = true;
268:                addedItems = new HashMap();
269:                removedItems = new HashMap();
270:                originalList = new Vector();
271:                itemClass.clear();
272:                modCount++;
273:            }
274:
275:            /**
276:             * Return whether this map contains the specified key.
277:             */
278:            public boolean containsKey(Object key) {
279:                // If the item is removed, then it is not contained.
280:                if (removedItems.containsKey(key))
281:                    return false;
282:                // If it is added, then it is contained.
283:                if (addedItems.containsKey(key))
284:                    return true;
285:                // Else, check the list
286:                if (originalList.size() > LazyList.BATCH_SIZE) {
287:                    // This means, that the backing lazy list would page if we
288:                    // were to iterate. So instead, we run a specific query for
289:                    // the given id.
290:                    Transaction tx = context.getTransactionTracker()
291:                            .getTransaction(TransactionTracker.TX_REQUIRED);
292:                    tx.begin();
293:                    try {
294:                        String listTableName = parentInfo
295:                                .getSubTableName(parentAttributeName);
296:                        TableTerm listTableTerm = new TableTerm(listTableName,
297:                                null);
298:                        Expression listExpression = new Expression();
299:                        listExpression.add(new ReferenceTerm(listTableTerm,
300:                                "persistence_id"));
301:                        listExpression.add("=");
302:                        listExpression.add(new ConstantTerm(new Long(context
303:                                .getObjectTracker().getIdentifier(parent))));
304:                        listExpression.add("and");
305:                        listExpression.add(new ReferenceTerm(listTableTerm,
306:                                "container_key"));
307:                        listExpression.add("=");
308:                        listExpression.add(new ConstantTerm(key.toString()));
309:                        listExpression.add("and");
310:                        originalTimeControl
311:                                .apply(listExpression, listTableTerm);
312:                        // Execute. If there is a hit, then object exists
313:                        QueryStatement stmt = new QueryStatement(listTableTerm,
314:                                listExpression, null);
315:                        stmt.setTimeControl(originalTimeControl);
316:                        stmt.setStaticRepresentation("FIND "
317:                                + listTableTerm
318:                                + " WHERE persistence_id = "
319:                                + context.getObjectTracker().getIdentifier(
320:                                        parent) + " and mapkey = " + key);
321:                        SearchResult result = context.getStore().find(tx, stmt,
322:                                new Limits(0, 0, -1));
323:                        // Check
324:                        if (result.getResultSize() > 0)
325:                            return true; // Object exists
326:                    } finally {
327:                        tx.commit();
328:                    }
329:                } else {
330:                    // Set is small, so iterate
331:                    for (int i = 0; i < originalList.size(); i++) {
332:                        Map obj = (Map) originalList.get(i);
333:                        if (key.equals(obj.get("container_key")))
334:                            return true;
335:                    }
336:                }
337:                // Fall through
338:                return false;
339:            }
340:
341:            /**
342:             * Returns whether this map contains one or more of the 
343:             * specified value.
344:             */
345:            public boolean containsValue(Object value) {
346:                if (value == null)
347:                    return false;
348:                int type = context.getClassTracker().getType(value.getClass());
349:                ObjectWrapper wrapper = new ObjectWrapper(value);
350:                long id = context.getObjectTracker().getIdentifier(value);
351:                if (id == 0)
352:                    return false; // Can not contain value with no id
353:                // If the item is removed, then it is not contained.
354:                if (removedItems.containsValue(wrapper))
355:                    return false;
356:                // If it is added, then it is contained.
357:                if (addedItems.containsValue(wrapper))
358:                    return true;
359:                // Else, check the list
360:                if (originalList.size() > LazyList.BATCH_SIZE) {
361:                    // This means, that the backing lazy list would page if we
362:                    // were to iterate. So instead, we run a specific query for
363:                    // the given id.
364:                    Transaction tx = context.getTransactionTracker()
365:                            .getTransaction(TransactionTracker.TX_REQUIRED);
366:                    tx.begin();
367:                    try {
368:                        ClassInfo itemInfo = context.getClassTracker()
369:                                .getClassInfo(value.getClass(), value);
370:                        String itemTableName = itemInfo.getTableName(itemInfo
371:                                .getSourceEntry());
372:                        TableTerm itemTableTerm = new TableTerm(itemTableName,
373:                                null);
374:                        String listTableName = parentInfo
375:                                .getSubTableName(parentAttributeName);
376:                        TableTerm listTableTerm = new TableTerm(listTableName,
377:                                null);
378:                        Expression listExpression = new Expression();
379:                        listExpression.add(new ReferenceTerm(listTableTerm,
380:                                "persistence_id"));
381:                        listExpression.add("=");
382:                        listExpression.add(new ConstantTerm(new Long(context
383:                                .getObjectTracker().getIdentifier(parent))));
384:                        listExpression.add("and");
385:                        if (type != ClassTracker.TYPE_PRIMITIVE) {
386:                            listExpression.add(new ReferenceTerm(listTableTerm,
387:                                    "value"));
388:                            listExpression.add("=");
389:                            listExpression.add(new ConstantTerm(new Long(id)));
390:                        } else {
391:                            listExpression.add(new ReferenceTerm(itemTableTerm,
392:                                    "value"));
393:                            listExpression.add("=");
394:                            listExpression.add(new ConstantTerm(value));
395:                        }
396:                        listExpression.add("and");
397:                        listExpression.add(new ReferenceTerm(itemTableTerm,
398:                                "persistence_id"));
399:                        listExpression.add("=");
400:                        listExpression.add(new ReferenceTerm(listTableTerm,
401:                                "value"));
402:                        listExpression.add("and");
403:                        originalTimeControl
404:                                .apply(listExpression, itemTableTerm);
405:                        listExpression.add("and");
406:                        originalTimeControl
407:                                .apply(listExpression, listTableTerm);
408:                        // Execute. If there is a hit, then object exists
409:                        QueryStatement stmt = new QueryStatement(listTableTerm,
410:                                listExpression, null);
411:                        stmt.setTimeControl(originalTimeControl);
412:                        stmt.setStaticRepresentation("FIND "
413:                                + listTableTerm
414:                                + " WHERE persistence_id = "
415:                                + context.getObjectTracker().getIdentifier(
416:                                        parent) + " and value = " + id);
417:                        SearchResult result = context.getStore().find(tx, stmt,
418:                                new Limits(0, 0, -1));
419:                        // Check
420:                        if (result.getResultSize() > 0)
421:                            return true; // Object exists
422:                    } finally {
423:                        tx.commit();
424:                    }
425:                } else {
426:                    // Set is small, so iterate
427:                    for (int i = 0; i < originalList.size(); i++) {
428:                        Map obj = (Map) originalList.get(i);
429:                        if (((type == ClassTracker.TYPE_PRIMITIVE) && (value
430:                                .equals(obj.get("object"))))
431:                                || ((type != ClassTracker.TYPE_PRIMITIVE) && (id == context
432:                                        .getObjectTracker().getIdentifier(
433:                                                obj.get("object")))))
434:                            return true;
435:                    }
436:                }
437:                // Fall through
438:                return false;
439:            }
440:
441:            /**
442:             * Returns a set view of this map.
443:             */
444:            public Set entrySet() {
445:                return new MapImplEntrySet();
446:            }
447:
448:            /**
449:             * Determine whether map equals another map in content.
450:             */
451:            public boolean equals(Object obj) {
452:                // If it is not a map, then it surely does not equal.
453:                if (!(obj instanceof  Map))
454:                    return false;
455:                // If they are the same size, and all items equal, then the
456:                // maps equal.
457:                Map c = (Map) obj;
458:                return (size() == c.size())
459:                        && (entrySet().containsAll(c.entrySet()));
460:            }
461:
462:            /**
463:             * Get the value for a mapkey.
464:             */
465:            public Object get(Object key) {
466:                // If contained in the added list, return that
467:                ObjectWrapper wrapper = (ObjectWrapper) addedItems.get(key);
468:                if (wrapper != null)
469:                    return wrapper.getObject();
470:                // If contained in the remove list, then the result is null.
471:                if (removedItems.containsKey(key))
472:                    return null;
473:                // Not found until now, so check the list
474:                if (originalList.size() > LazyList.BATCH_SIZE) {
475:                    // The list is too large, so select the item separately
476:                    List result = context.getStore()
477:                            .find(
478:                                    "find item(object)"
479:                                            + " where parent("
480:                                            + parentInfo.getSourceEntry()
481:                                                    .getSourceClass().getName()
482:                                            + ")" + "." + parentAttributeName
483:                                            + "['" + key.toString()
484:                                            + "']=item and parent = ?",
485:                                    new Object[] { parent },
486:                                    originalTimeControl, null);
487:                    if (result.size() < 1)
488:                        return null;
489:                    return result.get(0);
490:                } else {
491:                    // List is small, so iterate
492:                    for (int i = 0; i < originalList.size(); i++) {
493:                        Map obj = (Map) originalList.get(i);
494:                        if (key.equals(obj.get("container_key")))
495:                            return obj.get("object"); // Found key
496:                    }
497:                }
498:                // Fall through
499:                return null; // Not found
500:            }
501:
502:            /**
503:             * Put an item into the map.
504:             */
505:            public Object put(Object key, Object value) {
506:                // Check value validity
507:                if (value == null)
508:                    throw new IllegalArgumentException(
509:                            "map implementation not accepting null values.");
510:                int type = context.getClassTracker().getType(value.getClass());
511:                if ((type != ClassTracker.TYPE_OBJECT)
512:                        && (type != ClassTracker.TYPE_PRIMITIVE))
513:                    throw new IllegalArgumentException(
514:                            "map only handles object or primitive types, but was: "
515:                                    + value + " (" + value.getClass().getName()
516:                                    + ")");
517:                // Determine the old value if there was one
518:                Object oldValue = get(key);
519:                // If the old value is the same, then skip
520:                if ((oldValue != null)
521:                        && (context.getObjectTracker().getIdentifier(value) == context
522:                                .getObjectTracker().getIdentifier(oldValue)))
523:                    return oldValue;
524:                // Remove the key if there is an oldvalue
525:                if (oldValue != null)
526:                    remove(key);
527:                // Then add the entry, now that is it not contained
528:                itemClass.updateItemClassName(originalList, value.getClass(),
529:                        addedItems.size() == 0);
530:                addedItems.put(key, new ObjectWrapper(value));
531:                // Modification took place
532:                modCount++;
533:                // Return with the old value of the key
534:                logger.debug("added key: " + key);
535:                return oldValue;
536:            }
537:
538:            /**
539:             * Remove a key from the map.
540:             */
541:            public Object remove(Object key) {
542:                // Get the old value
543:                Object oldValue = get(key);
544:                if (oldValue == null)
545:                    return null; // Not contained, so no op.
546:                // Determine whether key is in the added list. If it is,
547:                // then simply remove it, so it will not be added. Else, add to
548:                // the removed list.
549:                if (addedItems.containsKey(key))
550:                    addedItems.remove(key);
551:                else
552:                    removedItems.put(key, new ObjectWrapper(oldValue));
553:                // Modification took place
554:                modCount++;
555:                // Return with old value
556:                logger.debug("removed key: " + key);
557:                return oldValue;
558:            }
559:
560:            public int size() {
561:                return originalList.size() - removedItems.size()
562:                        + addedItems.size();
563:            }
564:
565:            public String toString() {
566:                return originalList.toString();
567:            }
568:
569:            public class MapImplEntrySet extends AbstractSet {
570:                public void clear() {
571:                    MapImpl.this .clear();
572:                }
573:
574:                public boolean contains(Object o) {
575:                    Map.Entry entry = (Map.Entry) o;
576:                    ObjectWrapper wrapper = new ObjectWrapper(entry.getValue());
577:                    long id = context.getObjectTracker().getIdentifier(
578:                            entry.getValue());
579:                    if (id == 0)
580:                        return false; // Can not contain value with no id
581:                    // If the item is removed, then it is not contained.
582:                    if (removedItems.containsKey(entry.getKey()))
583:                        return false;
584:                    // If it is added, then it is contained and is the same value.
585:                    if (addedItems.containsKey(entry.getKey()))
586:                        return addedItems.get(entry.getKey()).equals(wrapper);
587:                    // Else, check the list
588:                    if (originalList.size() > LazyList.BATCH_SIZE) {
589:                        // This means, that the backing lazy list would page if we
590:                        // were to iterate. So instead, we run a specific query for
591:                        // the given id.
592:                        Transaction tx = context.getTransactionTracker()
593:                                .getTransaction(TransactionTracker.TX_REQUIRED);
594:                        tx.begin();
595:                        try {
596:                            String listTableName = parentInfo
597:                                    .getSubTableName(parentAttributeName);
598:                            TableTerm listTableTerm = new TableTerm(
599:                                    listTableName, null);
600:                            Expression listExpression = new Expression();
601:                            listExpression.add(new ReferenceTerm(listTableTerm,
602:                                    "persistence_id"));
603:                            listExpression.add("=");
604:                            listExpression.add(new ConstantTerm(new Long(
605:                                    context.getObjectTracker().getIdentifier(
606:                                            parent))));
607:                            listExpression.add("and");
608:                            listExpression.add(new ReferenceTerm(listTableTerm,
609:                                    "value"));
610:                            listExpression.add("=");
611:                            listExpression.add(new ConstantTerm(new Long(id)));
612:                            listExpression.add("and");
613:                            listExpression.add(new ReferenceTerm(listTableTerm,
614:                                    "container_key"));
615:                            listExpression.add("=");
616:                            listExpression
617:                                    .add(new ConstantTerm(entry.getKey()));
618:                            listExpression.add("and");
619:                            originalTimeControl.apply(listExpression,
620:                                    listTableTerm);
621:                            // Execute. If there is a hit, then object exists
622:                            QueryStatement stmt = new QueryStatement(
623:                                    listTableTerm, listExpression, null);
624:                            stmt.setTimeControl(originalTimeControl);
625:                            stmt.setStaticRepresentation("FIND "
626:                                    + listTableTerm
627:                                    + " WHERE persistence_id = "
628:                                    + context.getObjectTracker().getIdentifier(
629:                                            parent) + " and value = " + id
630:                                    + ", mapkey = " + entry.getKey());
631:                            SearchResult result = context.getStore().find(tx,
632:                                    stmt, new Limits(0, 0, -1));
633:                            // Check
634:                            if (result.getResultSize() > 0)
635:                                return true; // Object exists
636:                        } finally {
637:                            tx.commit();
638:                        }
639:                    } else {
640:                        // Set is small, so iterate
641:                        for (int i = 0; i < originalList.size(); i++) {
642:                            Map obj = (Map) originalList.get(i);
643:                            if (obj.get("container_key").equals(entry.getKey()))
644:                                return (id == context.getObjectTracker()
645:                                        .getIdentifier(obj.get("object")));
646:                        }
647:                    }
648:                    // Fall through
649:                    return false;
650:                }
651:
652:                public Iterator iterator() {
653:                    return new MapImplEntrySetIterator();
654:                }
655:
656:                public boolean remove(Object o) {
657:                    return MapImpl.this .remove(((Map.Entry) o).getKey()) != null;
658:                }
659:
660:                public int size() {
661:                    return MapImpl.this .size();
662:                }
663:
664:                public String toString() {
665:                    return originalList.toString();
666:                }
667:            }
668:
669:            public class MapImplEntrySetIterator implements  Iterator {
670:                private int ownModCount;
671:                private int index;
672:                private boolean hasNext;
673:                private Map.Entry next;
674:                private Map.Entry current;
675:                private Iterator addedIterator;
676:
677:                public MapImplEntrySetIterator() {
678:                    index = 0;
679:                    ownModCount = modCount;
680:                    addedIterator = addedItems.entrySet().iterator();
681:                    // preread
682:                    read();
683:                }
684:
685:                private void read() {
686:                    // Ensure that no modification took place
687:                    if (ownModCount != modCount)
688:                        throw new java.util.ConcurrentModificationException(
689:                                "map was modified while iterating");
690:                    // Check whether there are elements left in the list
691:                    while (index < originalList.size()) {
692:                        Map obj = (Map) originalList.get(index);
693:                        index++; // Next
694:                        Object key = obj.get("container_key");
695:                        if (!removedItems.containsKey(key)) {
696:                            // This is a valid item, because it is not removed
697:                            hasNext = true;
698:                            next = new MapImplEntry(obj);
699:                            return;
700:                        }
701:                        if (addedItems.containsKey(key)) {
702:                            // This is a valid item, because it's key is here, but
703:                            // it was altered with another value. In this case we
704:                            // place the pair here, in it's original place.
705:                            hasNext = true;
706:                            next = new MapImplEntry(key,
707:                                    (ObjectWrapper) addedItems.get(key));
708:                            return;
709:                        }
710:                    }
711:                    // If there were no elements in the original list, check through
712:                    // the added items. Note, that if the added key was already iterated
713:                    // through in the original list, that key has to be skipped here.
714:                    if (addedIterator.hasNext()) {
715:                        Map.Entry entry = (Map.Entry) addedIterator.next();
716:                        if (!removedItems.containsKey(entry.getKey())) {
717:                            // The key is not removed, meaning it is really a new key,
718:                            // which was not contained in the original list.
719:                            hasNext = true;
720:                            next = new MapImplEntry(entry);
721:                            return;
722:                        }
723:                    }
724:                    // Fall through
725:                    hasNext = false;
726:                    next = null;
727:                }
728:
729:                public void remove() {
730:                    // Remove the current item
731:                    if (index <= originalList.size()) {
732:                        // The current item is in the original list, not in the
733:                        // added list, insert into the removed list.
734:                        removedItems.put(current.getKey(), new ObjectWrapper(
735:                                current.getValue()));
736:                    } else {
737:                        // The current item is in the added list, so remove from it.
738:                        addedIterator.remove();
739:                        // Modify the modcount, because the whole set changed
740:                    }
741:                    modCount++;
742:                    ownModCount = modCount; // The modcount changed, but we're safe
743:                }
744:
745:                public boolean hasNext() {
746:                    return hasNext;
747:                }
748:
749:                public Object next() {
750:                    current = next;
751:                    read(); // Pre-read next
752:                    return current;
753:                }
754:
755:                public class MapImplEntry implements  Map.Entry {
756:                    private Object key;
757:                    private Object value;
758:
759:                    public MapImplEntry(Map obj) {
760:                        key = obj.get("container_key");
761:                        value = obj.get("object");
762:                    }
763:
764:                    public MapImplEntry(Map.Entry entry) {
765:                        key = entry.getKey();
766:                        value = ((ObjectWrapper) entry.getValue()).getObject();
767:                    }
768:
769:                    public MapImplEntry(Object key, ObjectWrapper wrapper) {
770:                        this .key = key;
771:                        this .value = wrapper.getObject();
772:                    }
773:
774:                    public Object getKey() {
775:                        return key;
776:                    }
777:
778:                    public Object getValue() {
779:                        return value;
780:                    }
781:
782:                    public Object setValue(Object value) {
783:                        // This will modify the map, but we're ok, because
784:                        // it won't hurt our iteration.
785:                        Object oldValue = this .value;
786:                        put(key, value);
787:                        this .value = value;
788:                        ownModCount = modCount;
789:                        return oldValue;
790:                    }
791:                }
792:            }
793:
794:            public static class SimpleMapEntry implements  Map.Entry {
795:                private Object key;
796:                private Object value;
797:
798:                public SimpleMapEntry(Map.Entry entry) {
799:                    this .key = entry.getKey();
800:                    this .value = ((ObjectWrapper) entry.getValue()).getObject();
801:                }
802:
803:                public Object getKey() {
804:                    return key;
805:                }
806:
807:                public Object getValue() {
808:                    return value;
809:                }
810:
811:                public Object setValue(Object value) {
812:                    Object oldValue = this .value;
813:                    this .value = value;
814:                    return oldValue;
815:                }
816:            }
817:
818:            public class ObjectWrapper {
819:                private Object obj;
820:                private long id;
821:                private int type;
822:
823:                public ObjectWrapper(Object obj) {
824:                    this .obj = obj;
825:                    context.getObjectTracker().registerObject(obj, 0);
826:                    this .id = context.getObjectTracker().getIdentifier(obj);
827:                    this .type = context.getClassTracker().getType(
828:                            obj.getClass());
829:                }
830:
831:                public long getIdentifier() {
832:                    return id;
833:                }
834:
835:                public Object getObject() {
836:                    return obj;
837:                }
838:
839:                public int hashCode() {
840:                    if (type == ClassTracker.TYPE_PRIMITIVE)
841:                        return obj.hashCode();
842:                    else
843:                        return (int) (id >> 32);
844:                }
845:
846:                public boolean equals(Object rhs) {
847:                    if (!(rhs instanceof  ObjectWrapper))
848:                        return false;
849:                    if (type == ClassTracker.TYPE_PRIMITIVE)
850:                        return obj.equals(((ObjectWrapper) rhs).obj);
851:                    else
852:                        return id == ((ObjectWrapper) rhs).id;
853:                }
854:
855:            }
856:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.