/* Licensed 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.activiti.rest.builder; import java.io.IOException; import java.io.Writer; import java.util.HashMap; import java.util.Map; import org.json.JSONException; import org.json.JSONObject; import org.springframework.context.ApplicationContext; import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.WebScriptException; import org.springframework.extensions.webscripts.processor.AbstractTemplateProcessor; /** * A Template Processor that passes the model on to a registered delegate class * of type {@link JSONObjectBuilder}, which will create a {@link JSONObject}. * The resulting JSONObject is written to the response. * * When no builder is defined for the required template, * <code>hasTemplate(template)</code> returns false. * * @author Frederik Heremans */ public class JSONTemplateProcessor extends AbstractTemplateProcessor { private static final String PROCESSOR_EXTENTION = "object"; private static final String PROCESSOR_EXTENTION_SUFFIX = "." + PROCESSOR_EXTENTION; private static final String PROCESSOR_NAME = "JSONObject"; private static final Integer DEFAULT_INDENT_FACTOR = 2; protected String defaultEncoding; protected String templateNamePrefix; protected ApplicationContext applicationContext; protected Integer indentFactor = DEFAULT_INDENT_FACTOR; private Map<String, JSONObjectBuilder> objectBuilders = new HashMap<String, JSONObjectBuilder>(); public boolean hasTemplate(String template) { return objectBuilders.containsKey(getTemplateKey(template)); } public void process(String template, Object model, Writer out) { JSONObjectBuilder builder = objectBuilders.get(getTemplateKey(template)); if (builder == null) { throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "Template " + template + " is registered on this this processor."); } try { JSONObject resultObject = builder.createJsonObject(model); writeJSON(resultObject, out); } catch (JSONException jsone) { throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "Error while creating JSONObject from model", jsone); } } public void processString(String template, Object model, Writer out) { throw new UnsupportedOperationException(this.getClass().getSimpleName() + " does not support processing of template string."); } @Override public void init() { initializeObjectBuilders(); } public void reset() { initializeObjectBuilders(); } protected void initializeObjectBuilders() { if (applicationContext != null) { // Search in context for all JSONObjectBuilders Map<String, JSONObjectBuilder> buildersFromContext = applicationContext.getBeansOfType(JSONObjectBuilder.class); Map<String, JSONObjectBuilder> newBuilders = new HashMap<String, JSONObjectBuilder>(); for (JSONObjectBuilder builder : buildersFromContext.values()) { newBuilders.put(templateNamePrefix + builder.getTemplateName(), builder); } objectBuilders = newBuilders; } } protected String getTemplateKey(String template) { if (template != null) { return template.replace(PROCESSOR_EXTENTION_SUFFIX, ""); } return null; } protected void writeJSON(JSONObject object, Writer out) throws WebScriptException { try { if (indentFactor == 0) { // When no indentation is required, we use JSONObject.write, which is // cheaper than toString() object.write(out); } else { out.write(object.toString(indentFactor)); } } catch (JSONException jsone) { throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "Error while writing JSONObject", jsone); } catch (IOException ioe) { throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "Error while writing JSONObject", ioe); } } @Override public void setApplicationContext(ApplicationContext applicationContext) { super.setApplicationContext(applicationContext); this.applicationContext = applicationContext; } public String getDefaultEncoding() { return defaultEncoding; } public String getName() { return PROCESSOR_NAME; } public String getExtension() { return PROCESSOR_EXTENTION; } public void setDefaultEncoding(String defaultEncoding) { this.defaultEncoding = defaultEncoding; } public void setTemplateNamePrefix(String templateNamePrefix) { this.templateNamePrefix = templateNamePrefix; } public void setIndentFactor(Integer indentFactor) { if (indentFactor != null && indentFactor > 0) { this.indentFactor = indentFactor; } else { this.indentFactor = DEFAULT_INDENT_FACTOR; } } }