/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.openide.text;
import java.io.*;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.*;
import javax.swing.text.Position;
import javax.swing.text.StyledDocument;
import javax.swing.text.BadLocationException;
import org.openide.util.RequestProcessor;
/** Reference to one position in a document.
* This position is held as an integer offset, or as a {@link Position} object.
* There is also support for serialization of positions.
*
* @author Petr Hamernik
*/
public final class PositionRef extends Object implements Serializable {
static final long serialVersionUID = -4931337398907426948L;
/** Which type of position is currently holded - int X Position */
transient private Manager.Kind kind;
/** Manager for this position */
private Manager manager;
/** insert after? */
private boolean insertAfter;
private boolean is178;
/** Creates new PositionRef
using the given manager at the specified
* position offset.
* @param manager manager for the position
* @param offset - position in the document
* @param bias the bias for the position
*/
PositionRef (Manager manager, int offset, Position.Bias bias) {
this (manager, manager.new OffsetKind (offset), bias);
if (offset == 178) {
is178 = true;
System.err.println("PositionRef=" + System.identityHashCode(this) + " is178 constructed");
Thread.dumpStack();
}
}
/** Creates new PositionRef
using the given manager at the specified
* line and column.
* @param manager manager for the position
* @param line line number
* @param column column number
* @param bias the bias for the position
*/
PositionRef (Manager manager, int line, int column, Position.Bias bias) {
this (manager, manager.new LineKind (line, column), bias);
}
/** Constructor for everything.
* @param manager manager that we are refering to
* @param kind kind of position we hold
* @param bias bias for the position
*/
private PositionRef (Manager manager, Manager.Kind kind, Position.Bias bias) {
this.manager = manager;
this.kind = kind;
insertAfter = (bias == Position.Bias.Backward);
init ();
}
/** Initialize variables after construction and after deserialization. */
private void init() {
kind = manager.addPosition(this);
}
/** Writes the manager and the offset (int). */
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeBoolean (insertAfter);
out.writeObject (manager);
kind.write (out);
}
/** Reads the manager and the offset (int). */
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
insertAfter = in.readBoolean ();
manager = (Manager)in.readObject();
kind = manager.readKind (in);
init ();
}
/** @return the appropriate manager for this position ref.
*/
public CloneableEditorSupport getCloneableEditorSupport () {
return manager.getCloneableEditorSupport ();
}
/** Getter for the editor support this position ref is associated with.
* But because the possition ref can be associated with any CloneableEditorSupport
* there can be situations when the editor support cannot be found.
* That is why this method can ClassCastException.
*
* @return editor support
* @exception ClassCastException if the position is attached to CloneableEditorSupport
* that is not subclass of EditorSupport
* @deprecated Will be deleted, please use {@link #getCloneableEditorSupport} instead.
*/
/*nbif compat.loaders_32143
public EditorSupport getEditorSupport () {
IllegalArgumentException ex = new IllegalArgumentException ("Call to an illegal method"); // NOI18N
org.openide.ErrorManager.getDefault ().annotate(ex,
"Method PositionRef.getEditorSupport will be deleted, use PositionRef.getCloneableEditorSupport instead!" // NOI18N
);
org.openide.ErrorManager.getDefault ().notify (org.openide.ErrorManager.INFORMATIONAL, ex);
return EditorSupport.extract (getCloneableEditorSupport ());
}
/*nbend*/
/** @return the bias of the position
*/
public Position.Bias getPositionBias() {
return insertAfter ? Position.Bias.Backward : Position.Bias.Forward;
}
/** @return the position as swing.text.Position object.
* @exception IOException when an exception occured during reading the file.
*/
public Position getPosition() throws IOException {
if(manager.getCloneableEditorSupport().getDocument() == null) {
manager.getCloneableEditorSupport ().openDocument ();
}
synchronized(manager) {
Manager.PositionKind p = (Manager.PositionKind)kind;
return p.pos;
}
}
/** @return the position as offset index in the file.
*/
public int getOffset() {
return kind.getOffset ();
}
/** Get the line number where this position points to.
* @return the line number for this position
* @throws IOException if the document could not be opened to check the line number
*/
public int getLine() throws IOException {
return kind.getLine ();
}
/** Get the column number where this position points to.
* @return the column number within a line (counting starts from zero)
* @exception IOException if the document could not be opened to check the column number
*/
public int getColumn() throws IOException {
return kind.getColumn ();
}
public String toString() {
return "Pos[" + getOffset () + "]" + ", kind=" + kind + ", is178=" + is178; // NOI18N
}
/** This class is responsible for the holding the Document object
* and the switching the status of PositionRef (Position X offset)
* objects which depends to this manager.
* It has one abstract method for the creating the StyledDocument.
*/
static final class Manager extends Object
implements Runnable, Serializable {
/** Head item of data structure replacing linked list here.
* @see ChainItem */
private transient ChainItem head;
/** ReferenceQueue where all ChainedItem
's will be enqueued to. */
private transient ReferenceQueue queue;
/** Counter which counts enqued items and after reaching
* number 100 schedules sweepTask. */
private transient int counter;
/** Task which is run in RequestProcessor thread and provides
* full pass sweep, i.e. removes items with garbaged referents from
* data strucure. */
private transient RequestProcessor.Task sweepTask;
/** support for the editor */
transient private CloneableEditorSupport support;
/** the document for this manager or null if the manager is not in memory */
transient private StyledDocument doc;
static final long serialVersionUID =-4374030124265110801L;
/** Creates new manager
* @param supp support to work with
*/
public Manager(CloneableEditorSupport supp) {
support = supp;
init();
}
/** Initialize the variables to the default values. */
protected void init() {
queue = new ReferenceQueue();
// A stable mark used to simplify operations with the list
head = new ChainItem(null, null, null);
}
/** Reads the object and initialize */
private void readObject (ObjectInputStream in) throws IOException, ClassNotFoundException {
Object firstObject = in.readObject();
/* Get rid of backward compatibility
if (firstObject instanceof DataObject) {
DataObject obj = (DataObject)firstObject;
support = (CloneableEditorSupport) obj.getCookie(CloneableEditorSupport.class);
} else */
{
// first object is environment
CloneableEditorSupport.Env env = (CloneableEditorSupport.Env)firstObject;
support = (CloneableEditorSupport)env.findCloneableOpenSupport ();
}
if (support == null) {
//PENDING - what about now ? does exist better way ?
throw new IOException();
}
}
final Object readResolve () {
return support.getPositionManager ();
}
private void writeObject(ObjectOutputStream out) throws IOException {
// old serialization version out.writeObject(support.findDataObject());
out.writeObject (support.env ());
}
/** @return the styled document or null if the document is not loaded.
*/
public CloneableEditorSupport getCloneableEditorSupport () {
return support;
}
/** Converts all positions into document one.
*/
void documentOpened (StyledDocument doc) {
this.doc = doc;
processPositions(true);
}
/** Closes the document and switch all positionRefs to the offset (int)
* holding status (Position objects willbe forgotten.
*/
void documentClosed () {
processPositions(false);
doc = null;
}
/** Puts/gets positions to/from memory. It also provides full
* pass sweep of the data structure (inlined in the code).
* @param toMemory puts positions to memory if true
,
* from memory if false
*/
private void processPositions(final boolean toMemory) {
// clear the queue, we'll do the sweep inline anyway
while(queue.poll() != null);
counter = 0;
/* pre-33165
synchronized(this) {
ChainItem previous = head;
ChainItem ref = previous.next;
while(ref != null) {
PositionRef pos = (PositionRef)ref.get();
if(pos == null) {
// Remove the item from data structure.
previous.next = ref.next;
} else {
// Process the PostionRef.
if(toMemory) {
pos.kind = pos.kind.toMemory(pos.insertAfter);
} else {
pos.kind = pos.kind.fromMemory();
}
previous = ref;
}
ref = ref.next;
}
}
*/
new DocumentRenderer(DocumentRenderer.PROCESS_POSITIONS, toMemory).render();
}
/** Polls queue and increases the counter
accordingly.
* Schedule full sweep task if counter exceedes 100. */
private void checkQueue() {
while(queue.poll() != null) {
counter++;
}
if(counter > 100) {
counter = 0;
if(sweepTask == null) {
sweepTask = RequestProcessor.getDefault().post(this);
} else if(sweepTask.isFinished()) {
sweepTask.schedule(0);
}
}
}
/** Implements Runnable
interface.
* Does full pass sweep in RequestProcessor
thread. */
public synchronized void run() {
ChainItem previous = head;
ChainItem ref = previous.next;
while(ref != null) {
if(ref.get() == null) {
// Remove the item from data structure.
previous.next = ref.next;
} else {
previous = ref;
}
ref = ref.next;
}
}
/** Adds the position to this manager. */
Kind addPosition(final PositionRef pos) {
Kind kind;
/* pre-33165
synchronized(this) {
head.next = new ChainItem(pos, queue, head.next);
kind = (doc == null ?
pos.kind :
pos.kind.toMemory(pos.insertAfter));
}
*/
kind = (Kind)new DocumentRenderer(DocumentRenderer.ADD_POSITION, pos).renderToObject();
checkQueue();
return kind;
}
//
// Kinds
//
/** Loads the kind from the stream */
Kind readKind (DataInput is) throws IOException {
int offset = is.readInt ();
int line = is.readInt ();
int column = is.readInt ();
if (offset == -1) {
// line and column must be valid
return new LineKind (line, column);
}
if (line == -1 || column == -1) {
// offset kind
return new OffsetKind (offset);
}
// out of memory representation
return new OutKind (offset, line, column);
}
// #19694. Item of special data structure replacing
// for our purposed LinkedList due to performance reasons.
/** One item which chained instanced provides data structure
* keeping positions for this Manager. */
private static class ChainItem extends WeakReference {
/** Next reference keeping the position. */
ChainItem next;
/** Cointructs chanined item.
* @param position PositionRef
as referent for this
* instance
* @param queue ReferenceQueue
to be used for this instance
* @param next next chained item */
public ChainItem(PositionRef position, ReferenceQueue queue, ChainItem next) {
super(position, queue);
this.next = next;
}
} // End of class ChainItem.
/** Base kind with all methods */
private abstract class Kind extends Object {
Kind() {}
/** Offset */
public abstract int getOffset ();
/** Get the line number */
public abstract int getLine() throws IOException;
/** Get the column number */
public abstract int getColumn() throws IOException;
/** Writes the kind to stream */
public abstract void write (DataOutput os) throws IOException;
/** Converts the kind to representation in memory */
public PositionKind toMemory (boolean insertAfter) {
/* pre-33165
// try to find the right position
Position p;
try {
p = NbDocument.createPosition (doc, getOffset (), insertAfter ? Position.Bias.Forward : Position.Bias.Backward);
} catch (BadLocationException e) {
p = doc.getEndPosition ();
}
return new PositionKind (p);
*/
return (PositionKind)new DocumentRenderer(
DocumentRenderer.KIND_TO_MEMORY, this, insertAfter).renderToObject();
}
/** Converts the kind to representation out from memory */
public Kind fromMemory () {
return this;
}
}
/** Kind for representing position when the document is
* in memory.
*/
private final class PositionKind extends Kind {
/** position */
private Position pos;
private boolean is178;
/** Constructor */
public PositionKind (Position pos) {
this.pos = pos;
is178 = (pos.getOffset() == 178);
if (is178) {
System.err.println("PositionKind=" + this + " is178 constructed");
Thread.dumpStack();
}
}
/** Offset */
public int getOffset () {
return pos.getOffset ();
}
/** Get the line number */
public int getLine() {
// pre-33165 return NbDocument.findLineNumber(doc, getOffset());
return new DocumentRenderer(
DocumentRenderer.POSITION_KIND_GET_LINE, this).renderToInt();
}
/** Get the column number */
public int getColumn() {
// pre-33165 return NbDocument.findLineColumn(doc, getOffset());
return new DocumentRenderer(
DocumentRenderer.POSITION_KIND_GET_COLUMN, this).renderToInt();
}
/** Writes the kind to stream */
public void write (DataOutput os) throws IOException {
/* pre-33165
int offset = getOffset();
int line = getLine();
int column = getColumn();
*/
DocumentRenderer renderer = new DocumentRenderer(
DocumentRenderer.POSITION_KIND_WRITE, this);
int offset = renderer.renderToIntIOE();
int line = renderer.getLine();
int column = renderer.getColumn();
if(offset < 0 || line < 0 || column < 0) {
throw new IOException(
"Illegal PositionKind: " + pos + "[offset=" // NOI18N
+ offset + ",line=" // NOI18N
+ line + ",column=" + column + "] in " // NOI18N
+ doc + " used by " + support + "." // NOI18N
);
}
os.writeInt(offset);
os.writeInt(line);
os.writeInt(column);
}
/** Converts the kind to representation in memory */
public PositionKind toMemory (boolean insertAfter) {
return this;
}
/** Converts the kind to representation out from memory */
public Kind fromMemory () {
return new OutKind (this);
}
}
/** Kind for representing position when the document is
* out from memory. There are all infomation about the position,
* including offset, line and column.
*/
private final class OutKind extends Kind {
private int offset;
private int line;
private int column;
/** Constructs the out kind from the position kind.
*/
public OutKind (PositionKind kind) {
/* pre-33165
int offset = kind.getOffset();
int line = kind.getLine();
int column = kind.getColumn();
*/
DocumentRenderer renderer = new DocumentRenderer(
DocumentRenderer.OUT_KIND_CONSTRUCTOR, kind);
int offset = renderer.renderToInt();
int line = renderer.getLine();
int column = renderer.getColumn();
if (offset == 178) {
System.err.println("OutKind=" + this + " is178 constructed for PositionKind=" + kind);
Thread.dumpStack();
}
System.err.println("offset=" + offset + ", line=" + line + ", column=" + column);
if(offset < 0 || line < 0 || column < 0) {
throw new IndexOutOfBoundsException(
"Illegal OutKind[offset=" // NOI18N
+ offset + ",line=" // NOI18N
+ line + ",column=" + column + "] in " // NOI18N
+ doc + " used by " + support + "." // NOI18N
);
}
this.offset = offset;
this.line = line;
this.column = column;
}
/** Constructs the out kind.
*/
OutKind (int offset, int line, int column) {
this.offset = offset;
this.line = line;
this.column = column;
}
/** Offset */
public int getOffset () {
return offset;
}
/** Get the line number */
public int getLine() {
return line;
}
/** Get the column number */
public int getColumn() {
return column;
}
/** Writes the kind to stream */
public void write (DataOutput os) throws IOException {
if(offset < 0 || line < 0 || column < 0) {
throw new IOException(
"Illegal OutKind[offset=" // NOI18N
+ offset + ",line=" // NOI18N
+ line + ",column=" + column + "] in " // NOI18N
+ doc + " used by " + support + "." // NOI18N
);
}
os.writeInt (offset);
os.writeInt (line);
os.writeInt (column);
}
} // OutKind
/** Kind for representing position when the document is
* out from memory. Represents only offset in the document.
*/
private final class OffsetKind extends Kind {
private int offset;
/** Constructs the out kind from the position kind.
*/
public OffsetKind (int offset) {
if(offset < 0) {
throw new IndexOutOfBoundsException(
"Illegal OffsetKind[offset=" // NOI18N
+ offset + "] in " + doc + " used by " // NOI18N
+ support + "." // NOI18N
);
}
this.offset = offset;
if (offset == 178) {
System.err.println("OffsetKind=" + this + " is178 constructed");
Thread.dumpStack();
}
}
/** Offset */
public int getOffset () {
return offset;
}
/** Get the line number */
public int getLine() throws IOException {
// pre-33165 return NbDocument.findLineNumber(getCloneableEditorSupport().openDocument(), offset);
getCloneableEditorSupport().openDocument(); // make sure document is fully read
return new DocumentRenderer(DocumentRenderer.OFFSET_KIND_GET_LINE,
this, offset).renderToIntIOE();
}
/** Get the column number */
public int getColumn() throws IOException {
// pre-33165 return NbDocument.findLineColumn (getCloneableEditorSupport().openDocument(), offset);
getCloneableEditorSupport().openDocument(); // make sure document fully read
return new DocumentRenderer(DocumentRenderer.OFFSET_KIND_GET_COLUMN,
this, offset).renderToIntIOE();
}
/** Writes the kind to stream */
public void write (DataOutput os) throws IOException {
if(offset < 0) {
throw new IOException(
"Illegal OffsetKind[offset=" // NOI18N
+ offset + "] in " + doc + " used by " // NOI18N
+ support + "." // NOI18N
);
}
os.writeInt (offset);
os.writeInt (-1);
os.writeInt (-1);
}
}
/** Kind for representing position when the document is
* out from memory. Represents only line and column in the document.
*/
private final class LineKind extends Kind {
private int line;
private int column;
/** Constructor.
*/
public LineKind (int line, int column) {
if(line < 0 || column < 0) {
throw new IndexOutOfBoundsException(
"Illegal LineKind[line=" // NOI18N
+ line + ",column=" + column + "] in " // NOI18N
+ doc + " used by " + support + "." // NOI18N
);
}
this.line = line;
this.column = column;
}
/** Offset */
public int getOffset () {
/* pre-33165
try {
StyledDocument doc = getCloneableEditorSupport().getDocument();
if (doc == null) {
doc = getCloneableEditorSupport().openDocument();
}
return NbDocument.findLineOffset (doc, line) + column;
} catch (IOException e) {
// what to do? hopefully unlikelly
return 0;
}
*/
try {
StyledDocument doc = getCloneableEditorSupport().getDocument();
if (doc == null) {
doc = getCloneableEditorSupport().openDocument();
}
int retOffset = new DocumentRenderer(DocumentRenderer.LINE_KIND_GET_OFFSET,
this, line, column, doc).renderToInt();
return retOffset;
} catch (IOException e) {
// what to do? hopefully unlikelly
return 0;
}
}
/** Get the line number */
public int getLine() throws IOException {
return line;
}
/** Get the column number */
public int getColumn() throws IOException {
return column;
}
/** Writes the kind to stream */
public void write (DataOutput os) throws IOException {
if(line < 0 || column < 0) {
throw new IOException(
"Illegal LineKind[line=" // NOI18N
+ line + ",column=" + column + "] in " // NOI18N
+ doc + " used by " + support + "." // NOI18N
);
}
os.writeInt (-1);
os.writeInt (line);
os.writeInt (column);
}
/** Converts the kind to representation in memory */
public PositionKind toMemory (boolean insertAfter) {
/* pre-33165
// try to find the right position
Position p;
try {
p = NbDocument.createPosition (doc, NbDocument.findLineOffset (doc, line) + column, insertAfter ? Position.Bias.Forward : Position.Bias.Backward);
} catch (BadLocationException e) {
p = doc.getEndPosition ();
}
*/
Position p = (Position)new DocumentRenderer(
DocumentRenderer.LINE_KIND_TO_MEMORY, this,
line, column, insertAfter).renderToObject();
return new PositionKind (p);
}
}
/**
* Helper class ensuring that critical parts will run under document's read lock
* by using {@link javax.swing.text.Document#render(Runnable)}.
*/
private final class DocumentRenderer implements Runnable {
private static final int KIND_TO_MEMORY = 0;
private static final int POSITION_KIND_GET_LINE = KIND_TO_MEMORY + 1;
private static final int POSITION_KIND_GET_COLUMN = POSITION_KIND_GET_LINE + 1;
private static final int POSITION_KIND_WRITE = POSITION_KIND_GET_COLUMN + 1;
private static final int OUT_KIND_CONSTRUCTOR = POSITION_KIND_WRITE + 1;
private static final int OFFSET_KIND_GET_LINE = OUT_KIND_CONSTRUCTOR + 1;
private static final int OFFSET_KIND_GET_COLUMN = OFFSET_KIND_GET_LINE + 1;
private static final int LINE_KIND_GET_OFFSET = OFFSET_KIND_GET_COLUMN + 1;
private static final int LINE_KIND_TO_MEMORY = LINE_KIND_GET_OFFSET + 1;
private static final int PROCESS_POSITIONS = LINE_KIND_TO_MEMORY + 1;
private static final int ADD_POSITION = PROCESS_POSITIONS + 1;
private final int opCode;
private Kind argKind;
private boolean argInsertAfter;
private boolean argToMemory;
private int argInt;
private Object retObject;
private int retInt;
private int argLine;
private int argColumn;
private PositionRef argPos;
private StyledDocument argDoc;
private IOException ioException;
DocumentRenderer(int opCode, Kind argKind) {
this.opCode = opCode;
this.argKind = argKind;
}
DocumentRenderer(int opCode, Kind argKind, boolean argInsertAfter) {
this(opCode, argKind);
this.argInsertAfter = argInsertAfter;
}
DocumentRenderer(int opCode, Kind argKind, int argInt) {
this(opCode, argKind);
this.argInt = argInt;
}
DocumentRenderer(int opCode, Kind argKind, int argLine, int argColumn) {
this(opCode, argKind);
this.argLine = argLine;
this.argColumn = argColumn;
}
DocumentRenderer(int opCode, Kind argKind, int argLine, int argColumn, StyledDocument argDoc) {
this(opCode, argKind, argLine, argColumn);
this.argDoc = argDoc;
}
DocumentRenderer(int opCode, Kind argKind, int argLine, int argColumn, boolean argInsertAfter) {
this(opCode, argKind, argLine, argColumn);
this.argInsertAfter = argInsertAfter;
}
DocumentRenderer(int opCode, boolean toMemory) {
this.opCode = opCode;
this.argToMemory = toMemory;
}
DocumentRenderer(int opCode, PositionRef argPos) {
this.opCode = opCode;
this.argPos = argPos;
}
void render() {
if (doc != null) {
doc.render(this);
} else {
this.run();
}
}
Object renderToObjectIOE() throws IOException {
Object o = renderToObject();
if (ioException != null) {
throw ioException;
}
return o;
}
Object renderToObject() {
render();
return retObject;
}
int renderToIntIOE() throws IOException {
int i = renderToInt();
if (ioException != null) {
throw ioException;
}
return i;
}
int renderToInt() {
render();
return retInt;
}
int getLine() {
return argLine;
}
int getColumn() {
return argColumn;
}
public void run() {
System.err.println("opCode=" + opCode);
try {
switch (opCode) {
case KIND_TO_MEMORY: {
// try to find the right position
Position p;
try {
p = NbDocument.createPosition (doc, argKind.getOffset (),
argInsertAfter ? Position.Bias.Forward : Position.Bias.Backward);
} catch (BadLocationException e) {
p = doc.getEndPosition ();
}
retObject = (PositionKind)new PositionKind (p);
break; }
case POSITION_KIND_GET_LINE: {
retInt = NbDocument.findLineNumber(doc, argKind.getOffset());
break; }
case POSITION_KIND_GET_COLUMN: {
retInt = NbDocument.findLineColumn(doc, argKind.getOffset());
break; }
case POSITION_KIND_WRITE:
case OUT_KIND_CONSTRUCTOR: {
retInt = argKind.getOffset();
argLine = argKind.getLine();
argColumn = argKind.getColumn();
break; }
case OFFSET_KIND_GET_LINE: {
retInt = NbDocument.findLineNumber(getCloneableEditorSupport().openDocument(), argInt);
break; }
case OFFSET_KIND_GET_COLUMN: {
retInt = NbDocument.findLineColumn (getCloneableEditorSupport().openDocument(), argInt);
break; }
case LINE_KIND_GET_OFFSET: {
retInt = NbDocument.findLineOffset (argDoc, argLine) + argColumn;
break; }
case LINE_KIND_TO_MEMORY: {
// try to find the right position
try {
retObject = NbDocument.createPosition (doc,
NbDocument.findLineOffset (doc, argLine) + argColumn,
argInsertAfter ? Position.Bias.Forward : Position.Bias.Backward);
} catch (BadLocationException e) {
e.printStackTrace(); // [TODO] remove
retObject = doc.getEndPosition ();
}
break; }
case PROCESS_POSITIONS: {
synchronized(Manager.this) {
ChainItem previous = head;
ChainItem ref = previous.next;
while(ref != null) {
PositionRef pos = (PositionRef)ref.get();
if(pos == null) {
// Remove the item from data structure.
previous.next = ref.next;
} else {
// Process the PostionRef.
if(argToMemory) {
pos.kind = pos.kind.toMemory(pos.insertAfter);
} else {
pos.kind = pos.kind.fromMemory();
}
previous = ref;
}
ref = ref.next;
}
}
break; }
case ADD_POSITION: {
synchronized(Manager.this) {
head.next = new ChainItem(argPos, queue, head.next);
retObject = (doc == null ?
argPos.kind :
argPos.kind.toMemory(argPos.insertAfter));
}
break; }
default:
throw new IllegalStateException(); // Unknown opcode
}
} catch (IOException e) {
e.printStackTrace();
ioException = e;
}
}
}
}
}