| /* |
| * 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; |
| } |
| |
| } |
| |
| |
| } |