/* * Copyright (C) 2012 Jan Pokorsky * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package cz.cas.lib.proarc.webapp.server.rest; import com.fasterxml.jackson.databind.ObjectMapper; import cz.cas.lib.proarc.common.json.JsonUtils; import cz.cas.lib.proarc.webapp.server.rest.SmartGwtResponse.AnnotatedSmartGwtResponse; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; import javax.xml.bind.annotation.adapters.XmlAdapter; /** * This provider enables a customized JSON mapper supporting JAXB annotations * and the mix-in annotations. * It handles the single item arrays as {@code "items":[{"propName":"propValue"}]} * instead of {@code "items":{"propName":"propValue"}}. * <p>See {@code web.xml} for its registration. * * @author Jan Pokorsky */ @Provider @Consumes({MediaType.APPLICATION_JSON, "text/json"}) @Produces({MediaType.APPLICATION_JSON, "text/json"}) public final class JacksonProvider implements ContextResolver<ObjectMapper> { private final ObjectMapper mapper; public JacksonProvider() { mapper = JsonUtils.createJaxbMapper(); registerAnnotatedSuperclass(AnnotatedAtmItem.class); registerAnnotatedSuperclass(AnnotatedBatchView.class); registerAnnotatedSuperclass(AnnotatedConfigurationProfile.class); registerAnnotatedSuperclass(AnnotatedDescriptionMetadata.class); registerAnnotatedSuperclass(AnnotatedDevice.class); registerAnnotatedSuperclass(AnnotatedDublinCoreRecord.class); // registerAnnotatedSuperclass(AnnotatedMetaModel.class); registerAnnotatedSuperclass(AnnotatedPageViewItem.class); registerAnnotatedSuperclass(AnnotatedSearchViewItem.class); registerAnnotatedSuperclass(AnnotatedSmartGwtResponse.class); registerAnnotatedSuperclass(AnnotatedStringRecord.class); registerAnnotatedSuperclass(AnnotatedUser.class); registerAnnotatedSuperclass(AnnotatedValueMap.class); registerAnnotatedSuperclass(AnnotatedMods.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedAbstractDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedAccessConditionDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedCopyInformationDefinitionNote.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedLanguageDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedLocationDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedNameDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedNoteDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedOriginInfoDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedPartDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedPhysicalDescriptionDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedPhysicalDescriptionNote.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedPhysicalLocationDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedRecordInfoDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedRelatedItemDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedStringPlusLanguage.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedSubjectDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedSubjectNameDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedSubjectTitleInfoDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedTableOfContentsDefinition.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedText.class); registerAnnotatedSuperclass(AnnotatedMods.AnnotatedTitleInfoDefinition.class); JsonUtils.setDefaultObjectMapper(mapper); } @Override public ObjectMapper getContext(Class<?> type) { return mapper; } private void register(Class<?> target, Class<?> mixinSource) { mapper.addMixIn(target, mixinSource); } private void registerAnnotatedSuperclass(Class<?> mixinSource) { register(mixinSource.getSuperclass(), mixinSource); } /** * The helper class that can override a declared XML adapter with the default JAXB mapping. * <p>Jackson2 requires a type declaration especially in case of the container types (Map, ...). * In that case it is necessary to create a subclass of the adapter. */ public static class DefaultAdapter<O> extends XmlAdapter<O, O> { @Override public O unmarshal(O v) throws Exception { return v; } @Override public O marshal(O v) throws Exception { return v; } } }