001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.util;
020:
021: import java.util.ArrayList;
022: import java.util.Collection;
023:
024: /**
025: * Default {@link CollectionChangeTracker}.
026: *
027: * @author Abe White
028: * @nojavadoc
029: */
030: public class CollectionChangeTrackerImpl extends AbstractChangeTracker
031: implements CollectionChangeTracker {
032:
033: private final Collection _coll;
034: private final boolean _dups;
035: private final boolean _order;
036:
037: /**
038: * Constructor.
039: *
040: * @param coll the collection to delegate to
041: * @param dups true if the collection allows duplicates, false otherwise
042: * @param order true if the collection is ordered, false otherwise
043: */
044: public CollectionChangeTrackerImpl(Collection coll, boolean dups,
045: boolean order) {
046: _coll = coll;
047: _dups = dups;
048: _order = order;
049: }
050:
051: /**
052: * Whether the underlying collection allows duplicates.
053: */
054: public boolean allowsDuplicates() {
055: return _dups;
056: }
057:
058: /**
059: * Whether the underlying collection is ordered.
060: */
061: public boolean isOrdered() {
062: return _order;
063: }
064:
065: public void added(Object elem) {
066: super .added(elem);
067: }
068:
069: public void removed(Object elem) {
070: super .removed(elem);
071: }
072:
073: protected int initialSequence() {
074: if (_order)
075: return _coll.size();
076: return super .initialSequence();
077: }
078:
079: protected void add(Object elem) {
080: if (rem == null || !rem.remove(elem)) {
081: // after a point it's inefficient to keep tracking
082: if (getAutoOff()
083: && getAdded().size() + getRemoved().size() >= _coll
084: .size())
085: stopTracking();
086: else {
087: if (add == null) {
088: if (_dups || _order)
089: add = new ArrayList();
090: else
091: add = newSet();
092: }
093: add.add(elem);
094: }
095: } else if (_order)
096: stopTracking();
097: else {
098: if (change == null)
099: change = newSet();
100: change.add(elem);
101: }
102: }
103:
104: protected void remove(Object elem) {
105: // if the collection contains multiple copies of the elem, we can't
106: // use change tracking because some back-ends can't just delete a
107: // single copy of a elem
108: if (_dups && getAutoOff() && _coll.contains(elem))
109: stopTracking();
110: else if (add == null || !add.remove(elem)) {
111: // after a point it's inefficient to keep tracking
112: if (getAutoOff()
113: && getRemoved().size() + getAdded().size() >= _coll
114: .size())
115: stopTracking();
116: else {
117: if (rem == null)
118: rem = newSet();
119: rem.add(elem);
120: }
121: }
122: }
123:
124: protected void change(Object elem) {
125: throw new InternalException();
126: }
127: }
|