| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.hyracks.maven.license.freemarker; |
| |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| import java.util.Arrays; |
| import java.util.Map; |
| |
| import freemarker.core.Environment; |
| import freemarker.template.TemplateBooleanModel; |
| import freemarker.template.TemplateDirectiveBody; |
| import freemarker.template.TemplateDirectiveModel; |
| import freemarker.template.TemplateException; |
| import freemarker.template.TemplateModel; |
| import freemarker.template.TemplateModelException; |
| import freemarker.template.TemplateNumberModel; |
| import org.apache.commons.io.IOUtils; |
| import org.apache.hyracks.maven.license.LicenseUtil; |
| |
| public class IndentDirective implements TemplateDirectiveModel { |
| |
| private static final String PARAM_NAME_SPACES = "spaces"; |
| private static final String PARAM_NAME_UNPAD = "unpad"; |
| private static final String PARAM_NAME_WRAP = "wrap"; |
| |
| @Override |
| public void execute(Environment env, Map params, TemplateModel [] loopVars, TemplateDirectiveBody body) |
| throws TemplateException, IOException { |
| |
| int numSpaces = -1; |
| boolean unpad = false; |
| boolean wrap = false; |
| |
| for (Object o : params.entrySet()) { |
| Map.Entry ent = (Map.Entry) o; |
| |
| String paramName = (String) ent.getKey(); |
| TemplateModel paramValue = (TemplateModel) ent.getValue(); |
| |
| switch (paramName) { |
| case PARAM_NAME_SPACES: |
| numSpaces = getIntParam(paramName, paramValue); |
| break; |
| case PARAM_NAME_UNPAD: |
| unpad = getBooleanParam(paramName, paramValue); |
| break; |
| case PARAM_NAME_WRAP: |
| wrap = getBooleanParam(paramName, paramValue); |
| break; |
| default: |
| throw new TemplateModelException("Unsupported parameter: " + paramName); |
| } |
| } |
| if (numSpaces < 0) { |
| throw new TemplateModelException("The required \"" + PARAM_NAME_SPACES + "\" parameter is missing."); |
| } |
| |
| if (body == null) { |
| throw new TemplateModelException("Indent requires a body"); |
| } else { |
| // Executes the nested body (same as <#nested> in FTL). In this |
| // case we don't provide a special writer as the parameter: |
| StringWriter sw = new StringWriter(); |
| body.render(sw); |
| String fixedup = LicenseUtil.process(sw.toString(), unpad, wrap); |
| IOUtils.copy(new StringReader(fixedup), new IndentingWriter(env.getOut(), numSpaces)); |
| } |
| } |
| |
| private int getIntParam(String paramName, TemplateModel paramValue) throws TemplateModelException { |
| int spacesParam; |
| if (!(paramValue instanceof TemplateNumberModel)) { |
| throw paramException(paramName, "must be a number"); |
| } |
| spacesParam = ((TemplateNumberModel) paramValue).getAsNumber().intValue(); |
| if (spacesParam < 0) { |
| throw paramException(paramName, "can't be negative"); |
| } |
| return spacesParam; |
| } |
| |
| private boolean getBooleanParam(String paramName, TemplateModel paramValue) throws TemplateModelException { |
| if (!(paramValue instanceof TemplateBooleanModel)) { |
| throw paramException(paramName, "must be a boolean"); |
| } |
| return ((TemplateBooleanModel) paramValue).getAsBoolean(); |
| } |
| |
| private TemplateModelException paramException(String paramName, String message) throws TemplateModelException { |
| return new TemplateModelException( |
| "The '" + paramName + "' parameter " + message); |
| } |
| |
| private static class IndentingWriter extends Writer { |
| private final Writer out; |
| private final char[] padChars; |
| boolean needsToPad; |
| |
| public IndentingWriter(Writer out, int numSpaces) { |
| this.out = out; |
| padChars = new char[numSpaces]; |
| Arrays.fill(padChars, ' '); |
| needsToPad = true; |
| } |
| |
| @Override |
| public void write(char[] cbuf, int off, int len) throws IOException { |
| for (int i = off; i < len; i++) { |
| if (cbuf[i] == '\n') { |
| out.write(cbuf[i]); |
| needsToPad = true; |
| } else { |
| if (needsToPad) { |
| out.write(padChars); |
| needsToPad = false; |
| } |
| out.write(cbuf[i]); |
| } |
| } |
| } |
| |
| @Override |
| public void flush() throws IOException { |
| out.flush(); |
| } |
| |
| @Override |
| public void close() throws IOException { |
| out.flush(); |
| } |
| } |
| } |