/*
* Copyright 2015 ArcBees Inc.
*
* 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 com.gwtplatform.dispatch.rest.processors.serialization.jackson;
import java.util.Map;
import java.util.TreeMap;
import javax.inject.Singleton;
import javax.tools.FileObject;
import javax.ws.rs.core.MediaType;
import com.google.auto.service.AutoService;
import com.google.common.base.Optional;
import com.gwtplatform.dispatch.rest.client.serialization.JacksonMapperProvider;
import com.gwtplatform.dispatch.rest.processors.DispatchRestContextProcessor;
import com.gwtplatform.dispatch.rest.processors.NameUtils;
import com.gwtplatform.dispatch.rest.processors.serialization.SerializationContext;
import com.gwtplatform.dispatch.rest.processors.serialization.SerializationProcessor;
import com.gwtplatform.dispatch.rest.shared.ContentType;
import com.gwtplatform.processors.tools.bindings.BindingContext;
import com.gwtplatform.processors.tools.bindings.BindingsProcessors;
import com.gwtplatform.processors.tools.domain.Type;
import com.gwtplatform.processors.tools.logger.Logger;
import com.gwtplatform.processors.tools.outputter.Outputter;
import com.gwtplatform.processors.tools.utils.Primitives;
import com.gwtplatform.processors.tools.utils.Utils;
import static com.gwtplatform.dispatch.rest.processors.NameUtils.findRestModuleType;
import static com.gwtplatform.processors.tools.bindings.BindingContext.newSetBinder;
import static com.gwtplatform.processors.tools.utils.Primitives.findByBoxed;
import static com.gwtplatform.processors.tools.utils.Primitives.findByPrimitive;
@AutoService(SerializationProcessor.class)
public class JacksonSerializationProcessor extends DispatchRestContextProcessor<SerializationContext, Void>
implements SerializationProcessor {
private static final String TEMPLATE =
"com/gwtplatform/dispatch/rest/processors/serialization/jackson/JacksonMapperProvider.vm";
private static final ContentType APPLICATION_JSON = ContentType.valueOf(MediaType.APPLICATION_JSON);
private final JacksonMapperProcessor mapperProcessor;
private final Map<Type, JacksonMapper> mappers;
private final Type parent;
private Type impl;
private FileObject sourceFile;
public JacksonSerializationProcessor() {
this.mapperProcessor = new JacksonMapperProcessor();
this.mappers = new TreeMap<>();
this.parent = new Type(JacksonMapperProvider.class);
}
@Override
public synchronized void init(Logger logger, Utils utils, Outputter outputter) {
super.init(logger, utils, outputter);
mapperProcessor.init(logger, utils, outputter);
impl = NameUtils.findJacksonMapperProviderType(utils);
sourceFile = outputter.prepareSourceFile(impl);
BindingContext context = newSetBinder(findRestModuleType(utils), parent, impl, Singleton.class);
new BindingsProcessors(logger, utils, outputter).process(context);
}
@Override
public boolean canProcess(SerializationContext context) {
return context.getContentTypes().contains(APPLICATION_JSON);
}
@Override
public Void process(SerializationContext context) {
if (!mappers.containsKey(context.getType())) {
JacksonMapper mapper = mapperProcessor.process(context);
mappers.put(mapper.getMapped(), mapper);
duplicateIfBoxedOrPrimitive(mapper);
}
return null;
}
private void duplicateIfBoxedOrPrimitive(JacksonMapper mapper) {
String name = mapper.getKey().getQualifiedParameterizedName();
Optional<Primitives> primitive = findByPrimitive(name);
Optional<Primitives> boxed = findByBoxed(name);
Type newKey = null;
if (primitive.isPresent()) {
newKey = new Type(primitive.get().getBoxedClass());
} else if (boxed.isPresent()) {
newKey = new Type(boxed.get().getPrimitive());
}
if (newKey != null) {
mappers.put(newKey, new JacksonMapper(newKey, mapper.getMapped(), mapper.getType()));
}
}
@Override
public void processLast() {
logger.debug("Generating Jackson serialization policy `%s`.", impl.getQualifiedName());
outputter.configure(TEMPLATE)
.withParam("mappers", mappers.values())
.writeTo(impl, sourceFile);
}
}