/**
*
*/
package org.openntf.domino.big.impl;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.logging.Logger;
import org.openntf.domino.Database;
import org.openntf.domino.Document;
import org.openntf.domino.DocumentCollection;
import org.openntf.domino.NoteCollection;
import org.openntf.domino.Session;
import org.openntf.domino.View;
import org.openntf.domino.annotations.Incomplete;
import org.openntf.domino.utils.Factory;
/**
* @author nfreeman
*
*/
@Incomplete
public class BigNoteCollection implements org.openntf.domino.big.BigNoteCollection {
@SuppressWarnings("unused")
private static final Logger log_ = Logger.getLogger(BigNoteCollection.class.getName());
private Map<String, int[]> idMap_;
public static String getAddress(final Database db) {
String result;
if ("".equals(db.getServer())) {
result = "";
} else {
result = db.getServer() + "!!";
}
result += db.getReplicaID();
return result;
}
public static String getAddress(final Document doc) {
final Database db = doc.getAncestorDatabase();
String result = getAddress(db);
result += doc.getNoteID();
return result;
}
public static String getServerName(final String address) {
final int bangbang = address.indexOf("!!");
if (bangbang > 0) {
return address.substring(0, bangbang - 1);
} else {
return "";
}
}
public static String getReplicaId(final String address) {
final int bangbang = address.indexOf("!!");
if (bangbang > 0) {
return address.substring(bangbang + 2, bangbang + 2 + 16);
} else {
return address.substring(0, 16);
}
}
public static String getNoteid(final String address) {
final int bangbang = address.indexOf("!!");
if (bangbang > 0) {
return address.substring(bangbang + 2 + 16);
} else {
return address.substring(16);
}
}
public static Document getDocument(final Session session, final String server, final String replid, final String noteid) {
final Database db = session.getDatabase("", "");
db.openByReplicaID(server, replid);
if (db.isOpen()) {
final Document result = db.getDocumentByID(noteid);
return result;
} else {
// TODO handle exception properly
return null;
}
}
public static class DocumentIterator implements Iterator<Document> {
private final BigNoteCollection coll_;
private Iterator<String> keyIterator_;
@SuppressWarnings("unused")
private final Set<String> completedKeys_ = new HashSet<String>();
@SuppressWarnings("unused")
private String currentKey_;
private int[] currentInts_;
private int currentIntLength_;
private int currentPos_;
DocumentIterator(final BigNoteCollection coll) {
coll_ = coll;
}
/*
* (non-Javadoc)
*
* @see java.util.Iterator#hasNext()
*/
@Override
public boolean hasNext() {
boolean result = false;
if (keyIterator_ == null) {
keyIterator_ = coll_.iterator();
}
if (currentPos_ >= currentIntLength_) {
currentInts_ = getNextInts();
if (currentInts_ != null) {
currentIntLength_ = currentInts_.length;
currentPos_ = 0;
result = true;
} else {
result = false;
}
} else {
result = true;
}
return result;
}
private int[] getNextInts() {
int length = 0;
String key = null;
int[] ints = null;
while (length == 0) {
key = keyIterator_.next();
if (key == null)
return null;
ints = coll_.getNoteIds(key);
length = ints == null ? 0 : ints.length;
}
// currentKey_ = key;
return ints;
}
/*
* (non-Javadoc)
*
* @see java.util.Iterator#next()
*/
@Override
public Document next() {
return null;
}
/*
* (non-Javadoc)
*
* @see java.util.Iterator#remove()
*/
@Override
public void remove() {
// NOOP
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<String> iterator() {
final Map<String, int[]> map = getIdMap();
Set<String> set;
synchronized (map) {
set = Collections.unmodifiableSortedSet((SortedSet<String>) map.keySet());
}
return set.iterator();
}
public Iterator<Document> documents() {
return new DocumentIterator(this);
}
/*
* (non-Javadoc)
*
* @see org.openntf.domino.big.BigNoteCollection#add(java.lang.String, int)
*/
@Override
public void add(final String filepath, final int additionSpecifier) {
final int[] ints = new int[1];
ints[0] = additionSpecifier;
add(filepath, ints);
}
/*
* (non-Javadoc)
*
* @see org.openntf.domino.big.BigNoteCollection#add(java.lang.String, int[])
*/
@Override
public void add(final String filepath, final int[] ints) {
Map<String, int[]> map = getIdMap();
synchronized (map) {
final int[] current = getIdMap().get(filepath);
if (current == null) {
getIdMap().put(filepath, ints);
} else {
// TODO potentially grow arrays in blocks
final int[] newArray = new int[current.length + ints.length + 1];
System.arraycopy(current, 0, newArray, 0, current.length);
System.arraycopy(ints, 0, newArray, current.length + 1, ints.length);
getIdMap().put(filepath, newArray);
}
}
}
/*
* (non-Javadoc)
*
* @see org.openntf.domino.big.BigNoteCollection#add(java.lang.String, java.lang.String)
*/
@Override
public void add(final String filepath, final String noteid) {
final int nid = Integer.valueOf(noteid, 16).intValue();
add(filepath, nid);
}
public void add(final NoteCollection nc) {
String filepath = getAddress(nc.getAncestorDatabase());
add(filepath, nc.getNoteIDs());
}
@SuppressWarnings("deprecation")
public void add(final DocumentCollection dc) {
add(Factory.toNoteCollection(dc));
}
public void add(final Document doc) {
final String filepath = getAddress(doc.getAncestorDatabase());
add(filepath, doc.getNoteID());
}
public void add(final View view) {
final String filepath = getAddress(view.getAncestorDatabase());
add(filepath, view.getDocument().getNoteID());
}
/*
* (non-Javadoc)
*
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
@Override
public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
int keyCount = in.readInt();
if (keyCount > 0) {
idMap_ = new LinkedHashMap<String, int[]>();
for (int i = 0; i < keyCount; i++) {
String key = in.readUTF();
int size = in.readInt();
int[] ints = new int[size];
for (int j = 0; j < size; j++) {
ints[j] = in.readInt();
}
idMap_.put(key, ints);
}
}
}
/*
* (non-Javadoc)
*
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
@Override
public void writeExternal(final ObjectOutput out) throws IOException {
Map<String, int[]> map = getIdMap();
synchronized (map) {
Set<String> keys = map.keySet();
out.writeInt(keys.size());
for (String key : map.keySet()) {
out.writeUTF(key);
int[] ints = map.get(key);
out.writeInt(ints.length);
for (int i : ints) {
out.writeInt(i);
}
}
}
}
public int[] getNoteIds(final String key) {
Map<String, int[]> map = getIdMap();
synchronized (map) {
return map.get(key);
}
}
private Map<String, int[]> getIdMap() {
if (idMap_ == null) {
idMap_ = new LinkedHashMap<String, int[]>();
}
return idMap_;
}
}