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