/* 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.workflow.simple.converter.json;
import java.io.InputStream;
import java.io.Writer;
import java.util.List;
import org.activiti.workflow.simple.definition.ChoiceStepsDefinition;
import org.activiti.workflow.simple.definition.DelayStepDefinition;
import org.activiti.workflow.simple.definition.FeedbackStepDefinition;
import org.activiti.workflow.simple.definition.HumanStepDefinition;
import org.activiti.workflow.simple.definition.ListConditionStepDefinition;
import org.activiti.workflow.simple.definition.ListStepDefinition;
import org.activiti.workflow.simple.definition.ParallelStepsDefinition;
import org.activiti.workflow.simple.definition.ScriptStepDefinition;
import org.activiti.workflow.simple.definition.WorkflowDefinition;
import org.activiti.workflow.simple.definition.form.BooleanPropertyDefinition;
import org.activiti.workflow.simple.definition.form.DatePropertyDefinition;
import org.activiti.workflow.simple.definition.form.FormDefinition;
import org.activiti.workflow.simple.definition.form.ListPropertyDefinition;
import org.activiti.workflow.simple.definition.form.NumberPropertyDefinition;
import org.activiti.workflow.simple.definition.form.ReferencePropertyDefinition;
import org.activiti.workflow.simple.definition.form.TextPropertyDefinition;
import org.activiti.workflow.simple.exception.SimpleWorkflowException;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* A converter capable of converting {@link WorkflowDefinition}s from and to a
* JSON representation.
* <br>
* <p>Instances of this class <b>are thread-safe</b>.</p>
*
* @author Frederik Heremans
*/
public class SimpleWorkflowJsonConverter {
protected ObjectMapper objectMapper;
protected List<Class<?>> additionalModelClasses;
/**
* @param inputStream the stream to read the JSON from.
* @return The workflow definition instance, read from the given input-stream.
* @throws SimpleWorkflowException when an error occurs while reading or parsing the definition.
*/
public WorkflowDefinition readWorkflowDefinition(InputStream inputStream) throws SimpleWorkflowException {
try {
return getObjectMapper().readValue(inputStream, WorkflowDefinition.class);
} catch (Exception e) {
throw wrapExceptionRead(e);
}
}
/**
* @param bytes array representing the definition JSON.
* @return The workflow definition instance, parsed from the given array.
* @throws SimpleWorkflowException when an error occurs while parsing the definition.
*/
public WorkflowDefinition readWorkflowDefinition(byte[] bytes) throws SimpleWorkflowException {
try {
return getObjectMapper().readValue(bytes, WorkflowDefinition.class);
} catch (Exception e) {
throw wrapExceptionRead(e);
}
}
public void writeWorkflowDefinition(WorkflowDefinition definition, Writer writer) {
try {
getObjectMapper().writeValue(writer, definition);
} catch (Exception e) {
throw wrapExceptionWrite(e);
}
}
/**
* @param inputStream the stream to read the JSON from.
* @return The workflow definition instance, read from the given input-stream.
* @throws SimpleWorkflowException when an error occurs while reading or parsing the definition.
*/
public FormDefinition readFormDefinition(InputStream inputStream) {
try {
return getObjectMapper().readValue(inputStream, FormDefinition.class);
} catch (Exception e) {
throw wrapExceptionRead(e);
}
}
public void writeFormDefinition(FormDefinition definition, Writer writer) {
try {
getObjectMapper().writeValue(writer, definition);
} catch (Exception e) {
throw wrapExceptionWrite(e);
}
}
/**
* @param e exception to wrap
* @return an {@link SimpleWorkflowException} to throw, wrapping the given exception.
*/
protected SimpleWorkflowException wrapExceptionRead(Exception e) {
return new SimpleWorkflowException("Error while parsing JSON", e);
}
/**
* @param e exception to wrap
* @return an {@link SimpleWorkflowException} to throw, wrapping the given exception.
*/
protected SimpleWorkflowException wrapExceptionWrite(Exception e) {
return new SimpleWorkflowException("Error while writing JSON", e);
}
protected ObjectMapper getObjectMapper() {
if (objectMapper == null) {
// Ensure ObjectMapper is only initialized once
synchronized (this) {
if (objectMapper == null) {
objectMapper = new ObjectMapper();
// Register all property-definition model classes as sub-types
objectMapper.registerSubtypes(ListPropertyDefinition.class, TextPropertyDefinition.class,
ReferencePropertyDefinition.class, DatePropertyDefinition.class, NumberPropertyDefinition.class, BooleanPropertyDefinition.class);
// Register all step-types
objectMapper.registerSubtypes(HumanStepDefinition.class, FeedbackStepDefinition.class, ParallelStepsDefinition.class, ChoiceStepsDefinition.class,
ListStepDefinition.class, ListConditionStepDefinition.class, ScriptStepDefinition.class, DelayStepDefinition.class);
// Register additional sub-types to allow custom model entities to be
// deserialized correctly
if (additionalModelClasses != null) {
objectMapper.registerSubtypes(additionalModelClasses.toArray(new Class<?>[] {}));
}
}
}
}
return objectMapper;
}
}