001/* 002 * JKNIV, whinstone one contract to access your database. 003 * 004 * Copyright (C) 2017, the original author or authors. 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software Foundation, Inc., 018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 019 */ 020package net.sf.jkniv.whinstone.couchdb.commands; 021 022import java.io.IOException; 023import java.io.UnsupportedEncodingException; 024import java.util.HashMap; 025import java.util.Map; 026 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029 030import com.fasterxml.jackson.core.JsonParseException; 031import com.fasterxml.jackson.core.type.TypeReference; 032import com.fasterxml.jackson.databind.DeserializationFeature; 033import com.fasterxml.jackson.databind.JsonMappingException; 034import com.fasterxml.jackson.databind.Module; 035import com.fasterxml.jackson.databind.ObjectMapper; 036import com.fasterxml.jackson.databind.SerializationFeature; 037import com.fasterxml.jackson.databind.module.SimpleModule; 038 039import net.sf.jkniv.exception.HandlerException; 040import net.sf.jkniv.reflect.beans.ObjectProxy; 041import net.sf.jkniv.reflect.beans.ObjectProxyFactory; 042import net.sf.jkniv.sqlegance.RepositoryException; 043import net.sf.jkniv.whinstone.QueryFactory; 044import net.sf.jkniv.whinstone.Queryable; 045 046public class JsonMapper 047{ 048 private static final Logger LOG = LoggerFactory.getLogger(JsonMapper.class); 049 private static HandlerException handlerException; 050 static final ObjectMapper MAPPER = new ObjectMapper(); 051 private static final Map<String, String> JACKSON_MODULES = new HashMap<String, String>(); 052 private static final ThreadLocal<Queryable> CURRENT_QUERY = new ThreadLocal<Queryable>(); 053 054 static 055 { 056 handlerException = new HandlerException(RepositoryException.class, "Cannot set parameter [%s] value [%s]"); 057 // JsonParseException | JsonMappingException | IOException 058 handlerException.config(JsonParseException.class, "Error to parser json non-well-formed content [%s]"); 059 handlerException.config(JsonMappingException.class, "Error to deserialization content [%s]"); 060 handlerException.config(UnsupportedEncodingException.class, "Error at json content encoding unsupported [%s]"); 061 handlerException.config(IOException.class, "Error from I/O json content [%s]"); 062 063 JACKSON_MODULES.put("ParameterNamesModule", "com.fasterxml.jackson.module.paramnames.ParameterNamesModule"); 064 JACKSON_MODULES.put("JavaTimeModule", "com.fasterxml.jackson.datatype.jsr310.JavaTimeModule"); 065 JACKSON_MODULES.put("Jdk8Module", "com.fasterxml.jackson.datatype.jdk8.Jdk8Module"); 066 JACKSON_MODULES.put("JSR310TimeModule", "com.fasterxml.jackson.datatype.jsr310.JSR310TimeModule"); 067 JACKSON_MODULES.put("ThreeTenModule", "com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule"); 068 069 SimpleModule simpleModule = new SimpleModule(); 070 simpleModule.addDeserializer(CouchDbResultImpl.class, new CouchDbJsonDeserialization()); 071 MAPPER.registerModule(simpleModule); 072 // pretty print 073 //String prettyStaff1 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff2); 074 //MAPPER.writerWithDefaultPrettyPrinter(); 075 076 } 077 078 private JsonMapper() 079 { 080 } 081 082 static void setCurrentQuery(Queryable queryable) 083 { 084 CURRENT_QUERY.set(queryable); 085 } 086 087 static Queryable getCurrentQuery() 088 { 089 Queryable queryable = CURRENT_QUERY.get(); 090 CURRENT_QUERY.remove(); 091 if(queryable == null) 092 { 093 queryable = QueryFactory.of("dummy", Map.class); 094 } 095 return queryable; 096 } 097 098 public static void config(SerializationFeature feature, boolean state) 099 { 100 MAPPER.configure(feature, state); 101 } 102 103 public static void config(DeserializationFeature feature, boolean state) 104 { 105 MAPPER.configure(feature, state); 106 } 107 108 public static void register(String moduleName, boolean state) 109 { 110 if (!state) 111 return; 112 113 Module module = null; 114 ObjectProxy<Module> proxy = null; 115 String classNameOfModule = JACKSON_MODULES.get(moduleName); 116 if (classNameOfModule != null) 117 { 118 proxy = ObjectProxyFactory.of(classNameOfModule); 119 module = proxy.newInstance(); 120 if (module != null) 121 { 122 MAPPER.registerModule(module); 123 LOG.info("Jackson module {} was registered with success by class {} ", moduleName , classNameOfModule); 124 } 125 } 126 if (module == null) 127 LOG.error("Cannot register the module {}! {} ", moduleName, (classNameOfModule == null ? "ParameterNamesModule, JavaTimeModule and Jdk8Module are supported to register" : "the class "+classNameOfModule +" was not found at classpath")); 128 129 } 130 131// public static ObjectMapper newMapper() 132// { 133// //ObjectMapper mapper = new ObjectMapper(); 134// // FIXME design jackson json properties config 135// //mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 136// return MAPPER; 137// } 138 139 public static <T> T mapper(String content, Class<T> valueType) 140 { 141 try 142 { 143 return MAPPER.readValue(content, valueType); 144 } 145 catch (Exception e) 146 { 147 // JsonParseException | JsonMappingException | IOException 148 handlerException.handle(e); 149 } 150 return null; 151 } 152 153 @SuppressWarnings("rawtypes") 154 public static <T> T mapper(String content, TypeReference valueType) 155 { 156 try 157 { 158 return MAPPER.readValue(content, valueType); 159 } 160 catch (Exception e) 161 { 162 // JsonParseException | JsonMappingException | IOException 163 handlerException.handle(e); 164 } 165 return null; 166 } 167 168 public static <T> T mapper(Map<String, Object> content, Class<T> valueType) 169 { 170 try 171 { 172 //final ObjectMapper mapper = new ObjectMapper(); // jackson's objectmapper 173 return MAPPER.convertValue(content, valueType); 174 //return newMapper().readValue(content, valueType); 175 } 176 catch (Exception e) 177 { 178 // JsonParseException | JsonMappingException | IOException 179 handlerException.handle(e); 180 } 181 return null; 182 } 183 184 public static String mapper(Object o) 185 { 186 try 187 { 188 return MAPPER.writeValueAsString(o); 189 } 190 catch (Exception e) 191 { 192 // JsonParseException | JsonMappingException | IOException 193 handlerException.handle(e); 194 } 195 return null; 196 } 197}