001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * bstefanescu 011 * 012 * $Id$ 013 */ 014 015package org.nuxeo.ecm.platform.rendering.fm.extensions; 016 017import java.io.IOException; 018import java.io.Writer; 019import java.util.ArrayList; 020import java.util.List; 021 022import freemarker.template.TemplateException; 023 024/** 025 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 026 */ 027public class BlockWriter extends Writer { 028 029 BlockWriterRegistry reg; 030 031 final String page; 032 033 final String name; 034 035 StringBuilder buf = new StringBuilder(); 036 037 List<String> segments = new ArrayList<String>(); 038 039 List<String> blocks = new ArrayList<String>(); 040 041 BlockWriter superBlock; // the direct parent in the hierarchy - null if none 042 043 BlockWriter baseBlock; // the root of the block hierarchy - null if none 044 045 String ifBlockDefined; 046 047 // used to avoid writing blocks or characters in the current block writer. 048 // This is the case of the extension tag - that should ignore any content 049 // and blocks too because blocks inside extension tag 050 // must be derived blocks (the base hierarchy block will be found later when 051 // the extended base template will be parsed) 052 boolean suppressOutput = false; 053 054 public BlockWriter(String page, String name, BlockWriterRegistry reg) { 055 this.reg = reg; 056 this.name = name; 057 this.page = page; 058 } 059 060 public final BlockWriterRegistry getRegistry() { 061 return reg; 062 } 063 064 public void setSuppressOutput(boolean suppressOutput) { 065 this.suppressOutput = suppressOutput; 066 } 067 068 public boolean getSuppressOutput() { 069 return suppressOutput; 070 } 071 072 @Override 073 public void close() throws IOException { 074 buf = null; 075 segments = null; 076 blocks = null; 077 superBlock = null; 078 reg = null; 079 } 080 081 @Override 082 public void flush() throws IOException { 083 // do nothing 084 } 085 086 public boolean isEmpty() { 087 return buf.length() == 0 && segments.isEmpty() && blocks.isEmpty(); 088 } 089 090 @Override 091 public void write(char[] cbuf, int off, int len) throws IOException { 092 if (!suppressOutput) { 093 buf.append(cbuf, off, len); 094 } 095 } 096 097 public void writeBlock(BlockWriter bw) { 098 if (!suppressOutput) { 099 // add the current buffer to the segments list 100 segments.add(buf.toString()); 101 // reset buffer 102 buf.setLength(0); 103 // ad the sub block to the children block list 104 blocks.add(bw.name); 105 } 106 // inform the container about the new block 107 reg.addBlock(bw.name, bw); 108 } 109 110 public void writeSuperBlock() { 111 if (!suppressOutput) { 112 segments.add(buf.toString()); // add the current buffer to the 113 // segments list 114 buf.setLength(0); // reset buffer 115 blocks.add(".."); // add a special key that represent the super 116 // block 117 } 118 } 119 120 public void copyTo(Writer writer) throws TemplateException, IOException { 121 // check first if you need to suppress this block 122 if (ifBlockDefined != null) { 123 BlockWriter bw = reg.getBlock(ifBlockDefined); 124 if (bw == null || bw.isEmpty()) { 125 return; 126 } 127 } 128 for (int i = 0, len = segments.size(); i < len; i++) { 129 writer.write(segments.get(i)); 130 String key = blocks.get(i); 131 BlockWriter bw = null; 132 if (key == "..") { // the super block 133 bw = superBlock; 134 } else { // a regular block 135 bw = reg.getBlock(key); 136 } 137 bw.copyTo(writer); 138 } 139 writer.write(buf.toString()); 140 } 141 142 @Override 143 public String toString() { 144 return name + "@" + page; 145 } 146}