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

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

The 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 static java.text.MessageFormat.format;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.TreeMap;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import com.hcl.domino.DominoException;
import com.hcl.domino.data.CollectionEntry;
import com.hcl.domino.data.CollectionSearchQuery.CollectionEntryProcessor;
import com.hcl.domino.data.CollectionSearchQuery.SelectedEntries;
import com.hcl.domino.data.Database;
import com.hcl.domino.data.Database.Action;
import com.hcl.domino.exception.IncompatibleImplementationException;
import com.hcl.domino.data.DbQueryResult;
import com.hcl.domino.data.Document;
import com.hcl.domino.data.DominoCollection;
import com.hcl.domino.data.IDTable;
import com.hcl.domino.data.Navigate;
import com.hcl.domino.jna.data.DocumentSummaryIterator.DocumentData;
import com.hcl.domino.jna.internal.search.NotesSearch.JNASearchMatch;
import com.hcl.domino.misc.Loop;

public abstract class DbQueryResultUtil> implements DbQueryResult {
	private Map m_computeValues;
	private JNADominoCollection m_sortCollection;
	private Integer m_total;
	
	public DbQueryResultUtil() {
		m_computeValues = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
	}
	
	@Override
	public abstract Database getParentDatabase();
	
	@Override
	public abstract Optional getNoteIds();

