content: // This file is part of AceWiki.
  // Copyright 2008-2013, AceWiki developers.
  // 
  // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
  // Lesser General Public License as published by the Free Software Foundation, either version 3 of
  // the License, or (at your option) any later version.
  // 
  // AceWiki 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
  // Lesser General Public License for more details.
  // 
  // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
  // not, see http://www.gnu.org/licenses/.
  
  package ch.uzh.ifi.attempto.base;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * This class represents a text container that stores a sequence of text elements that represent a
   * (partial) text or sentence.
   * 
   * @author Tobias Kuhn
   */
  public class TextContainer {
  	
  	private List<TextElement> elements = new ArrayList<TextElement>();
  	private TextOperator textOperator = new DefaultTextOperator();
  	
  	/**
  	 * Creates a new text container.
  	 */
  	public TextContainer() {
  	}
  	
  	/**
  	 * Creates a new text container using the given text operator.
  	 * 
  	 * @param textOperator The text operator to be used.
  	 */
  	public TextContainer(TextOperator textOperator) {
  		setTextOperator(textOperator);
  	}
  	
  	/**
  	 * Creates a new text container that contains the given text elements.
  	 * 
  	 * @param elements The elements to be added to the new text container.
  	 */
  	public TextContainer(TextElement... elements) {
  		for (TextElement el : elements) {
  			addElement(el);
  		}
  	}
  	
  	/**
  	 * Creates a new text container that uses the given text operator and that contains the
  	 * given text elements.
  	 * 
  	 * @param textOperator The text operator to be used.
  	 * @param elements The elements to be added to the new text container.
  	 */
  	public TextContainer(TextOperator textOperator, TextElement... elements) {
  		for (TextElement el : elements) {
  			addElement(el);
  		}
  		setTextOperator(textOperator);
  	}
  	
  	/**
  	 * Returns the number of text elements of this text container.
  	 * 
  	 * @return The number of text elements.
  	 */
  	public int getTextElementsCount() {
  		return elements.size();
  	}
  	
  	/**
  	 * Returns the text element with the given index.
  	 * @param index The index of the text element to be returned.
  	 * @return The text element.
  	 */
  	public TextElement getTextElement(int index) {
  		return elements.get(index);
  	}
  	
  	/**
  	 * Returns the sequence of text elements.
  	 * 
  	 * @return A list containing the text elements.
  	 */
  	public List<TextElement> getTextElements() {
  		return new ArrayList<TextElement>(elements);
  	}
  	
  	/**
  	 * Sets the text elements.
  	 * @param elements A list of text elements.
  	 */
  	public void setTextElements(List<TextElement> elements) {
  		this.elements = new ArrayList<TextElement>(elements);
  	}
  	
  	/**
  	 * Adds the text element to the end of the sequence.
  	 * 
  	 * @param el The text element to be added.
  	 */
  	public void addElement(TextElement el) {
  		el.setTextContainer(this);
  		elements.add(el);
  	}
  	
  	/**
  	 * Removes all text elements.
  	 */
  	public void removeAllElements() {
  		for (TextElement te : elements) te.removeTextContainer();
  		elements.clear();
  	}
  	
  	/**
  	 * Removes the last text element of the sequence if it is not empty.
  	 */
  	public void removeLastElement() {
  		if (elements.size() > 0) {
  			int last = elements.size() - 1;
  			elements.get(last).removeTextContainer();
  			elements.remove(last);
  		}
  	}
  	
  	/**
  	 * Returns the text that is represented by the sequence of text element as a string.
  	 * 
  	 * @return The text.
  	 */
  	public String getText() {
  		String text = "";
  		TextElement prev = null;
  		for (TextElement e : elements) {
  			if (prev != null) {
  				text += textOperator.getGlue(prev, e) + e.getText();
  			} else {
  				text += e.getText();
  			}
  			prev = e;
  		}
  		return text;
  	}
  
  	/**
  	 * Returns the tokens as a list of strings.
  	 * 
  	 * @return The tokens.
  	 */
  	public List<String> getTokens() {
  		List<String> tokens = new ArrayList<>();
  		for (TextElement te : getTextElements()) {
  			tokens.add(te.getOriginalText());
  		}
  		return tokens;
  	}
  
  	/**
  	 * Sets the text operator.
  	 * 
  	 * @param textOperator The new text operator.
  	 */
  	public void setTextOperator(TextOperator textOperator) {
  		this.textOperator = textOperator;
  	}
  	
  	/**
  	 * Returns the text operator of this text container.
  	 * 
  	 * @return The text operator.
  	 */
  	public TextOperator getTextOperator() {
  		return textOperator;
  	}
  	
  	/**
  	 * Returns the position of the given text element within this text container or -1 if the
  	 * text element is not contained by this text container. Note that the elements are checked for
  	 * identity, not for equality.
  	 * 
  	 * @param textElement The text element.
  	 * @return The index of the text element.
  	 */
  	public int getIndexOf(TextElement textElement) {
  		// indexOf(...) does not work, because it uses the equals-method, but we need to check for
  		// identity:
  		int index = -1;
  		for (int i = 0 ; i < elements.size() ; i++) {
  			if (elements.get(i) == textElement) {
  				index = i;
  				break;
  			}
  		}
  		return index;
  	}
  	
  	String getTextElementText(TextElement te) {
  		if (textOperator == null) {
  			return te.getOriginalText();
  		} else {
  			String preceding = null;
  			String following = null;
  			int pos = getIndexOf(te);
  			if (pos > 0) {
  				preceding = elements.get(pos-1).getOriginalText();
  			}
  			if (pos < elements.size()-1) {
  				following = elements.get(pos+1).getOriginalText();
  			}
  			return textOperator.getTextInContext(te, preceding, following);
  		}
  	}
  	
  	/**
  	 * Returns a new text container containing a subsequence of the elements of this text
  	 * container.
  	 * 
  	 * @param startPos The position of the first element.
  	 * @param endPos The position after the last element.
  	 * @return The new text container.
  	 */
  	public TextContainer getSubTextContainer(int startPos, int endPos) {
  		TextContainer subtc = new TextContainer(textOperator);
  		for (int i = startPos; i < endPos; i++) {
  			subtc.addElement(elements.get(i));
  		}
  		return subtc;
  	}
  	
  	public TextContainer clone() {
  		TextContainer clone = new TextContainer();
  		clone.elements = new ArrayList<TextElement>(this.elements);
  		clone.textOperator = this.textOperator;
  		return clone;
  	}
  
  }
  