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 java.io.Serial;
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.regex.Pattern;
25  import org.bremersee.geojson.converter.deserialization.JacksonGeometryDeserializer;
26  import org.bremersee.geojson.converter.serialization.JacksonGeometrySerializer;
27  import org.locationtech.jts.geom.Geometry;
28  import org.locationtech.jts.geom.GeometryCollection;
29  import org.locationtech.jts.geom.GeometryFactory;
30  import org.locationtech.jts.geom.LineString;
31  import org.locationtech.jts.geom.MultiLineString;
32  import org.locationtech.jts.geom.MultiPoint;
33  import org.locationtech.jts.geom.MultiPolygon;
34  import org.locationtech.jts.geom.Point;
35  import org.locationtech.jts.geom.Polygon;
36  import tools.jackson.core.Version;
37  import tools.jackson.databind.ValueDeserializer;
38  import tools.jackson.databind.module.SimpleDeserializers;
39  import tools.jackson.databind.module.SimpleModule;
40  
41  /**
42   * A Jackson JSON processor module that provides the processing (serialization and deserialization)
43   * of the following types.
44   * <ul>
45   * <li>{@link Geometry}</li>
46   * <li>{@link Point}</li>
47   * <li>{@link LineString}</li>
48   * <li>{@link Polygon}</li>
49   * <li>{@link MultiPoint}</li>
50   * <li>{@link MultiLineString}</li>
51   * <li>{@link MultiPolygon}</li>
52   * <li>{@link GeometryCollection}</li>
53   * </ul>
54   *
55   * @author Christian Bremer
56   */
57  public class GeoJsonObjectMapperModule extends SimpleModule {
58  
59    @Serial
60    private static final long serialVersionUID = 1L;
61  
62    /**
63     * The constant TYPE_ID.
64     */
65    public static final String TYPE_ID = GeoJsonObjectMapperModule.class.getName();
66  
67    /**
68     * Default constructor.
69     */
70    public GeoJsonObjectMapperModule() {
71      this(new GeometryFactory());
72    }
73  
74    /**
75     * Instantiates a new geo json object mapper module.
76     *
77     * @param geometryFactory the geometry factory
78     */
79    public GeoJsonObjectMapperModule(GeometryFactory geometryFactory) {
80      this(geometryFactory, false, false);
81    }
82  
83    /**
84     * Instantiates a new geo json object mapper module.
85     *
86     * @param withBoundingBox with bounding box
87     * @param useBigDecimal the use big decimal
88     */
89    public GeoJsonObjectMapperModule(boolean withBoundingBox, boolean useBigDecimal) {
90      this(new GeometryFactory(), withBoundingBox, useBigDecimal);
91    }
92  
93    /**
94     * Instantiates a new geo json object mapper module.
95     *
96     * @param geometryFactory the geometry factory
97     * @param withBoundingBox the with bounding box
98     * @param useBigDecimal the use big decimal
99     */
100   public GeoJsonObjectMapperModule(
101       GeometryFactory geometryFactory,
102       boolean withBoundingBox,
103       boolean useBigDecimal) {
104 
105     super(TYPE_ID, getVersion());
106     setDeserializers(new SimpleDeserializers(getDeserializers(geometryFactory)));
107     addSerializer(Geometry.class, new JacksonGeometrySerializer(withBoundingBox, useBigDecimal));
108   }
109 
110   private static Version getVersion() {
111 
112     int defaultMajor = 6;
113     int defaultMinor = 0;
114     int defaultPatchLevel = 0;
115     String defaultSnapshotInfo = "SNAPSHOT";
116 
117     int major = defaultMajor;
118     int minor = defaultMinor;
119     int patchLevel = defaultPatchLevel;
120     String snapshotInfo = defaultSnapshotInfo;
121 
122     String version = GeoJsonObjectMapperModule.class.getPackage().getImplementationVersion();
123     if (version != null) {
124       try {
125         int i = version.indexOf('-');
126         if (i < 0) {
127           snapshotInfo = null;
128         } else {
129           snapshotInfo = version.substring(i + 1);
130           String[] a = version.substring(0, i).split(Pattern.quote("."));
131           major = Integer.parseInt(a[0]);
132           minor = Integer.parseInt(a[1]);
133           patchLevel = Integer.parseInt(a[2]);
134         }
135 
136       } catch (RuntimeException e) {
137         major = defaultMajor;
138         minor = defaultMinor;
139         snapshotInfo = defaultSnapshotInfo;
140       }
141     }
142 
143     return new Version(major, minor, patchLevel, snapshotInfo, "org.bremersee",
144         "geojson");
145   }
146 
147   private static Map<Class<?>, ValueDeserializer<?>> getDeserializers(
148       GeometryFactory geometryFactory) {
149 
150     GeometryFactory gf = isNull(geometryFactory)
151         ? new GeoJsonGeometryFactory()
152         : geometryFactory;
153     HashMap<Class<?>, ValueDeserializer<?>> map = new HashMap<>();
154     map.put(Geometry.class, new JacksonGeometryDeserializer(gf));
155     map.put(Point.class, new JacksonGeometryDeserializer(gf));
156     map.put(LineString.class, new JacksonGeometryDeserializer(gf));
157     map.put(Polygon.class, new JacksonGeometryDeserializer(gf));
158     map.put(MultiPoint.class, new JacksonGeometryDeserializer(gf));
159     map.put(MultiLineString.class, new JacksonGeometryDeserializer(gf));
160     map.put(MultiPolygon.class, new JacksonGeometryDeserializer(gf));
161     map.put(GeometryCollection.class, new JacksonGeometryDeserializer(gf));
162     return map;
163   }
164 
165 }