001    // This file is part of AceWiki.
002    // Copyright 2008-2012, AceWiki developers.
003    // 
004    // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
005    // Lesser General Public License as published by the Free Software Foundation, either version 3 of
006    // the License, or (at your option) any later version.
007    // 
008    // AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009    // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
010    // Lesser General Public License for more details.
011    // 
012    // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
013    // not, see http://www.gnu.org/licenses/.
014    
015    package ch.uzh.ifi.attempto.base;
016    
017    import java.util.ArrayList;
018    import java.util.List;
019    
020    /**
021     * This class represents a text container that stores a sequence of text elements that represent a
022     * (partial) text or sentence.
023     * 
024     * @author Tobias Kuhn
025     */
026    public class TextContainer {
027            
028            private List<TextElement> elements = new ArrayList<TextElement>();
029            private TextOperator textOperator = new DefaultTextOperator();
030            
031            /**
032             * Creates a new text container.
033             */
034            public TextContainer() {
035            }
036            
037            /**
038             * Creates a new text container using the given text operator.
039             * 
040             * @param textOperator The text operator to be used.
041             */
042            public TextContainer(TextOperator textOperator) {
043                    setTextOperator(textOperator);
044            }
045            
046            /**
047             * Creates a new text container that contains the given text elements.
048             * 
049             * @param elements The elements to be added to the new text container.
050             */
051            public TextContainer(TextElement... elements) {
052                    for (TextElement el : elements) {
053                            addElement(el);
054                    }
055            }
056            
057            /**
058             * Creates a new text container that uses the given text operator and that contains the
059             * given text elements.
060             * 
061             * @param textOperator The text operator to be used.
062             * @param elements The elements to be added to the new text container.
063             */
064            public TextContainer(TextOperator textOperator, TextElement... elements) {
065                    for (TextElement el : elements) {
066                            addElement(el);
067                    }
068                    setTextOperator(textOperator);
069            }
070            
071            /**
072             * Returns the number of text elements of this text container.
073             * 
074             * @return The number of text elements.
075             */
076            public int getTextElementsCount() {
077                    return elements.size();
078            }
079            
080            /**
081             * Returns the text element with the given index.
082             * @param index The index of the text element to be returned.
083             * @return The text element.
084             */
085            public TextElement getTextElement(int index) {
086                    return elements.get(index);
087            }
088            
089            /**
090             * Returns the sequence of text elements.
091             * 
092             * @return A list containing the text elements.
093             */
094            public List<TextElement> getTextElements() {
095                    return new ArrayList<TextElement>(elements);
096            }
097            
098            /**
099             * Sets the text elements.
100             * @param elements A list of text elements.
101             */
102            public void setTextElements(List<TextElement> elements) {
103                    this.elements = new ArrayList<TextElement>(elements);
104            }
105            
106            /**
107             * Adds the text element to the end of the sequence.
108             * 
109             * @param el The text element to be added.
110             */
111            public void addElement(TextElement el) {
112                    el.setTextContainer(this);
113                    elements.add(el);
114            }
115            
116            /**
117             * Removes all text elements.
118             */
119            public void removeAllElements() {
120                    for (TextElement te : elements) te.removeTextContainer();
121                    elements.clear();
122            }
123            
124            /**
125             * Removes the last text element of the sequence if it is not empty.
126             */
127            public void removeLastElement() {
128                    if (elements.size() > 0) {
129                            int last = elements.size() - 1;
130                            elements.get(last).removeTextContainer();
131                            elements.remove(last);
132                    }
133            }
134            
135            /**
136             * Returns the text that is represented by the sequence of text element as a string.
137             * 
138             * @return The text.
139             */
140            public String getText() {
141                    String text = "";
142                    TextElement prev = null;
143                    for (TextElement e : elements) {
144                            if (prev != null) {
145                                    text += textOperator.getGlue(prev, e) + e.getText();
146                            } else {
147                                    text += e.getText();
148                            }
149                            prev = e;
150                    }
151                    return text;
152            }
153            
154            /**
155             * Sets the text operator.
156             * 
157             * @param textOperator The new text operator.
158             */
159            public void setTextOperator(TextOperator textOperator) {
160                    this.textOperator = textOperator;
161            }
162            
163            /**
164             * Returns the text operator of this text container.
165             * 
166             * @return The text operator.
167             */
168            public TextOperator getTextOperator() {
169                    return textOperator;
170            }
171            
172            /**
173             * Returns the position of the given text element within this text container or -1 if the
174             * text element is not contained by this text container. Note that the elements are checked for
175             * identity, not for equality.
176             * 
177             * @param textElement The text element.
178             * @return The index of the text element.
179             */
180            public int getIndexOf(TextElement textElement) {
181                    // indexOf(...) does not work, because it uses the equals-method, but we need to check for
182                    // identity:
183                    int index = -1;
184                    for (int i = 0 ; i < elements.size() ; i++) {
185                            if (elements.get(i) == textElement) {
186                                    index = i;
187                                    break;
188                            }
189                    }
190                    return index;
191            }
192            
193            String getTextElementText(TextElement te) {
194                    if (textOperator == null) {
195                            return te.getOriginalText();
196                    } else {
197                            String preceding = null;
198                            String following = null;
199                            int pos = getIndexOf(te);
200                            if (pos > 0) {
201                                    preceding = elements.get(pos-1).getOriginalText();
202                            }
203                            if (pos < elements.size()-1) {
204                                    following = elements.get(pos+1).getOriginalText();
205                            }
206                            return textOperator.getTextInContext(te, preceding, following);
207                    }
208            }
209            
210            /**
211             * Returns a new text container containing a subsequence of the elements of this text
212             * container.
213             * 
214             * @param startPos The position of the first element.
215             * @param endPos The position after the last element.
216             * @return The new text container.
217             */
218            public TextContainer getSubTextContainer(int startPos, int endPos) {
219                    TextContainer subtc = new TextContainer(textOperator);
220                    for (int i = startPos; i < endPos; i++) {
221                            subtc.addElement(elements.get(i));
222                    }
223                    return subtc;
224            }
225            
226            public TextContainer clone() {
227                    TextContainer clone = new TextContainer();
228                    clone.elements = new ArrayList<TextElement>(this.elements);
229                    clone.textOperator = this.textOperator;
230                    return clone;
231            }
232    
233    }