	@SuppressWarnings("unchecked")
	@Override
	public QUERYTYPE computeValues(Map itemsAndFormulas) {
		m_computeValues.putAll(itemsAndFormulas);
		return (QUERYTYPE) this;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public QUERYTYPE computeValues(String... itemsAndFormulas) {
		if (itemsAndFormulas==null || itemsAndFormulas.length==0) {
			return (QUERYTYPE) this;
		}
		
		if ((itemsAndFormulas.length % 2)==1) {
			throw new IllegalArgumentException(format("List of item/formulas must have an even number of entries: {0}", Arrays.toString(itemsAndFormulas)));
		}
		
		for (int i=0; i getDocuments() {
		Iterator idsIt;
		
		if (m_sortCollection!=null) {
			//produce note id iterator in collection order
			idsIt = collectIds(0, Integer.MAX_VALUE).iterator();
		}
		else {
			idsIt = getNoteIds().get().iterator();
		}
		
		Database db = getParentDatabase();
		
		Spliterator noteIdsSplitIt = Spliterators.spliteratorUnknownSize(idsIt, 0);
		Stream noteIdStream = StreamSupport.stream(noteIdsSplitIt, false);
		
		return noteIdStream
			.map(db::getDocumentById)
			.filter(Optional::isPresent)
			.map(Optional::get);
	}

	@Override
	public  T build(int skip, int count, CollectionEntryProcessor processor) {
		IDTable ids = getNoteIds().get();
		JNADatabase parentDb = (JNADatabase) getParentDatabase();

		if (m_sortCollection!=null) {
			T result = processor.start();

			if (count>0) {
				//select note ids in view and find out which of them are in the requested page (skip, count)
				Set idsInCollectionOrder = m_sortCollection
						.query()
						.select(
								SelectedEntries
								.deselectAll()
								.select(ids)
								)
						.direction(Navigate.NEXT_SELECTED)
						.collectIds(skip, count);

				int pageSize = Math.min(count, 20000);

				DocumentSummaryIterator summaryIterator = new DocumentSummaryIterator(parentDb,
						pageSize, idsInCollectionOrder.iterator(),
						skip, count, m_computeValues);
				
				while (summaryIterator.hasNext()) {
					DocumentData currDocData = summaryIterator.next();
					
					JNADocSummaryCollectionEntry entry = toCollectionEntry(parentDb, m_sortCollection, currDocData);
					
					Action action = processor.entryRead(result, entry);
					if (action == Action.Stop) {
						break;
					}
				}
			}
			
			result = processor.end(result);
			return result;
		}
		else {
			JNADominoCollection defaultCollection = (JNADominoCollection) parentDb.openDefaultCollection().orElseThrow(
				() -> new DominoException(format("No default collection found in database {0}!!{1}", parentDb.getServer(), parentDb.getRelativeFilePath()))
			);
			
			T result = processor.start();
			
			if (count>0) {
				Iterator noteIdIt = ids.iterator();

				int pageSize = Math.min(count, 20000);

				DocumentSummaryIterator summaryIterator = new DocumentSummaryIterator(parentDb,
						pageSize, noteIdIt,
						skip, count, m_computeValues);
				
				while (summaryIterator.hasNext()) {
					DocumentData currDocData = summaryIterator.next();
					
					JNADocSummaryCollectionEntry entry = toCollectionEntry(parentDb, defaultCollection, currDocData);
					
					Action action = processor.entryRead(result, entry);
					if (action == Action.Stop) {
						break;
					}
				}
			}

			result = processor.end(result);
			return result;
		}
	}

	private JNADocSummaryCollectionEntry toCollectionEntry(JNADatabase parentDb, JNADominoCollection parentCollection,
			DocumentData currDocData) {
		JNASearchMatch searchMatch = currDocData.getSearchMatch();
		
		TreeMap caseInsensitiveSummaryData = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
		caseInsensitiveSummaryData.putAll(currDocData.getAllSummaryData());
		
		JNADocSummaryCollectionEntry entry = new JNADocSummaryCollectionEntry(parentDb, parentCollection,
				searchMatch.getNoteID(), searchMatch.getUNID(), searchMatch.getSequenceNumber(),
				searchMatch.getSequenceTime(), caseInsensitiveSummaryData);
		
		return entry;
	}
	
	@Override
	public Set collectIds(int skip, int count) {
		if (count==0) {
			return new LinkedHashSet<>();
		}
		
		IDTable ids = getNoteIds().get();

		if (m_sortCollection!=null) {
			//select note ids in view and find out which of them are in the requested page (skip, count)
			Set idsInCollectionOrder = m_sortCollection
					.query()
					.select(
							SelectedEntries
							.deselectAll()
							.select(ids)
							)
					.direction(Navigate.NEXT_SELECTED)
					.collectIds(skip, count);

			return idsInCollectionOrder;
		}
		else {
			LinkedHashSet result = new LinkedHashSet<>();
			int skipped = 0;
			int processed = 0;
			
			Iterator idIt = ids.iterator();
			while (idIt.hasNext()) {
				Integer currNoteId = idIt.next();
				if (skipped < skip) {
					skipped++;
					continue;
				}
				else {
					result.add(currNoteId);
					processed++;
				}
				
				if (processed >= count) {
					break;
				}
			}
			
			return result;
		}
	}

	@Override
	public void collectIds(int skip, int count, Collection idTable) {
		if (count==0) {
			return;
		}
		
		IDTable ids = getNoteIds().get();

		if (m_sortCollection!=null) {
			//select note ids in view and find out which of them are in the requested page (skip, count)
			Set idsInCollectionOrder = m_sortCollection
					.query()
					.select(
							SelectedEntries
							.deselectAll()
							.select(ids)
							)
					.direction(Navigate.NEXT_SELECTED)
					.collectIds(skip, count);

			idTable.addAll(idsInCollectionOrder);
		}
		else {
			int skipped = 0;
			int processed = 0;
			
			Iterator idIt = ids.iterator();
			while (idIt.hasNext()) {
				Integer currNoteId = idIt.next();
				if (skipped < skip) {
					skipped++;
					continue;
				}
				else {
					idTable.add(currNoteId);
					processed++;
				}
				
				if (processed >= count) {
					break;
				}
			}
		}
	}

	@Override
	public List collectEntries(int skip, int count) {
		return build(skip, count, new CollectionEntryProcessor>() {

			@Override
			public List start() {
				return new ArrayList<>();
			}

			@Override
			public Action entryRead(List result, CollectionEntry entry) {
				result.add(entry);
				return Action.Continue;
			}

			@Override
			public List end(List result) {
				return result;
			}
		});
	}

	@Override
	public void collectEntries(int skip, int count, Collection collection) {
		build(skip, count, new CollectionEntryProcessor>() {

			@Override
			public Collection start() {
				return collection;
			}

			@Override
			public Action entryRead(Collection result, CollectionEntry entry) {
				result.add(entry);
				return Action.Continue;
			}

			@Override
			public Collection end(Collection result) {
				return result;
			}
		});
	}

	private static class LoopImpl extends Loop {
		
		public void next() {
			super.setIndex(getIndex()+1);
		}
		
		@Override
		public void setIsLast() {
			super.setIsLast();
		}
	}
	
	@Override
	public void forEachDocument(int skip, int count, BiConsumer consumer) {
		JNADatabase parentDb = (JNADatabase) getParentDatabase();
		IDTable ids = getNoteIds().get();
		LoopImpl loop = new LoopImpl();

		Iterator docIt;

		if (m_sortCollection!=null) {
			//select note ids in view and find out which of them are in the requested page (skip, count)
			Set idsInCollectionOrder = m_sortCollection
					.query()
					.select(
							SelectedEntries
							.deselectAll()
							.select(ids)
							)
					.direction(Navigate.NEXT_SELECTED)
					.collectIds(skip, count);

			docIt = idsInCollectionOrder.stream()
				.map(parentDb::getDocumentById)
				.filter(Optional::isPresent)
				.map(Optional::get)
				.iterator();
		}
		else {
			Set idsInPage = collectIds(skip, count);
			docIt = idsInPage.stream()
				.map(parentDb::getDocumentById)
				.filter(Optional::isPresent)
				.map(Optional::get)
				.iterator();
		}

		while (docIt.hasNext()) {
			Document currDoc = docIt.next();

			if (!docIt.hasNext()) {
				loop.setIsLast();
			}

			consumer.accept(currDoc, loop);

			if (loop.isStopped()) {
				break;
			}

			loop.next();
		}
	}
	
	@Override
	public int size() {
		IDTable ids = getNoteIds().get();
		
		if (m_total==null) {
			if (m_sortCollection!=null) {
				m_total = m_sortCollection
						.query()
						.select(
								SelectedEntries
								.deselectAll()
								.select(ids)
								)
						.direction(Navigate.NEXT_SELECTED)
						.size();
			}
			else {
				m_total = ids.size();
			}
		}
		return m_total;
	}
		
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy