001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.common;
012:
013: import com.versant.core.metadata.ClassMetaData;
014: import com.versant.core.metadata.ModelMetaData;
015: import com.versant.core.util.OIDObjectOutput;
016: import com.versant.core.util.OIDObjectInput;
017:
018: import java.io.*;
019: import java.util.Comparator;
020: import java.util.Arrays;
021: import java.util.Iterator;
022:
023: /**
024: * Collection of OIDs and States to be deleted. If this is constucted with
025: * keepStates == false then then states array is null and added states will
026: * be silently dropped. If keepStates == true then the array will be not
027: * null but the entry for a given OID may still be null if this information
028: * was not available. In this case the datastore will have to read the
029: * object prior to deleting it.
030: */
031: public final class DeletePacket {
032:
033: private static final int INITIAL_CAPACITY = 20;
034: private static final int GROW_FACTOR = 2;
035:
036: private ModelMetaData jmd;
037: private boolean keepStates;
038: public OID[] oids = new OID[INITIAL_CAPACITY];
039: public State[] states;
040:
041: private int size;
042:
043: /**
044: * This is for Externalizable.
045: */
046: public DeletePacket() {
047: }
048:
049: public DeletePacket(ModelMetaData jmd) {
050: this .jmd = jmd;
051: keepStates = jmd.sendStateOnDelete;
052: if (keepStates)
053: states = new State[INITIAL_CAPACITY];
054: }
055:
056: /**
057: * Add a state to the container to be deleted.
058: */
059: public void add(OID oid, State state) {
060: if (Debug.DEBUG) {
061: if (oid.isNew()) {
062: BindingSupportImpl.getInstance().internal(
063: "oid is new: " + oid);
064: }
065: // make sure untyped OIDs are not added
066: if (oid.getAvailableClassMetaData() == null) {
067: BindingSupportImpl.getInstance().internal(
068: "oid is untyped: " + oid);
069: }
070: }
071: resize();
072: if (keepStates)
073: states[size] = state;
074: oids[size++] = oid;
075: }
076:
077: /**
078: * The number of entries in the container.
079: */
080: public int size() {
081: return size;
082: }
083:
084: /**
085: * Is the container empty?
086: */
087: public boolean isEmpty() {
088: return size == 0;
089: }
090:
091: /**
092: * Check if the arrays needs to grow some more.
093: */
094: private void resize() {
095: int length = oids.length;
096: if (length == size) {
097: int growTo = (length + 1) * GROW_FACTOR;
098: OID[] tmpOIDs = new OID[growTo];
099: System.arraycopy(oids, 0, tmpOIDs, 0, length);
100: oids = tmpOIDs;
101: if (keepStates) {
102: State[] tmpStates = new State[growTo];
103: System.arraycopy(states, 0, tmpStates, 0, length);
104: states = tmpStates;
105: }
106: }
107: }
108:
109: /**
110: * Clear the container for reuse.
111: */
112: public void clear() {
113: oids = new OID[INITIAL_CAPACITY];
114: if (keepStates) {
115: states = new State[INITIAL_CAPACITY];
116: }
117: size = 0;
118: }
119:
120: public boolean isKeepStates() {
121: return keepStates;
122: }
123:
124: /**
125: * Sort the OIDs. This is a NOP if keepStates is true.
126: */
127: public void sortOIDs(Comparator comp) {
128: if (keepStates)
129: return;
130: states = null;
131: if (size <= 1)
132: return;
133: if (size == 2) {
134: if (comp.compare(oids[0], oids[1]) > 0) {
135: OID t = oids[0];
136: oids[0] = oids[1];
137: oids[1] = t;
138: }
139: return;
140: }
141: Arrays.sort(oids, 0, size, comp);
142: }
143:
144: public void dump() {
145: StringBuffer sb = new StringBuffer("DeleteOIDStateContainer: ");
146: for (int i = 0; i < oids.length; i++) {
147: OID oid = oids[i];
148: if (oid == null)
149: break;
150: sb.append("\nOID = " + oid.toSString());
151: if (keepStates) {
152: sb.append("\nState = " + states[i]);
153: }
154: sb.append("\nNext");
155: }
156: System.out.println(sb.toString());
157: }
158:
159: public void writeExternal(OIDObjectOutput out) throws IOException {
160: out.writeBoolean(keepStates);
161: out.writeInt(size);
162: if (keepStates) {
163: for (int i = 0; i < size; i++) {
164: oids[i].resolve(states[i]);
165: out.writeShort(states[i].getClassIndex());
166: out.writeWithoutCMD(oids[i]);
167: states[i].writeExternal(out);
168: }
169: } else {
170: for (int i = 0; i < size; i++) {
171: out.write(oids[i]);
172: }
173: }
174: }
175:
176: public void readExternal(OIDObjectInput in) throws IOException,
177: ClassNotFoundException {
178: jmd = in.getModelMetaData();
179: keepStates = in.readBoolean();
180: size = in.readInt();
181: oids = new OID[size];
182: if (keepStates) {
183: states = new State[size];
184: for (int i = 0; i < size; i++) {
185: ClassMetaData cmd = jmd.classes[in.readShort()];
186: oids[i] = in.readOID(cmd);
187: states[i] = cmd.createState();
188: states[i].readExternal(in);
189: }
190: } else {
191: for (int i = 0; i < size; i++) {
192: oids[i] = in.readOID();
193: }
194: }
195: }
196:
197: /**
198: * Iterate over the OIDs.
199: */
200: public Iterator iterator() {
201: return new Iter();
202: }
203:
204: public class Iter implements Iterator {
205:
206: private int pos;
207:
208: public boolean hasNext() {
209: return pos < size - 1;
210: }
211:
212: public Object next() {
213: return oids[pos++];
214: }
215:
216: public void remove() {
217: throw new UnsupportedOperationException();
218: }
219:
220: }
221:
222: }
|