Selection.java
/**
* **********************************************************************
*
* <p>Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to you 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
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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.
*
* <p>**********************************************************************
*/
package org.odftoolkit.odfdom.incubator.search;
import java.util.Hashtable;
import java.util.Vector;
import org.odftoolkit.odfdom.pkg.OdfElement;
/**
* Abstract class Selection describe one of the matched results The selection can be recognized by
* the container mElement, the start mIndex of the text content of this mElement and the text
* content.
*/
public abstract class Selection {
private OdfElement mElement;
private int mIndex;
/**
* get the container mElement of this selection
*
* @return the container mElement
*/
public OdfElement getElement() {
return mElement;
}
/**
* get the start mIndex of the text content of the container mElement this is only meaningful for
* TextSelection. other type Selection will return 0.
*
* @return the start mIndex of the container mElement
*/
public int getIndex() {
return mIndex;
}
/**
* cut the current selection
*
* @throws InvalidNavigationException
*/
public abstract void cut() throws InvalidNavigationException;
/**
* paste the current selection at front of the specified position selection
*
* @param positionitem the position selection
* @throws InvalidNavigationException
*/
public abstract void pasteAtFrontOf(Selection positionitem) throws InvalidNavigationException;
/**
* paste the current selection at end of the specified position selection
*
* @param positionitem the position selection
* @throws InvalidNavigationException
*/
public abstract void pasteAtEndOf(Selection positionitem) throws InvalidNavigationException;
/**
* when a selected item has been delete, the selections after this deleted selection should be
* refresh because these selections mIndex will be changed
*
* @param deleteditem the deleted selection
*/
protected abstract void refreshAfterFrontalDelete(Selection deleteditem);
/**
* when a selected item has been inserted, the selection after the inserted item should be refresh
* because these selections mIndex will be changed
*
* @param inserteditem the inserted selection
*/
protected abstract void refreshAfterFrontalInsert(Selection inserteditem);
/**
* A quick method to update the mIndex of this selection
*
* @param offset the offset that the mIndex should be added
*/
protected abstract void refresh(int offset);
/**
* SelectionManager can manage all the selections that are returned to end users. This
* SelectionManager contains a repository of all selections, and will refresh the status/mIndex of
* selections after certain operation.
*/
static class SelectionManager {
private static Hashtable<OdfElement, Vector<Selection>> repository =
new Hashtable<OdfElement, Vector<Selection>>();
/**
* Register the selection item
*
* @param item the selection item
*/
public static void registerItem(Selection item) {
OdfElement element = item.getElement();
if (repository.containsKey(element)) {
Vector<Selection> selections = repository.get(element);
int i = 0;
while (i < selections.size()) {
if (selections.get(i).getIndex() > item.getIndex()) {
selections.insertElementAt(item, i);
break;
}
i++;
}
if (i == selections.size()) {
selections.add(item);
}
} else {
Vector<Selection> al = new Vector<Selection>();
al.add(item);
repository.put(element, al);
}
}
/**
* Refresh the selections in repository after a item is cut.
*
* @param cutItem the cut item
*/
public static synchronized void refreshAfterCut(Selection cutItem) {
// travase the whole sub tree
OdfElement element = cutItem.getElement();
if (repository.containsKey(element)) {
Vector<Selection> selections = repository.get(element);
for (int i = 0; i < selections.size(); i++) {
if (selections.get(i).getIndex() > cutItem.getIndex()) {
selections.get(i).refreshAfterFrontalDelete(cutItem);
}
}
}
}
/**
* Refresh the selections in repository after a pastedAtFrontOf operation is called.
*
* @param item the pasted item
* @param positionItem the position item
*/
public static synchronized void refreshAfterPasteAtFrontOf(
Selection item, Selection positionItem) {
// travase the whole sub tree
OdfElement element = positionItem.getElement();
if (repository.containsKey(element)) {
Vector<Selection> selections = repository.get(element);
for (int i = 0; i < selections.size(); i++) {
if (selections.get(i).getIndex() >= positionItem.getIndex()) {
selections.get(i).refreshAfterFrontalInsert(item);
}
}
}
}
/**
* Refresh the selections in repository after a pastedAtEndOf operation is called.
*
* @param item the pasted item
* @param positionItem the position item
*/
public static synchronized void refreshAfterPasteAtEndOf(
Selection item, Selection positionItem) {
OdfElement element = positionItem.getElement();
int positionIndex;
if (positionItem instanceof TextSelection) {
positionIndex = positionItem.getIndex() + ((TextSelection) positionItem).getText().length();
} else {
positionIndex = positionItem.getIndex();
}
if (repository.containsKey(element)) {
Vector<Selection> selections = repository.get(element);
for (int i = 0; i < selections.size(); i++) {
if (selections.get(i).getIndex() >= positionIndex) {
selections.get(i).refreshAfterFrontalInsert(item);
}
}
}
}
/**
* Remove the selection from repository.
*
* @param item selection item
*/
public static void unregisterItem(Selection item) {
OdfElement element = item.getElement();
if (repository.containsKey(element)) {
Vector<Selection> selections = repository.get(element);
selections.remove(item);
}
}
/**
* A direct method to update all the selections contained in a mElement after a certain
* position.
*
* @param containerElement the container mElement
* @param offset the offset
* @param positionIndex the mIndex of a certain position
*/
public static synchronized void refresh(
OdfElement containerElement, int offset, int positionIndex) {
if (repository.containsKey(containerElement)) {
Vector<Selection> selections = repository.get(containerElement);
for (int i = 0; i < selections.size(); i++) {
if (selections.get(i).getIndex() >= positionIndex) {
selections.get(i).refresh(offset);
}
}
}
}
private SelectionManager() {}
}
}