001 package com.saelist.stx.operators;
002
003 import java.util.*;
004 import com.saelist.stx.parser.*;
005 import com.saelist.stx.*;
006
007
008 /** See {@link com.saelist.stx.Operator} for general description of the Operator
009 * concept in stx. YankOperator replaces the text of the pair with the
010 * concatenated text of its descendants. The text is indented with two
011 * spaces for each generation.
012 * <pre>
013 *
014 * text
015 * '
016 * this is
017 * a message composed of
018 * multiple lines.
019 *
020 *
021 *</pre>
022 * into
023 * <pre>
024 *
025 * text
026 * this is\na message composed of\n multiple lines.
027 *
028 *</pre>
029 */
030 public class YankOperator extends AbstractOperator {
031
032 private Set removed = new HashSet();
033 private String pattern;
034
035 /** Caches the pattern and replacement settings in variables.
036 */
037 public void init() {
038 pattern = config.eval1("pattern");
039 logger.info("init(): pattern=" + pattern);
040 removed.clear();
041 }
042
043 /** Replaces the text of pairs that match pattern with the concatenated text
044 * of its descendands and removes the descendants.
045 */
046 public void operate(Pair pair) {
047 if(! pair.getText().matches(pattern) || removed.contains(pair))
048 return;
049 pair.setText(subText(pair, ""));
050 }
051
052 /** Recursively accumulates the text of the descendants of <code>pair</code>
053 * while removing them from their parents.
054 */
055 public String subText(Pair pair, String indent) {
056 logger.debug("subText(): pair=" + pair + "', indent='" + indent + "'.");
057 StringBuffer text = new StringBuffer();
058 for(Iterator children = pair.getPairs(); children.hasNext(); ) {
059 Pair child = (Pair) children.next();
060 text.append(indent + child.getText() + "\n" + subText(child, indent + " "));
061 pair.remove(child);
062 removed.add(child);
063 }
064 return text.toString();
065 }
066
067
068 }