All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hcl.domino.jna.data.JNADominoCollectionPosition Maven / Gradle / Ivy

There is a newer version: 1.44.0
Show newest version
/*
 * ==========================================================================
 * Copyright (C) 2019-2022 HCL America, Inc. ( http://www.hcl.com/ )
 *                            All rights reserved.
 * ==========================================================================
 * Licensed under the  Apache License, Version 2.0  (the "License").  You may
 * not use this file except in compliance with the License.  You may obtain a
 * copy of the License at .
 *
 * Unless  required  by applicable  law or  agreed  to  in writing,  software
 * distributed under the License is distributed on an  "AS IS" BASIS, WITHOUT
 * WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the  specific language  governing permissions  and limitations
 * under the License.
 * ==========================================================================
 */
package com.hcl.domino.jna.data;

import java.text.MessageFormat;
import java.util.Arrays;

import com.hcl.domino.data.IAdaptable;
import com.hcl.domino.jna.internal.structs.NotesCollectionPositionStruct;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;

/**
 * This structure is used to specify the hierarchical, index position of an item (or category)
 * within a View(collection).
*
* Level = (number of levels in tumbler - 1)
*
* Tumbler is an array of ordinal ranks within the view; with the first (0) entry referring to the top level.
*
* For example, consider the following non-Domino Outline Scheme :
*
* I. First Main Category
*     A. First sub-category under I
*     B. Second sub-category under I
* II. Second Main Category
*     A. First sub-category under II
*         1. First item under II.A
*         2. Second item under II.A
*     B. Second sub-category under II
*     C. Third sub-category under II
* III. Third Main Category
*
* With this example, [2; II.A.2] refers to the "Second item under II.A."
* Similarly, [0; III] refers to the "Third Main Category."
*
* Finally, it should be noted that [2; I.B.1], [1; I.C], and [3; II.A.1] are all NOT valid positions.
*
* [2; I.B.1] because the "Second sub-category under I" has no items.
* [1; I.C] because there is no "Third sub-category under I", and
* [3; II.A.1] because the value of Level (3) shows four levels should be represented * in the Tumbler and there are only three. * * @author Karsten Lehmann */ public class JNADominoCollectionPosition implements IAdaptable { /** # levels -1 in tumbler */ private int level; /** * MINIMUM level that this position is allowed to be nagivated to. This is * useful to navigate a subtree using all navigator codes. This field is * IGNORED unless the NAVIGATE_MINLEVEL flag is enabled (for backward * compatibility) */ private int minLevel; /** * MAXIMUM level that this position is allowed to be nagivated to. This is * useful to navigate a subtree using all navigator codes. This field is * IGNORED unless the NAVIGATE_MAXLEVEL flag is enabled (for backward * compatibility) */ private int maxLevel; /** * Current tumbler (1.2.3, etc)
* C type : DWORD[32] */ private int[] tumbler = new int[32]; private String toString; private NotesCollectionPositionStruct struct; public JNADominoCollectionPosition(IAdaptable adaptable) { NotesCollectionPositionStruct struct = adaptable.getAdapter(NotesCollectionPositionStruct.class); if (struct!=null) { this.struct = struct; this.level = struct.Level; this.minLevel = struct.MinLevel; this.maxLevel = struct.MaxLevel; this.tumbler = struct.Tumbler; return; } Pointer p = adaptable.getAdapter(Pointer.class); if (p!=null) { this.struct = NotesCollectionPositionStruct.newInstance(p); this.level = this.struct.Level; this.minLevel = this.struct.MinLevel; this.maxLevel = this.struct.MaxLevel; this.tumbler = this.struct.Tumbler; return; } throw new IllegalArgumentException("Constructor argument cannot provide a supported datatype"); } /** * Creates a new instance * * @param tumbler array with position information [index level0, index level1, ...], e.g. [1,2,3], up to 32 entries */ public JNADominoCollectionPosition(int[] tumbler) { this(computeLevel(tumbler), 0, 0, tumbler); } private static int computeLevel(int[] tumbler) { if (tumbler[0]==0) { return 0; } for (int i=1; i32) { throw new IllegalArgumentException(MessageFormat.format("Tumbler array exceeds the maximum size ({0} > 32)", tumbler.length)); } this.tumbler = new int[32]; for (int i=0; i *
* Please note that we also support an advanced syntax in contrast to IBM's API in order * to specify the min/max level parameters: "1.2.3|0-2" for minlevel=0, maxlevel=2. These * levels can be used to limit reading entries in a categorized view to specified depths. * * @param posStr position string */ public JNADominoCollectionPosition(String posStr) { int iPos = posStr.indexOf("|"); //$NON-NLS-1$ if (iPos!=-1) { //optional addition to the classic position string: |minlevel-maxlevel String minMaxStr = posStr.substring(iPos+1); posStr = posStr.substring(0, iPos); iPos = minMaxStr.indexOf("-"); //$NON-NLS-1$ if (iPos!=-1) { minLevel = Byte.parseByte(minMaxStr.substring(0, iPos)); maxLevel = Byte.parseByte(minMaxStr.substring(iPos+1)); } } tumbler = new int[32]; if (posStr==null || posStr.length()==0 || "0".equals(posStr)) { //$NON-NLS-1$ level = 0; tumbler[0] = 0; this.toString = "0"; //$NON-NLS-1$ } else { String[] parts = posStr.split("\\."); //$NON-NLS-1$ level = (short) (parts.length-1); for (int i=0; i T getAdapter(Class clazz) { if (clazz == NotesCollectionPositionStruct.class || clazz == Structure.class) { if (this.struct==null) { this.struct = NotesCollectionPositionStruct.newInstance(); this.struct.Level = (short) (this.level & 0xffff); this.struct.MinLevel = (byte) (this.minLevel & 0xff); this.struct.MaxLevel = (byte) (this.maxLevel & 0xff); this.struct.Tumbler = this.tumbler.clone(); this.struct.write(); } return (T) this.struct; } return null; } /** * # levels -1 in tumbler * * @return levels */ public int getLevel() { if (this.struct!=null) { //get current struct value, is changed by NIFReadEntries this.level = this.struct.Level & 0xffff; } return this.level; } /** * MINIMUM level that this position is allowed to be nagivated to. This is * useful to navigate a subtree using all navigator codes. This field is * IGNORED unless the NAVIGATE_MINLEVEL flag is enabled (for backward * compatibility) * * @return min level */ public int getMinLevel() { if (this.struct!=null) { //get current struct value, is changed by NIFReadEntries this.minLevel = (this.struct.MinLevel & 0xffff); } return this.minLevel; } /** * Sets the MINIMUM level that this position is allowed to be nagivated to. This is * useful to navigate a subtree using all navigator codes. This field is * IGNORED unless the NAVIGATE_MINLEVEL flag is enabled (for backward * compatibility) * * @param level min level */ public void setMinLevel(int level) { this.minLevel = level; if (this.struct!=null) { this.struct.MinLevel = (byte) (level & 0xff); this.struct.write(); } } /** * MAXIMUM level that this position is allowed to be navigated to. This is * useful to navigate a subtree using all navigator codes. * * @return max level */ public int getMaxLevel() { if (this.struct!=null) { //get current struct value, is changed by NIFReadEntries this.maxLevel = (this.struct.MaxLevel & 0xffff); } return this.maxLevel; } /** * Sets the MAXIMUM level that this position is allowed to be navigated to. This is * useful to navigate a subtree using all navigator codes. * * @param level max level */ public void setMaxLevel(int level) { this.maxLevel = level; if (this.struct!=null) { this.struct.MaxLevel = (byte) (level & 0xff); this.struct.write(); } } /** * Returns the index position at each view level * * @param level 0 for first level * @return position starting with 1 if not restricted by reader fields */ public int getTumbler(int level) { if (this.struct!=null) { //get current struct value, is changed by NIFReadEntries this.tumbler = this.struct.Tumbler; } return this.tumbler[level]; } /** * Converts the position object to a position string like "1.2.3".
*
* Please note that we also support an advanced syntax in contrast to IBM's API in order * to specify the min/max level parameters: "1.2.3|0-2" for minlevel=0, maxlevel=2. These * levels can be used to limit reading entries in a categorized view to specified depths.
*
* This method will returns a string with the advanced syntax if MinLevel or MaxLevel is not 0. * * @return position string */ @Override public String toString() { boolean recalc; //cache if cached value needs to be recalculated if (this.toString==null) { recalc = true; } else if (this.struct!=null && (this.level != this.struct.Level || this.minLevel != this.struct.MinLevel || this.maxLevel != this.struct.MaxLevel || !Arrays.equals(this.tumbler, this.struct.Tumbler))) { recalc = true; } else { recalc = false; } if (recalc) { int level = this.getLevel(); int minLevel = this.getMinLevel(); int maxLevel = this.getMaxLevel(); StringBuilder sb = new StringBuilder(); for (int i=0; i<=level; i++) { if (sb.length() > 0) { sb.append('.'); } sb.append(this.getTumbler(i)); } if (minLevel!=0 || maxLevel!=0) { sb.append("|").append(minLevel).append("-").append(maxLevel); //$NON-NLS-1$ //$NON-NLS-2$ } toString = sb.toString(); } return toString; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy