com.mindoo.domino.jna.internal.NotesLookupResultBufferDecoder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of domino-jna Show documentation
Show all versions of domino-jna Show documentation
Java project to access the HCL Domino C API using Java Native Access (JNA)
The newest version!
package com.mindoo.domino.jna.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import com.mindoo.domino.jna.IItemTableData;
import com.mindoo.domino.jna.IItemValueTableData;
import com.mindoo.domino.jna.NotesCollection;
import com.mindoo.domino.jna.NotesCollectionStats;
import com.mindoo.domino.jna.NotesDateRange;
import com.mindoo.domino.jna.NotesIDTable;
import com.mindoo.domino.jna.NotesItem;
import com.mindoo.domino.jna.NotesTimeDate;
import com.mindoo.domino.jna.NotesViewEntryData;
import com.mindoo.domino.jna.NotesViewLookupResultData;
import com.mindoo.domino.jna.constants.ReadMask;
import com.mindoo.domino.jna.errors.NotesError;
import com.mindoo.domino.jna.errors.NotesErrorUtils;
import com.mindoo.domino.jna.gc.NotesGC;
import com.mindoo.domino.jna.internal.structs.NotesCollectionStatsStruct;
import com.mindoo.domino.jna.internal.structs.NotesItemTableStruct;
import com.mindoo.domino.jna.utils.LMBCSString;
import com.mindoo.domino.jna.utils.NotesStringUtils;
import com.mindoo.domino.jna.utils.PlatformUtils;
import com.mindoo.domino.jna.utils.PointerWithBounds;
import com.sun.jna.Pointer;
/**
* Utility class to decode the buffer returned by data lookups, e.g. in {@link NotesCollection}'s
* and for database searches.
*
* @author Karsten Lehmann
*/
public class NotesLookupResultBufferDecoder {
/**
* Decodes the buffer, 32 bit mode
*
* @param parentCollection parent collection
* @param bufferHandle buffer handle
* @param numEntriesSkipped entries skipped during collection scan
* @param numEntriesReturned entries read during collection scan
* @param returnMask bitmask used to fill the buffer with data
* @param signalFlags signal flags returned by NIFReadEntries, e.g. whether we have more data to read
* @param pos position of first match, if returned by find method
* @param indexModifiedSequenceNo index modified sequence no
* @param retDiffTime only set in {@link NotesCollection#readEntriesExt(com.mindoo.domino.jna.NotesCollectionPosition, EnumSet, int, EnumSet, int, EnumSet, NotesTimeDate, NotesIDTable, Integer)}
* @param convertStringsLazily true to delay string conversion until the first use
* @param convertNotesTimeDateToCalendar true to convert {@link NotesTimeDate} values to {@link Calendar}
* @param singleColumnLookupName for single column lookups, programmatic name of lookup column
* @return collection data
*/
public static NotesViewLookupResultData b32_decodeCollectionLookupResultBuffer(NotesCollection parentCollection, int bufferHandle, int numEntriesSkipped, int numEntriesReturned,
EnumSet returnMask, short signalFlags, String pos,
int indexModifiedSequenceNo, NotesTimeDate retDiffTime, boolean convertStringsLazily, boolean convertNotesTimeDateToCalendar,
String singleColumnLookupName) {
return b64_decodeCollectionLookupResultBuffer(parentCollection, bufferHandle, numEntriesSkipped, numEntriesReturned,
returnMask, signalFlags, pos, indexModifiedSequenceNo, retDiffTime, convertStringsLazily, convertNotesTimeDateToCalendar,
singleColumnLookupName);
}
/**
* Decodes the buffer, 32 bit mode
*
* @param parentCollection parent collection
* @param ptrBuffer buffer pointer
* @param numEntriesSkipped entries skipped during collection scan
* @param numEntriesReturned entries read during collection scan
* @param returnMask bitmask used to fill the buffer with data
* @param signalFlags signal flags returned by NIFReadEntries, e.g. whether we have more data to read
* @param pos position of first match, if returned by find method
* @param indexModifiedSequenceNo index modified sequence no
* @param retDiffTime only set in {@link NotesCollection#readEntriesExt(com.mindoo.domino.jna.NotesCollectionPosition, EnumSet, int, EnumSet, int, EnumSet, NotesTimeDate, NotesIDTable, Integer)}
* @param convertStringsLazily true to delay string conversion until the first use
* @param convertNotesTimeDateToCalendar true to convert {@link NotesTimeDate} values to {@link Calendar}
* @param singleColumnLookupName for single column lookups, programmatic name of lookup column
* @return collection data
*/
public static NotesViewLookupResultData b32_decodeCollectionLookupResultBuffer(NotesCollection parentCollection, Pointer ptrBuffer,
int numEntriesSkipped, int numEntriesReturned,
EnumSet returnMask, short signalFlags, String pos,
int indexModifiedSequenceNo, NotesTimeDate retDiffTime, boolean convertStringsLazily, boolean convertNotesTimeDateToCalendar,
String singleColumnLookupName) {
return b64_decodeCollectionLookupResultBuffer(parentCollection, ptrBuffer, numEntriesSkipped, numEntriesReturned,
returnMask, signalFlags, pos, indexModifiedSequenceNo, retDiffTime, convertStringsLazily, convertNotesTimeDateToCalendar,
singleColumnLookupName);
}
/**
* Decodes the buffer, 64 bit mode
*
* @param parentCollection parent collection
* @param bufferHandle buffer handle
* @param numEntriesSkipped entries skipped during collection scan
* @param numEntriesReturned entries read during collection scan
* @param returnMask bitmask used to fill the buffer with data
* @param signalFlags signal flags returned by NIFReadEntries, e.g. whether we have more data to read
* @param pos position to add to NotesViewLookupResultData object in case view data is read via {@link NotesCollection#findByKeyExtended2(EnumSet, EnumSet, Object...)}
* @param indexModifiedSequenceNo index modified sequence no
* @param retDiffTime only set in {@link NotesCollection#readEntriesExt(com.mindoo.domino.jna.NotesCollectionPosition, EnumSet, int, EnumSet, int, EnumSet, NotesTimeDate, NotesIDTable, Integer)}
* @param convertStringsLazily true to delay string conversion until the first use
* @param convertNotesTimeDateToCalendar true to convert {@link NotesTimeDate} values to {@link Calendar}
* @param singleColumnLookupName for single column lookups, programmatic name of lookup column
* @return collection data
*/
public static NotesViewLookupResultData b64_decodeCollectionLookupResultBuffer(NotesCollection parentCollection, long bufferHandle, int numEntriesSkipped, int numEntriesReturned,
EnumSet returnMask, short signalFlags, String pos, int indexModifiedSequenceNo, NotesTimeDate retDiffTime,
boolean convertStringsLazily, boolean convertNotesTimeDateToCalendar, String singleColumnLookupName) {
Pointer bufferPtr;
if (PlatformUtils.is64Bit()) {
bufferPtr = Mem64.OSLockObject(bufferHandle);
}
else {
bufferPtr = Mem32.OSLockObject((int) bufferHandle);
}
try {
return b64_decodeCollectionLookupResultBuffer(parentCollection, bufferPtr, numEntriesSkipped,
numEntriesReturned, returnMask, signalFlags, pos, indexModifiedSequenceNo, retDiffTime,
convertStringsLazily, convertNotesTimeDateToCalendar, singleColumnLookupName);
}
finally {
if (PlatformUtils.is64Bit()) {
Mem64.OSUnlockObject(bufferHandle);
short result = Mem64.OSMemFree(bufferHandle);
NotesErrorUtils.checkResult(result);
}
else {
Mem32.OSUnlockObject((int)bufferHandle);
short result = Mem32.OSMemFree((int)bufferHandle);
NotesErrorUtils.checkResult(result);
}
}
}
/**
* Decodes the buffer, 64 bit mode
*
* @param parentCollection parent collection
* @param bufferPtr buffer pointer
* @param numEntriesSkipped entries skipped during collection scan
* @param numEntriesReturned entries read during collection scan
* @param returnMask bitmask used to fill the buffer with data
* @param signalFlags signal flags returned by NIFReadEntries, e.g. whether we have more data to read
* @param pos position to add to NotesViewLookupResultData object in case view data is read via {@link NotesCollection#findByKeyExtended2(EnumSet, EnumSet, Object...)}
* @param indexModifiedSequenceNo index modified sequence no
* @param retDiffTime only set in {@link NotesCollection#readEntriesExt(com.mindoo.domino.jna.NotesCollectionPosition, EnumSet, int, EnumSet, int, EnumSet, NotesTimeDate, NotesIDTable, Integer)}
* @param convertStringsLazily true to delay string conversion until the first use
* @param convertNotesTimeDateToCalendar true to convert {@link NotesTimeDate} values to {@link Calendar}
* @param singleColumnLookupName for single column lookups, programmatic name of lookup column
* @return collection data
*/
public static NotesViewLookupResultData b64_decodeCollectionLookupResultBuffer(NotesCollection parentCollection,
Pointer bufferPtr, int numEntriesSkipped, int numEntriesReturned,
EnumSet returnMask, short signalFlags, String pos, int indexModifiedSequenceNo, NotesTimeDate retDiffTime,
boolean convertStringsLazily, boolean convertNotesTimeDateToCalendar, String singleColumnLookupName) {
int bufferPos = 0;
NotesCollectionStats collectionStats = null;
if (returnMask.contains(ReadMask.COLLECTIONSTATS)) {
NotesCollectionStatsStruct tmpStats = NotesCollectionStatsStruct.newInstance(bufferPtr);
tmpStats.read();
collectionStats = new NotesCollectionStats(tmpStats.TopLevelEntries, tmpStats.LastModifiedTime);
bufferPos += tmpStats.size();
}
List viewEntries = new ArrayList();
final boolean decodeAllValues = true;
if (returnMask.size()==1 && returnMask.contains(ReadMask.NOTEID)) {
//special optimized case for reading only note ids
int[] noteIds = new int[numEntriesReturned];
bufferPtr.read(0, noteIds, 0, numEntriesReturned);
for (int i=0; i itemValues = itemTableData.asMap(false);
newData.setSummaryData(itemValues);
}
if (singleColumnLookupName!=null) {
newData.setSingleColumnLookupName(singleColumnLookupName);
}
}
}
return new NotesViewLookupResultData(collectionStats, viewEntries, numEntriesSkipped, numEntriesReturned, signalFlags, pos, indexModifiedSequenceNo, retDiffTime);
}
/**
* Produces an ITEM_TABLE by decoding an ITEM_VALUE_TABLE structure, which contains an ordered list of item values,
* and adding an array of column names
*
* @param columnItemNames column item names
* @param bufferPtr pointer to a buffer
* @param convertStringsLazily true to delay string conversion until the first use
* @param convertNotesTimeDateToCalendar true to convert {@link NotesTimeDate} values to {@link Calendar}
* @param decodeAllValues true to decode all values in the buffer
* @return item value table data
*/
public static IItemTableData decodeItemValueTableWithColumnNames(String[] columnItemNames,
Pointer bufferPtr, boolean convertStringsLazily, boolean convertNotesTimeDateToCalendar, boolean decodeAllValues) {
ItemValueTableDataImpl valueTable = (ItemValueTableDataImpl) decodeItemValueTable(bufferPtr, convertStringsLazily, convertNotesTimeDateToCalendar, decodeAllValues);
IItemTableData itemTableData = new ItemTableDataImpl(columnItemNames, valueTable);
return itemTableData;
}
/**
* Decodes an ITEM_VALUE_TABLE structure, which contains an ordered list of item values
*
* @param bufferPtr pointer to a buffer
* @param convertStringsLazily true to delay string conversion until the first use
* @param convertNotesTimeDateToCalendar true to convert {@link NotesTimeDate} values to {@link Calendar}
* @param decodeAllValues true to decode all values in the buffer
* @return item value table data
*/
public static IItemValueTableData decodeItemValueTable(Pointer bufferPtr,
boolean convertStringsLazily, boolean convertNotesTimeDateToCalendar, boolean decodeAllValues) {
int bufferPos = 0;
//skip item value table header
bufferPos += NotesConstants.itemValueTableSize;
// The information in a view summary of values is as follows:
//
// ITEM_VALUE_TABLE containing header information (total length of summary, number of items in summary)
// WORD containing the length of item #1 (including data type)
// WORD containing the length of item #2 (including data type)
// WORD containing the length of item #3 (including data type)
// ...
// USHORT containing the data type of item #1
// value of item #1
// USHORT containing the data type of item #2
// value of item #2
// USHORT containing the data type of item #3
// value of item #3
// ....
int totalBufferLength = bufferPtr.getShort(0) & 0xffff;
int itemsCount = bufferPtr.getShort(2) & 0xffff;
int[] itemValueLengths = new int[itemsCount];
//we don't have any item names:
int[] itemNameLengths = null;
//read all item lengths
for (int j=0; j0) {
itemNames[j] = NotesStringUtils.fromLMBCS(bufferPtr.share(bufferPos), itemNameLengths[j]);
bufferPos += itemNameLengths[j];
}
//read data type
if (itemValueLengths[j] == 0) {
/* If an item has zero length it indicates an "empty" item in the
summary. This might occur in a lower-level category and stand for a
higher-level category that has already appeared. Or an empty item might
be a field that is missing in a response doc. Just print * as a place
holder and go on to the next item in the pSummary. */
continue;
}
else {
itemDataTypes[j] = (int) (bufferPtr.getShort(bufferPos) & 0xffff);
//add data type size to position
bufferPos += 2;
//read item values
itemValueBufferPointers[j] = bufferPtr.share(bufferPos);
itemValueBufferSizes[j] = itemValueLengths[j] - 2;
//skip item value
bufferPos += (itemValueLengths[j] - 2);
if (decodeAllValues) {
if (itemDataTypes[j] == NotesItem.TYPE_TEXT) {
Object strVal = ItemDecoder.decodeTextValue(itemValueBufferPointers[j], (int) (itemValueBufferSizes[j] & 0xffff), convertStringsLazily);
decodedItemValues[j] = strVal;
}
else if (itemDataTypes[j] == NotesItem.TYPE_TEXT_LIST) {
//read a text list item value
int valueLength = (int) (itemValueBufferSizes[j] & 0xffff);
List