package org.openntf.domino.nsfdata.structs;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Formatter;
/**
* <p>
* The Universal Note ID (UNID) identifies all copies of the same note in different replicas of the same database universally (across all
* servers). If one note in one database has the same UNID as another note in a replica database, then the two notes are replicas of each
* other.
* </p>
*
* <p>
* The UNID is used to reference a specific note from another note. Specifically, the FIELD_LINK ($REF) field of a response note contains
* the UNID of it's parent. Similarly, Doc Links (see NOTELINK) contains the UNID of the linked-to note plus the database ID where the
* linked-to note can be found. The important characteristic of the UNID is that it continues to reference a specific note even if the note
* being referenced is updated.
* </p>
*
* <p>
* The Domino replicator uses the Universal Note ID to match the notes in one database with their respective copies in replica databases.
* For example, if database A is a replica copy of database B, database A contains a note with a particular UNID, and database B contains a
* note with the same UNID, then the replicator concludes that these two notes are replica copies of one another. On the other hand, if
* database A contains a note with a particular UNID but database B does not, then the replicator will create a copy of that note and add it
* to database B.
* </p>
*
* <p>
* One database must never contain two notes with the same UNID. If the replicator finds two notes with the same UNID in the same database,
* it generates an error message in the log and does not replicate the document.
* </p>
*
* <p>
* The "File" member of the UNID contains a number derived in different ways depending on the release of Domino or Notes. Pre- 2.1 versions
* of Notes set the "File" member to the creation timedate of the NSF file in which the note is created. Notes 2.1 sets the "File" member to
* a user-unique identifier, derived in part from information in the ID of the user creating the note, and in part from the database where
* the note is created. Notes 3.0 sets the "File" member to a random number generated at the time the note is created.
* </p>
*
* <p>
* The "Note" member of the UNID contains the date/time when the very first copy of the note was stored into the first NSF (Note: date/time
* from $CREATED item, if exists, takes precedence).
* </p>
*
* <p>
* (nsfdata.h)
* </p>
*
*/
public class UNIVERSALNOTEID extends AbstractStruct {
public final TIMEDATE File = inner(new TIMEDATE());
public final TIMEDATE Note = inner(new TIMEDATE());
public static UNIVERSALNOTEID fromString(final String hexString) {
if (hexString == null) {
UNIVERSALNOTEID result = new UNIVERSALNOTEID();
result.init();
return result;
}
int len = hexString.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
}
// This is big endian because Java is internally, apparently
ByteBuffer longBuffer = ByteBuffer.wrap(data).order(ByteOrder.BIG_ENDIAN);
long[] longs = new long[2];
longs[0] = longBuffer.getLong();
longs[1] = longBuffer.getLong();
return fromLongs(longs);
}
public static UNIVERSALNOTEID fromLongs(final long[] value) {
if (value == null) {
throw new IllegalArgumentException("value cannot be null");
}
if (value.length != 2) {
throw new IllegalArgumentException("value length must be 2");
}
byte[] newData = new byte[16];
ByteBuffer data = ByteBuffer.wrap(newData).order(ByteOrder.LITTLE_ENDIAN);
for (int i = 0; i < value.length; i++) {
data.putLong(value[i]);
}
data.position(0);
UNIVERSALNOTEID result = new UNIVERSALNOTEID();
result.init(data);
return result;
}
public String getStringValue() {
Formatter formatter = new Formatter();
// byte[] data = new byte[getData().limit() - getData().position()];
ByteBuffer data = getData().duplicate().order(ByteOrder.LITTLE_ENDIAN);
formatter.format("%16x", data.getLong());
formatter.format("%16x", data.getLong());
String result = formatter.toString();
formatter.close();
return result.toUpperCase();
}
@Override
public String toString() {
return "[" + getClass().getSimpleName() + ": " + getStringValue() + "]";
}
}