blob: eeb1333a8f594240122c4b11f187fd3ff068c074 [file] [log] [blame]
/*
* 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.ode.jacob.soup.jackson;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import org.apache.ode.jacob.Channel;
import org.apache.ode.jacob.ChannelProxy;
import org.apache.ode.jacob.soup.Continuation;
import org.apache.ode.jacob.vpu.ExecutionQueueImpl;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
/**
* Variant of {@link org.apache.ode.jacob.vpu.ExecutionQueueImpl} that can be
* serialized and deserialized with Jackson.
*/
public class JacksonExecutionQueueImpl extends ExecutionQueueImpl {
public JacksonExecutionQueueImpl() {
super(null);
}
public static ObjectMapper configureMapper() {
SimpleModule sm = new SimpleModule("jacobmodule");
sm.addSerializer(ChannelProxy.class, new ChannelProxySerializer());
sm.addSerializer(Continuation.class, new ContinuationSerializer());
sm.addSerializer(JacksonExecutionQueueImpl.class, new ExecutionQueueImplSerializer());
sm.addDeserializer(JacksonExecutionQueueImpl.class, new ExecutionQueueImplDeserializer());
sm.addDeserializer(Continuation.class, new ContinuationDeserializer());
sm.addDeserializer(Channel.class, new ChannelProxyDeserializer());
ObjectMapper om = new ObjectMapper();
om.registerModule(sm);
om.disable(MapperFeature.AUTO_DETECT_CREATORS);
om.disable(MapperFeature.AUTO_DETECT_GETTERS);
om.disable(MapperFeature.AUTO_DETECT_IS_GETTERS);
om.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
om.setDefaultTyping(new JacobTypeResolverBuilder());
om.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);
om.enable(SerializationFeature.INDENT_OUTPUT);
return om;
}
public static class ExecutionQueueImplSerializer extends StdSerializer<JacksonExecutionQueueImpl> {
public ExecutionQueueImplSerializer() {
super(JacksonExecutionQueueImpl.class);
}
@Override
public void serialize(JacksonExecutionQueueImpl value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonGenerationException {
jgen.writeStartObject();
serializeContents(value, jgen, provider);
jgen.writeEndObject();
}
@Override
public void serializeWithType(JacksonExecutionQueueImpl value, JsonGenerator jgen,
SerializerProvider provider, TypeSerializer typeSer)
throws IOException, JsonProcessingException {
typeSer.writeTypePrefixForObject(value, jgen);
serializeContents(value, jgen, provider);
typeSer.writeTypeSuffixForObject(value, jgen);
}
private void serializeContents(JacksonExecutionQueueImpl value, JsonGenerator jgen,
SerializerProvider provider) throws JsonGenerationException, IOException {
jgen.writeNumberField("objIdCounter", value._objIdCounter);
jgen.writeNumberField("currentCycle", value._currentCycle);
jgen.writeObjectField("continuations", value._reactions.toArray(new Continuation[] {}));
jgen.writeObjectField("channels", value._channels.values().toArray(new ChannelFrame[] {}));
jgen.writeObjectField("global", value._gdata);
}
}
public static class ExecutionQueueImplDeserializer extends StdDeserializer<JacksonExecutionQueueImpl> {
private static final long serialVersionUID = 1L;
public ExecutionQueueImplDeserializer() {
super(JacksonExecutionQueueImpl.class);
}
@Override
public JacksonExecutionQueueImpl deserialize(JsonParser jp,
DeserializationContext ctxt) throws IOException,
JsonProcessingException {
JacksonExecutionQueueImpl soup = new JacksonExecutionQueueImpl();
while (jp.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jp.getCurrentName();
if (jp.getCurrentToken() == JsonToken.FIELD_NAME) {
// if we're not already on the field, advance by one.
jp.nextToken();
}
if ("objIdCounter".equals(fieldname)) {
soup._objIdCounter = jp.getIntValue();
} else if ("currentCycle".equals(fieldname)) {
soup._currentCycle = jp.getIntValue();
} else if ("continuations".equals(fieldname)) {
Continuation[] cs = (Continuation[])jp.readValueAs(Continuation[].class);
soup._reactions = new HashSet<Continuation>(Arrays.asList(cs));
} else if ("channels".equals(fieldname)) {
soup._channels = new HashMap<Integer, ChannelFrame>();
ChannelFrame[] frames = jp.readValueAs(ChannelFrame[].class);
for (ChannelFrame f : frames) {
soup._channels.put(f.getId(), f);
}
}
}
return soup;
}
}
}