View Javadoc
1   /*
2    * Copyright 2015-2022 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.bremersee.geojson;
18  
19  import static java.util.Objects.isNull;
20  
21  import com.fasterxml.jackson.core.Version;
22  import com.fasterxml.jackson.databind.JsonDeserializer;
23  import com.fasterxml.jackson.databind.JsonSerializer;
24  import com.fasterxml.jackson.databind.module.SimpleModule;
25  import java.io.Serial;
26  import java.util.ArrayList;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.regex.Pattern;
31  import org.bremersee.geojson.converter.deserialization.JacksonGeometryDeserializer;
32  import org.bremersee.geojson.converter.serialization.JacksonGeometrySerializer;
33  import org.locationtech.jts.geom.Geometry;
34  import org.locationtech.jts.geom.GeometryCollection;
35  import org.locationtech.jts.geom.GeometryFactory;
36  import org.locationtech.jts.geom.LineString;
37  import org.locationtech.jts.geom.MultiLineString;
38  import org.locationtech.jts.geom.MultiPoint;
39  import org.locationtech.jts.geom.MultiPolygon;
40  import org.locationtech.jts.geom.Point;
41  import org.locationtech.jts.geom.Polygon;
42  
43  /**
44   * A Jackson JSON processor module that provides the processing (serialization and deserialization)
45   * of the following types.
46   * <ul>
47   * <li>{@link Geometry}</li>
48   * <li>{@link Point}</li>
49   * <li>{@link LineString}</li>
50   * <li>{@link Polygon}</li>
51   * <li>{@link MultiPoint}</li>
52   * <li>{@link MultiLineString}</li>
53   * <li>{@link MultiPolygon}</li>
54   * <li>{@link GeometryCollection}</li>
55   * </ul>
56   *
57   * @author Christian Bremer
58   */
59  public class GeoJsonObjectMapperModule extends SimpleModule {
60  
61    @Serial
62    private static final long serialVersionUID = 1L;
63  
64    /**
65     * The constant TYPE_ID.
66     */
67    public static final String TYPE_ID = GeoJsonObjectMapperModule.class.getName();
68  
69    /**
70     * Default constructor.
71     */
72    public GeoJsonObjectMapperModule() {
73      this(new GeometryFactory());
74    }
75  
76    /**
77     * Instantiates a new geo json object mapper module.
78     *
79     * @param geometryFactory the geometry factory
80     */
81    public GeoJsonObjectMapperModule(GeometryFactory geometryFactory) {
82      this(geometryFactory, false, false);
83    }
84  
85    /**
86     * Instantiates a new geo json object mapper module.
87     *
88     * @param withBoundingBox with bounding box
89     * @param useBigDecimal the use big decimal
90     */
91    public GeoJsonObjectMapperModule(boolean withBoundingBox, boolean useBigDecimal) {
92      this(new GeometryFactory(), withBoundingBox, useBigDecimal);
93    }
94  
95    /**
96     * Instantiates a new geo json object mapper module.
97     *
98     * @param geometryFactory the geometry factory
99     * @param withBoundingBox the with bounding box
100    * @param useBigDecimal the use big decimal
101    */
102   public GeoJsonObjectMapperModule(
103       GeometryFactory geometryFactory,
104       boolean withBoundingBox,
105       boolean useBigDecimal) {
106     super(
107         TYPE_ID,
108         getVersion(),
109         getDeserializers(geometryFactory),
110         getSerializers(withBoundingBox, useBigDecimal));
111   }
112 
113   private static Version getVersion() {
114 
115     int defaultMajor = 5;
116     int defaultMinor = 0;
117     int defaultPatchLevel = 0;
118     String defaultSnapshotInfo = "SNAPSHOT";
119 
120     int major = defaultMajor;
121     int minor = defaultMinor;
122     int patchLevel = defaultPatchLevel;
123     String snapshotInfo = defaultSnapshotInfo;
124 
125     String version = GeoJsonObjectMapperModule.class.getPackage().getImplementationVersion();
126     if (version != null) {
127       try {
128         int i = version.indexOf('-');
129         if (i < 0) {
130           snapshotInfo = null;
131         } else {
132           snapshotInfo = version.substring(i + 1);
133           String[] a = version.substring(0, i).split(Pattern.quote("."));
134           major = Integer.parseInt(a[0]);
135           minor = Integer.parseInt(a[1]);
136           patchLevel = Integer.parseInt(a[2]);
137         }
138 
139       } catch (RuntimeException e) {
140         major = defaultMajor;
141         minor = defaultMinor;
142         snapshotInfo = defaultSnapshotInfo;
143       }
144     }
145 
146     return new Version(major, minor, patchLevel, snapshotInfo, "org.bremersee",
147         "geojson");
148   }
149 
150   private static Map<Class<?>, JsonDeserializer<?>> getDeserializers(
151       GeometryFactory geometryFactory) {
152 
153     GeometryFactory gf = isNull(geometryFactory)
154         ? new GeoJsonGeometryFactory()
155         : geometryFactory;
156     HashMap<Class<?>, JsonDeserializer<?>> map = new HashMap<>();
157     map.put(Geometry.class, new JacksonGeometryDeserializer(gf));
158     map.put(Point.class, new JacksonGeometryDeserializer(gf));
159     map.put(LineString.class, new JacksonGeometryDeserializer(gf));
160     map.put(Polygon.class, new JacksonGeometryDeserializer(gf));
161     map.put(MultiPoint.class, new JacksonGeometryDeserializer(gf));
162     map.put(MultiLineString.class, new JacksonGeometryDeserializer(gf));
163     map.put(MultiPolygon.class, new JacksonGeometryDeserializer(gf));
164     map.put(GeometryCollection.class, new JacksonGeometryDeserializer(gf));
165     return map;
166   }
167 
168   private static List<JsonSerializer<?>> getSerializers(boolean withBoundingBox,
169       boolean useBigDecimal) {
170     ArrayList<JsonSerializer<?>> list = new ArrayList<>();
171     list.add(new JacksonGeometrySerializer(withBoundingBox, useBigDecimal));
172     return list;
173   }
174 
175 }