Update years in copyright line
[Sone.git] / src / main / java / net / pterodactylus / sone / text / PartContainer.java
index d52658e..75714f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - PartContainer.java - Copyright © 2010 David Roden
+ * Sone - PartContainer.java - Copyright © 2010–2015 David Roden
  *
  * 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
 
 package net.pterodactylus.sone.text;
 
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Deque;
+import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 /**
  * Part implementation that can contain an arbitrary amount of other parts.
@@ -30,7 +31,7 @@ import java.util.List;
  *
  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
  */
-public class PartContainer implements Part {
+public class PartContainer implements Part, Iterable<Part> {
 
        /** The parts to render. */
        private final List<Part> parts = new ArrayList<Part>();
@@ -87,28 +88,78 @@ public class PartContainer implements Part {
         * {@inheritDoc}
         */
        @Override
-       public void render(Writer writer) throws IOException {
+       public String getText() {
+               StringBuilder partText = new StringBuilder();
                for (Part part : parts) {
-                       part.render(writer);
+                       partText.append(part.getText());
                }
+               return partText.toString();
        }
 
        //
-       // OBJECT METHODS
+       // ITERABLE METHODS
        //
 
        /**
         * {@inheritDoc}
         */
        @Override
-       public String toString() {
-               StringWriter stringWriter = new StringWriter();
-               try {
-                       render(stringWriter);
-               } catch (IOException ioe1) {
-                       /* should never throw, ignore. */
-               }
-               return stringWriter.toString();
+       @SuppressWarnings("synthetic-access")
+       public Iterator<Part> iterator() {
+               return new Iterator<Part>() {
+
+                       private Deque<Iterator<Part>> partStack = new ArrayDeque<Iterator<Part>>();
+                       private Part nextPart;
+                       private boolean foundNextPart;
+                       private boolean noNextPart;
+
+                       {
+                               partStack.push(parts.iterator());
+                       }
+
+                       private void findNext() {
+                               if (foundNextPart) {
+                                       return;
+                               }
+                               noNextPart = true;
+                               while (!partStack.isEmpty()) {
+                                       Iterator<Part> parts = partStack.pop();
+                                       if (parts.hasNext()) {
+                                               nextPart = parts.next();
+                                               partStack.push(parts);
+                                               if (nextPart instanceof PartContainer) {
+                                                       partStack.push(((PartContainer) nextPart).iterator());
+                                               } else {
+                                                       noNextPart = false;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               foundNextPart = true;
+                       }
+
+                       @Override
+                       public boolean hasNext() {
+                               findNext();
+                               return !noNextPart;
+                       }
+
+                       @Override
+                       public Part next() {
+                               findNext();
+                               if (noNextPart) {
+                                       throw new NoSuchElementException();
+                               }
+                               foundNextPart = false;
+                               return nextPart;
+                       }
+
+                       @Override
+                       public void remove() {
+                               /* ignore. */
+                       }
+
+               };
        }
 
 }