package com.opensymphony.module.sitemesh; import java.io.IOException; import java.io.Writer; import java.util.*; /** * The default implementation of sitemesh buffer */ public class DefaultSitemeshBuffer implements SitemeshBuffer { private final char[] buffer; private final int length; private final TreeMap<Integer, SitemeshBufferFragment> bufferFragments; public DefaultSitemeshBuffer(char[] buffer) { this(buffer, buffer.length); } public DefaultSitemeshBuffer(char[] buffer, int length) { this(buffer, length, new TreeMap<Integer, SitemeshBufferFragment>()); } public DefaultSitemeshBuffer(char[] buffer, int length, TreeMap<Integer, SitemeshBufferFragment> bufferFragments) { this.buffer = buffer; this.length = length; this.bufferFragments = bufferFragments; } public void writeTo(Writer writer, int start, int length) throws IOException { int pos = start; for (Map.Entry<Integer, SitemeshBufferFragment> entry : bufferFragments.entrySet()) { int fragmentPosition = entry.getKey(); if (fragmentPosition < pos) { continue; } if (fragmentPosition > start + length) { break; } // Write the buffer up to the fragment writer.write(buffer, pos, fragmentPosition - pos); // Write the fragment entry.getValue().writeTo(writer); // increment pos pos = fragmentPosition; } // Write out the remaining buffer if (pos < start + length) { writer.write(buffer, pos, (start + length) - pos); } } public int getTotalLength() { return getTotalLength(0, length); } public int getTotalLength(int start, int length) { int total = length; for (Map.Entry<Integer, SitemeshBufferFragment> entry : bufferFragments.entrySet()) { int fragmentPosition = entry.getKey(); if (fragmentPosition < start) { continue; } if (fragmentPosition > start + length) { break; } total += entry.getValue().getTotalLength(); } return total; } public int getBufferLength() { return length; } public char[] getCharArray() { return buffer; } public boolean hasFragments() { return !bufferFragments.isEmpty(); } public static Builder builder() { return new Builder(); } public static Builder builder(SitemeshBuffer sitemeshBuffer) { if (sitemeshBuffer instanceof DefaultSitemeshBuffer) { return new Builder((DefaultSitemeshBuffer) sitemeshBuffer); } else { return new Builder(sitemeshBuffer); } } public static class Builder { private char[] buffer; private int length; private final TreeMap<Integer, SitemeshBufferFragment> fragments; private Builder() { this.fragments = new TreeMap<Integer, SitemeshBufferFragment>(); } private Builder(DefaultSitemeshBuffer buffer) { this.buffer = buffer.buffer; this.length = buffer.length; this.fragments = new TreeMap<Integer, SitemeshBufferFragment>(buffer.bufferFragments); } private Builder(SitemeshBuffer buffer) { this.buffer = buffer.getCharArray(); this.length = buffer.getBufferLength(); this.fragments = new TreeMap<Integer, SitemeshBufferFragment>(); } public Builder setBuffer(char[] buffer) { this.buffer = buffer; return this; } public Builder setLength(int length) { this.length = length; return this; } public Builder insert(int position, SitemeshBufferFragment fragment) { this.fragments.put(position, fragment); return this; } public SitemeshBuffer build() { return new DefaultSitemeshBuffer(buffer, length, fragments); } } }