View Javadoc
1   /*
2    * Copyright (C) 2023 B3Partners B.V.
3    *
4    * SPDX-License-Identifier: MIT
5    */
6   package org.tailormap.api.persistence;
7   
8   import com.fasterxml.jackson.core.JsonProcessingException;
9   import com.fasterxml.jackson.databind.ObjectMapper;
10  import jakarta.persistence.Basic;
11  import jakarta.persistence.CascadeType;
12  import jakarta.persistence.Column;
13  import jakarta.persistence.Entity;
14  import jakarta.persistence.EntityListeners;
15  import jakarta.persistence.EnumType;
16  import jakarta.persistence.Enumerated;
17  import jakarta.persistence.GeneratedValue;
18  import jakarta.persistence.GenerationType;
19  import jakarta.persistence.Id;
20  import jakarta.persistence.JoinColumn;
21  import jakarta.persistence.JoinTable;
22  import jakarta.persistence.ManyToOne;
23  import jakarta.persistence.OneToMany;
24  import jakarta.persistence.OrderBy;
25  import jakarta.persistence.Table;
26  import jakarta.persistence.Transient;
27  import jakarta.persistence.Version;
28  import jakarta.validation.constraints.NotNull;
29  import java.util.ArrayList;
30  import java.util.List;
31  import org.hibernate.annotations.Type;
32  import org.tailormap.api.persistence.json.JDBCConnectionProperties;
33  import org.tailormap.api.persistence.json.ServiceAuthentication;
34  import org.tailormap.api.persistence.json.TMServiceCaps;
35  import org.tailormap.api.persistence.listener.EntityEventPublisher;
36  
37  @Entity
38  @Table(name = "feature_source")
39  @EntityListeners(EntityEventPublisher.class)
40  public class TMFeatureSource {
41  
42    public enum Protocol {
43      WFS("wfs"),
44  
45      JDBC("jdbc");
46  
47      private final String value;
48  
49      Protocol(String value) {
50        this.value = value;
51      }
52  
53      public String getValue() {
54        return value;
55      }
56  
57      @Override
58      public String toString() {
59        return String.valueOf(value);
60      }
61  
62      public static TMFeatureSource.Protocol fromValue(String value) {
63        for (TMFeatureSource.Protocol p : TMFeatureSource.Protocol.values()) {
64          if (p.value.equals(value)) {
65            return p;
66          }
67        }
68        throw new IllegalArgumentException("Unexpected value '" + value + "'");
69      }
70    }
71  
72    @Id
73    @GeneratedValue(strategy = GenerationType.IDENTITY)
74    private Long id;
75  
76    @Version
77    private Long version;
78  
79    @Transient
80    private boolean refreshCapabilities;
81  
82    @Column(columnDefinition = "text")
83    private String notes;
84  
85    @NotNull @Enumerated(EnumType.STRING)
86    private TMFeatureSource.Protocol protocol;
87  
88    @Basic
89    private String title;
90  
91    @Column(length = 2048)
92    private String url;
93  
94    @Type(value = io.hypersistence.utils.hibernate.type.json.JsonBinaryType.class)
95    @Column(columnDefinition = "jsonb")
96    private JDBCConnectionProperties jdbcConnection;
97  
98    @Type(value = io.hypersistence.utils.hibernate.type.json.JsonBinaryType.class)
99    @Column(columnDefinition = "jsonb")
100   private ServiceAuthentication authentication;
101 
102   @ManyToOne
103   @JoinColumn(name = "linked_service")
104   private GeoService linkedService;
105 
106   @Type(value = io.hypersistence.utils.hibernate.type.json.JsonBinaryType.class)
107   @Column(columnDefinition = "jsonb")
108   private TMServiceCaps serviceCapabilities;
109 
110   @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
111   @JoinTable(
112       name = "feature_source_feature_types",
113       inverseJoinColumns = @JoinColumn(name = "feature_type"),
114       joinColumns = @JoinColumn(name = "feature_source", referencedColumnName = "id"))
115   @OrderBy("name asc")
116   private List<TMFeatureType> featureTypes = new ArrayList<>();
117 
118   @Override
119   public String toString() {
120     try {
121       return "TMFeatureSource{"
122           + "id="
123           + id
124           + ", protocol="
125           + protocol
126           + ", title='"
127           + title
128           + '\''
129           + ", url='"
130           + url
131           + '\''
132           + ", jdbcConnection="
133           + new ObjectMapper().writeValueAsString(jdbcConnection)
134           + '}';
135     } catch (JsonProcessingException e) {
136       throw new RuntimeException(e);
137     }
138   }
139 
140   // <editor-fold desc="getters and setters">
141   public Long getId() {
142     return id;
143   }
144 
145   public TMFeatureSource setId(Long id) {
146     this.id = id;
147     return this;
148   }
149 
150   public Long getVersion() {
151     return version;
152   }
153 
154   public TMFeatureSource setVersion(Long version) {
155     this.version = version;
156     return this;
157   }
158 
159   public boolean isRefreshCapabilities() {
160     return refreshCapabilities;
161   }
162 
163   public void setRefreshCapabilities(boolean refreshCapabilities) {
164     this.refreshCapabilities = refreshCapabilities;
165   }
166 
167   public String getNotes() {
168     return notes;
169   }
170 
171   public TMFeatureSource setNotes(String notes) {
172     this.notes = notes;
173     return this;
174   }
175 
176   public Protocol getProtocol() {
177     return protocol;
178   }
179 
180   public TMFeatureSource setProtocol(Protocol protocol) {
181     this.protocol = protocol;
182     return this;
183   }
184 
185   public String getTitle() {
186     return title;
187   }
188 
189   public TMFeatureSource setTitle(String title) {
190     this.title = title;
191     return this;
192   }
193 
194   public String getUrl() {
195     return url;
196   }
197 
198   public TMFeatureSource setUrl(String url) {
199     this.url = url;
200     return this;
201   }
202 
203   public JDBCConnectionProperties getJdbcConnection() {
204     return jdbcConnection;
205   }
206 
207   public TMFeatureSource setJdbcConnection(JDBCConnectionProperties jdbcConnection) {
208     this.jdbcConnection = jdbcConnection;
209     return this;
210   }
211 
212   public ServiceAuthentication getAuthentication() {
213     return authentication;
214   }
215 
216   public TMFeatureSource setAuthentication(ServiceAuthentication authentication) {
217     this.authentication = authentication;
218     return this;
219   }
220 
221   public GeoService getLinkedService() {
222     return linkedService;
223   }
224 
225   public TMFeatureSource setLinkedService(GeoService linkedService) {
226     this.linkedService = linkedService;
227     return this;
228   }
229 
230   public TMServiceCaps getServiceCapabilities() {
231     return serviceCapabilities;
232   }
233 
234   public TMFeatureSource setServiceCapabilities(TMServiceCaps serviceCapabilities) {
235     this.serviceCapabilities = serviceCapabilities;
236     return this;
237   }
238 
239   // Added this extra getter to work around Spring Data Rest
240   // By adding a repository for feature types SDR does not add feature types when fetching a feature
241   // source, while the front-end currently depends on having all feature types available.
242   // In the future we could refactor this to give only a list of names and fetch the type itself
243   // when needed.
244   public List<TMFeatureType> getAllFeatureTypes() {
245     return featureTypes;
246   }
247 
248   public List<TMFeatureType> getFeatureTypes() {
249     return featureTypes;
250   }
251 
252   public TMFeatureSource setFeatureTypes(List<TMFeatureType> featureTypes) {
253     this.featureTypes = featureTypes;
254     return this;
255   }
256 
257   // </editor-fold>
258 
259   public TMFeatureType findFeatureTypeByName(String featureTypeName) {
260     return getFeatureTypes().stream()
261         .filter(ft -> featureTypeName.equals(ft.getName()))
262         .findFirst()
263         .orElse(null);
264   }
265 }