package org.crosswire.sword.keys; // Ported from SWORD rev 2658 /****************************************************************************** * listkey - code for base class 'listkey'. listkey is the basis for all * types of keys for indexing into modules * (e.g. verse, word, place, etc.) * * $Id: listkey.h 2645 2011-07-22 11:03:45Z scribe $ * * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society * P. O. Box 2528 * Tempe, AZ 85280-2528 * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation version 2. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * */ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.ArrayList; /** ListKey is the basis for all * types of keys that have lists of specified indexes * (e.g. a list of verses, place, etc.) */ public class ListKey extends SWKey { protected int arrayPos = 0; protected List array = new ArrayList(); public boolean isTraversable() { return true; } public long getIndex() { return arrayPos; } public void setIndex(long index) { setToElement((int)index); } /****************************************************************************** * ListKey Constructor - initializes instance of ListKey * * ENT: ikey - text key */ public ListKey() { this(""); } ListKey(String ikey) { super(ikey); clear(); init(); } public ListKey(ListKey k) { super(k.keytext); arrayPos = k.arrayPos; array = new ArrayList(); for (int i = 0; i < array.size(); i++) array.add(((SWKey)k.array.get(i)).clone()); init(); } protected void init() { // this is a listkey, bound is always set boundSet = true; } public SWKey clone() { return new ListKey(this); } /****************************************************************************** * ListKey::ClearList - Clears out elements of list */ public void clear() { array.clear(); arrayPos = 0; } /****************************************************************************** * ListKey::copyFrom Equates this ListKey to another ListKey object * * ENT: ikey - other ListKey object */ public void copyFrom(ListKey ikey) { clear(); arrayPos = ikey.arrayPos; for (int i = 0; i < ikey.array.size(); ++i) { array.add(((SWKey)ikey.array.get(i)).clone()); } setToElement(0); } /****************************************************************************** * ListKey::add - Adds an element to the list */ public void add(SWKey ikey) { array.add(ikey.clone()); setToElement(array.size()-1); } /****************************************************************************** * ListKey::setPosition(SW_POSITION) - Positions this key * * ENT: p - position * * RET: *this */ public void setPosition(int p) { switch (p) { case TOP: setToElement(0, p); break; case BOTTOM: setToElement(array.size()-1, p); break; } } /****************************************************************************** * ListKey::increment - Increments a number of elements */ public void increment() { increment(1); } public void increment(int step) { if (step < 0) { decrement(step*-1); return; } popError(); // clear error for(; step != 0 && popError() == 0; --step) { if (arrayPos < array.size() && array.size() > 0) { if (array.get(arrayPos).isBoundSet()) { array.get(arrayPos).increment(); } if ((array.get(arrayPos).popError() != 0) || (!array.get(arrayPos).isBoundSet())) { setToElement(arrayPos+1); } else super.setText(array.get(arrayPos).getText()); } else error = KEYERR_OUTOFBOUNDS; } } /****************************************************************************** * ListKey::decrement - Decrements a number of elements */ public void decrement() { decrement(1); } public void decrement(int step) { if (step < 0) { increment(step*-1); return; } popError(); // clear error for(; step != 0 && popError() == 0; --step) { if (arrayPos > -1 && array.size() > 0) { if (array.get(arrayPos).isBoundSet()) { array.get(arrayPos).decrement(); } if ((array.get(arrayPos).popError() != 0) || (!array.get(arrayPos).isBoundSet())) { setToElement(arrayPos-1, BOTTOM); } else super.setText(array.get(arrayPos).getText()); } else error = KEYERR_OUTOFBOUNDS; } } /****************************************************************************** * ListKey::Count - Returns number of elements in list */ public int getCount() { return array.size(); } /****************************************************************************** * ListKey::setToElement - Sets key to element number * * ENT: ielement - element number to set to * * RET: error status */ public char setToElement(int ielement) { return setToElement(ielement, TOP); } public char setToElement(int ielement, int pos) { arrayPos = ielement; if (arrayPos >= array.size()) { arrayPos = (array.size()>0)?array.size() - 1:0; error = KEYERR_OUTOFBOUNDS; } else { if (arrayPos < 0) { arrayPos = 0; error = KEYERR_OUTOFBOUNDS; } else { error = 0; } } if (array.size() > 0) { if (array.get(arrayPos).isBoundSet()) { array.get(arrayPos).setPosition(pos); } super.setText(array.get(arrayPos).getText()); } else super.setText(""); return error; } /****************************************************************************** * ListKey::getElement - Gets a key element number * * ENT: pos - element number to get (or default current) * * RET: Key or null on error */ public SWKey getElement() { return getElement(-1); } public SWKey getElement(int pos) { if (pos < 0) pos = arrayPos; if (pos >= array.size()) error = KEYERR_OUTOFBOUNDS; return (error!=0) ? null:(SWKey)array.get(pos); } /****************************************************************************** * ListKey::Remove - Removes current element from list */ public void remove() { if ((arrayPos > -1) && (arrayPos < array.size())) { array.remove(arrayPos); setToElement((arrayPos > 0) ? arrayPos-1 : 0); } } /****************************************************************************** * ListKey::getRangeText - returns parsable range text for this key */ public String getRangeText() { StringBuffer buf = new StringBuffer(); for (int i = 0; i < array.size(); ++i) { buf.append(array.get(i).getRangeText()); if (i < array.size()-1) { buf.append("; "); } } rangeText = buf.toString(); return rangeText; } /****************************************************************************** * ListKey::getRangeText - returns parsable range text for this key */ public void mergeContiguousElements() { List newArray = new ArrayList(); VerseKey lastVerseKey = null; for (int i = 0; i < array.size(); ++i) { if (array.get(i) instanceof VerseKey) { VerseKey v = (VerseKey)array.get(i); if (lastVerseKey != null && v.getVerse() > 0 && v.getChapter() > 0) { if (!lastVerseKey.isBoundSet()) { lastVerseKey.setUpperBound(lastVerseKey); lastVerseKey.setLowerBound(lastVerseKey); } lastVerseKey.setPosition(VerseKey.BOTTOM); VerseKey lowerBound = (v.isBoundSet()) ? (VerseKey)v.getLowerBound().clone() : (VerseKey)v.clone(); lowerBound.decrement(); if (lowerBound.compareTo(lastVerseKey)<=0) { lowerBound.increment(); lastVerseKey.setPosition(VerseKey.TOP); if (lowerBound.compareTo(lastVerseKey)>=0) { // start of key is within or adjacent to previous key VerseKey upperBound = (v.isBoundSet()) ? (VerseKey)v.getUpperBound().clone() : (VerseKey)v.clone(); if (upperBound.compareTo(lastVerseKey) > 0) { lastVerseKey.setUpperBound(upperBound); } continue; } } } lastVerseKey = v; } else lastVerseKey = null; newArray.add(array.get(i)); } array = newArray; } /****************************************************************************** * ListKey::getRangeText - returns parsable range text for this key */ public String getShortRangeText() { StringBuffer buf = new StringBuffer(); for (int i = 0; i < array.size()-1; ++i) { if (array.get(i) instanceof VerseKey) { VerseKey v = (VerseKey)array.get(i); if (v.isBoundSet()) { v.setPosition(VerseKey.TOP); // /* if (v.getChapter() == 1 && v.getVerse() == 1) { array.set(i, array.get(array.size()-1)); array.set(array.size()-1, v); break; } */ // } } } for (int i = 0; i < array.size(); ++i) { buf.append(array.get(i).getShortRangeText()); if (i < array.size()-1) { buf.append("; "); } } rangeText = buf.toString(); return rangeText; } /****************************************************************************** * ListKey::getOSISRefRangeText - returns parsable range text for this key */ public String getOSISRefRangeText() { StringBuffer buf = new StringBuffer(); for (int i = 0; i < array.size(); ++i) { buf.append(array.get(i).getOSISRefRangeText()); if (i < array.size()-1) { buf.append(";"); } } rangeText = buf.toString(); return rangeText; } /****************************************************************************** * ListKey::getText - returns text key if (const char *) cast is requested */ public String getText() { int pos = arrayPos; SWKey key = (pos >= array.size() || array.size() == 0) ? null:array.get(pos); return (key != null) ? key.getText() : keytext; } public String getShortText() { int pos = arrayPos; SWKey key = (pos >= array.size() || array.size() == 0) ? null:array.get(pos); return (key != null) ? key.getShortText() : keytext; } public void setText(String ikey) { // at least try to set the current element to this text for (arrayPos = 0; arrayPos < array.size(); ++arrayPos) { SWKey key = array.get(arrayPos); if (key != null) { if (key.isTraversable() && key.isBoundSet()) { key.setText(ikey); if (key.popError() == 0) break; } else { if (key.getText().equals(ikey)) break; } } } if (arrayPos >= array.size()) { error = KEYERR_OUTOFBOUNDS; arrayPos = array.size()-1; } super.setText(ikey); } public boolean contains(SWKey other) { positionFrom(other); return popError() == 0; } public void sort() { Collections.sort(array); } };