diff --git a/NOTICE b/NOTICE index e99ae3610..9a20039fe 100644 --- a/NOTICE +++ b/NOTICE @@ -21,17 +21,14 @@ This project includes: 52°North Faroe JSON Backend under The Apache Software License, Version 2.0 52°North Faroe Parent under The Apache Software License, Version 2.0 52°North Faroe Utilities under The Apache Software License, Version 2.0 - 52°North Iceland under The Apache Software License, Version 2.0 52°North Iceland Aggregator Project under The Apache Software License, Version 2.0 52°North Iceland Statistics under The Apache Software License, Version 2.0 52°North Iceland Statistics Documentation Generator under The Apache Software License, Version 2.0 52°North Iceland Statistics Geolocation Feature under The Apache Software License, Version 2.0 52°North Iceland Statistics Kibana Exporter Tool under The Apache Software License, Version 2.0 52°North Jan Mayen under The Apache Software License, Version 2.0 - 52°North Shetland under The Apache Software License, Version 2.0 52°North Shetland Parent under The Apache Software License, Version 2.0 52°North Shetland RDF under The Apache Software License, Version 2.0 - 52°North Svalbard Core under The Apache Software License, Version 2.0 52°North Svalbard Exi under The Apache Software License, Version 2.0 52°North Svalbard JSON Common under The Apache Software License, Version 2.0 52°North Svalbard JSON encoding under The Apache Software License, Version 2.0 @@ -42,25 +39,19 @@ This project includes: aggs-matrix-stats under Elastic License 2.0 or Server Side Public License, v 1 ANTLR 4 Runtime under The BSD License Apache Commons CLI under Apache License, Version 2.0 - Apache Commons Codec under Apache License, Version 2.0 Apache Commons Compress under Apache License, Version 2.0 Apache Commons CSV under Apache License, Version 2.0 Apache Commons IO under Apache License, Version 2.0 Apache HttpAsyncClient under Apache License, Version 2.0 - Apache HttpClient under Apache License, Version 2.0 Apache HttpClient Cache under Apache License, Version 2.0 - Apache HttpCore under Apache License, Version 2.0 Apache HttpCore NIO under Apache License, Version 2.0 Apache Jena - ARQ (SPARQL 1.1 Query Engine) under The Apache Software License, Version 2.0 Apache Jena - Base Common Environment under The Apache Software License, Version 2.0 Apache Jena - Core under The Apache Software License, Version 2.0 Apache Jena - IRI under The Apache Software License, Version 2.0 Apache Jena - Shadowed external libraries under The Apache Software License, Version 2.0 - Apache Log4j API under Apache License, Version 2.0 Apache Thrift under The Apache Software License, Version 2.0 - c3p0 under GNU Lesser General Public License, Version 2.1 or Eclipse Public License, Version 1.0 Checker Qual under The MIT License - Commons Lang under The Apache Software License, Version 2.0 compiler under Apache License 2.0 dexx under MIT License elasticsearch-cli under Elastic License 2.0 or Server Side Public License, v 1 @@ -72,6 +63,7 @@ This project includes: elasticsearch-x-content under Elastic License 2.0 or Server Side Public License, v 1 embedded-elasticsearch under The Apache Software License, Version 2.0 error-prone annotations under Apache 2.0 + faroe-rest under The Apache Software License, Version 2.0 FindBugs-jsr305 under The Apache Software License, Version 2.0 Geographic Common (GCO) schema (version 2012-07-13) under The Apache Software License, Version 2.0 Geographic MetaData (GMD) schema (version 2012-07-13) under The Apache Software License, Version 2.0 @@ -79,7 +71,6 @@ This project includes: Guava ListenableFuture only under The Apache Software License, Version 2.0 Guava: Google Core Libraries for Java under Apache License, Version 2.0 HdrHistogram under Public Domain, per Creative Commons CC0 - HikariCP under The Apache Software License, Version 2.0 HPPC Collections under The Apache Software License, Version 2.0 INSPIRE Addresses schema (spec. v4.0) under The Apache Software License, Version 2.0 INSPIRE Administrative Units schema (spec. v4.0) under The Apache Software License, Version 2.0 @@ -98,17 +89,18 @@ This project includes: J2ObjC Annotations under The Apache Software License, Version 2.0 Jackson dataformat: CBOR under The Apache Software License, Version 2.0 Jackson dataformat: Smile under The Apache Software License, Version 2.0 + Jackson datatype: jdk8 under The Apache Software License, Version 2.0 Jackson-annotations under The Apache Software License, Version 2.0 Jackson-core under The Apache Software License, Version 2.0 jackson-databind under The Apache Software License, Version 2.0 Jackson-dataformat-YAML under The Apache Software License, Version 2.0 + Jackson-datatype-Hibernate5 under The Apache Software License, Version 2.0 Java archiving library under Apache 2 - JavaBeans(TM) Activation Framework under COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 JavaMail API jar under CDDL or GPLv2+CE javax.annotation API under CDDL + GPLv2 with classpath exception javax.inject under The Apache Software License, Version 2.0 + javax.transaction API under CDDL + GPLv2 with classpath exception jaxb-api under CDDL 1.1 or GPL2 w/ CPE - JCL 1.2 implemented over SLF4J under Apache License, Version 2.0 Joda-Time under Apache License, Version 2.0 JOpt Simple under The MIT License JSONLD Java :: Core under Revised BSD License @@ -129,7 +121,6 @@ This project includes: mapper-extras under Elastic License 2.0 or Server Side Public License, v 1 MaxMind DB Reader under Apache License 2.0 MaxMind GeoIP2 API under Apache License, Version 2.0 - mchange-commons-java under GNU Lesser General Public License, Version 2.1 or Eclipse Public License, Version 1.0 Neo Visionaries Internationalization Package under The Apache Software License, Version 2.0 Netty/Buffer under Apache License, Version 2.0 Netty/Codec under Apache License, Version 2.0 @@ -137,8 +128,8 @@ This project includes: Netty/Common under Apache License, Version 2.0 Netty/Handler under Apache License, Version 2.0 Netty/Resolver under Apache License, Version 2.0 - Netty/TomcatNative [OpenSSL - Classes] under The Apache Software License, Version 2.0 Netty/Transport under Apache License, Version 2.0 + Netty/Transport/Native/Unix/Common under Apache License, Version 2.0 null under Lesser General Public License, version 3 or greater or Apache Software License, version 2.0 OASIS WS-N specification schemas - including WS-BrokeredNotification (v1.3) under The Apache Software License, Version 2.0 OASIS WS-Resources specification schemas v1.2 under The Apache Software License, Version 2.0 @@ -178,35 +169,26 @@ This project includes: OGC WaterML DR schema (spec. v2.0) under The Apache Software License, Version 2.0 OGC WaterML schema (spec. v2.0) under The Apache Software License, Version 2.0 OGC XML schemas under The Apache Software License, Version 2.0 - Old JAXB Core under CDDL+GPL License - Old JAXB Runtime under CDDL+GPL License - org.locationtech.jts:jts-core under Eclipse Public License, Version 2.0 or Eclipse Distribution License - v 1.0 parent-join under Elastic License 2.0 or Server Side Public License, v 1 Portele Schape Change schema (spec. v3.0) under The Apache Software License, Version 2.0 - quartz under The Apache Software License, Version 2.0 rank-eval under Elastic License 2.0 or Server Side Public License, v 1 rest under The Apache Software License, Version 2.0 rest-high-level under Elastic License 2.0 Saxon-HE under Mozilla Public License Version 2.0 server under Elastic License 2.0 or Server Side Public License, v 1 SLF4J API Module under MIT License - SnakeYAML under Apache License, Version 2.0 Spring AOP under Apache License, Version 2.0 - Spring Beans under Apache License, Version 2.0 Spring Commons Logging Bridge under Apache License, Version 2.0 - Spring Context under Apache License, Version 2.0 Spring Context Support under Apache License, Version 2.0 Spring Core under Apache License, Version 2.0 Spring Expression Language (SpEL) under Apache License, Version 2.0 - Spring Web under Apache License, Version 2.0 + Spring Web MVC under Apache License, Version 2.0 T-Digest under The Apache Software License, Version 2.0 W3C SOAP specification recommondation (v1.1) under The Apache Software License, Version 2.0 W3C SOAP specification recommondation (v1.2 part 1) under The Apache Software License, Version 2.0 W3C WS-Addressing specification schemas (v1.0) under The Apache Software License, Version 2.0 W3C xlink schema (spec. v1.1.0) under The Apache Software License, Version 2.0 - XML Commons External Components XML APIs under The Apache Software License, Version 2.0 or The SAX License or The W3C License XML Resolver under Apache License version 2.0 - XmlBeans under The Apache Software License, Version 2.0 XmlBeansXPath under The Apache Software License, Version 2.0 XMLUnit for Java under BSD License diff --git a/README.md b/README.md index 42eaa8a0f..f8cf7029b 100644 --- a/README.md +++ b/README.md @@ -237,3 +237,12 @@ The development of the 52°North Arctic Sea implementation was supported by se | [![BMVI](https://raw.githubusercontent.com/52North/arctic-sea/master/etc/images/bmvi-logo.png)](https://www.bmvi.de/)[![mFund](https://raw.githubusercontent.com/52North/arctic-sea/master/etc/images/mfund-logo.jpg)](https://www.bmvi.de/DE/Themen/Digitales/mFund/Ueberblick/ueberblick.html)[![WaCoDis](https://raw.githubusercontent.com/52North/arctic-sea/master/etc/images/wacodis-logo.png)](http://wacodis.fbg-hsbo.de/) | The development of this version of 52°North Arctic Sea was supported by the [German Federal Ministry of of Transport and Digital Infrastructure](https://www.bmvi.de/) research project [WaCoDis](http://wacodis.fbg-hsbo.de/) (co-funded by the German Federal Ministry of Transport and Digital Infrastructure, programme mFund) | | [![BMBF](https://raw.githubusercontent.com/52North/arctic-sea/master/etc/images/bmbf-logo.png)](https://www.bmbf.de/)[![fona](https://raw.githubusercontent.com/52North/arctic-sea/master/etc/images/fona-logo.png)](https://www.fona.de/)[![MuDak-WRM](https://raw.githubusercontent.com/52North/arctic-sea/master/etc/images/mudak-wrm-logo.png)](http://www.mudak-wrm.kit.edu/) | The development of this version of 52°North Arctic Sea was supported by the [German Federal Ministry of Education and Research](https://www.bmbf.de/) research project [MuDak-WRM](http://www.mudak-wrm.kit.edu/) (co-funded by the German Federal Ministry of Education and Research, programme [fona](https://www.fona.de/)) | | [![BRIDGES](https://raw.githubusercontent.com/52North/arctic-sea/master/etc/images/bridges-logo.jpg)](http://www.bridges-h2020.eu/)| The development of this version of the 52°North Arctic Sea was supported by the [Horizon 2020](https://ec.europa.eu/programmes/horizon2020/) research project [BRIDGES](http://www.bridges-h2020.eu/) (co-funded by the European Commission under the grant agreement n°635359) + +
+ +## Steps to Run Faroe REST Backend---------> + + - 1. Open the project in a Java IDE (Ecplise or intellij) + - 2. Go to the faroe--->rest--->src/main/java/--->org.n52.faroeREST.springrest--->SpringrestApplication.java + - 3. Run this file as a Java Application + - (The above steps aresufficient, however, If you encounter any error, then try: maven clean ---> maven build ---> update project---> and repeat step 3) \ No newline at end of file diff --git a/faroe/core/pom.xml b/faroe/core/pom.xml index 37e3b6a4e..0b45f661e 100644 --- a/faroe/core/pom.xml +++ b/faroe/core/pom.xml @@ -54,6 +54,10 @@ com.fasterxml.jackson.core jackson-databind + + com.fasterxml.jackson.core + jackson-annotations + javax.inject javax.inject diff --git a/faroe/core/src/main/java/org/n52/faroe/JSONSettingConstants.java b/faroe/core/src/main/java/org/n52/faroe/JSONSettingConstants.java index 4f6ae71ec..c973aed0a 100644 --- a/faroe/core/src/main/java/org/n52/faroe/JSONSettingConstants.java +++ b/faroe/core/src/main/java/org/n52/faroe/JSONSettingConstants.java @@ -46,5 +46,5 @@ public interface JSONSettingConstants { String FILE_TYPE = "file"; String URI_TYPE = "uri"; - + String SETTING_DEFINITIONS = "settingDefinitions"; } diff --git a/faroe/core/src/main/java/org/n52/faroe/SettingDefinition.java b/faroe/core/src/main/java/org/n52/faroe/SettingDefinition.java index 5999e2b94..673a0f97e 100644 --- a/faroe/core/src/main/java/org/n52/faroe/SettingDefinition.java +++ b/faroe/core/src/main/java/org/n52/faroe/SettingDefinition.java @@ -18,24 +18,56 @@ import java.io.Serializable; import java.util.Optional; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import org.n52.faroe.settings.BooleanSettingDefinition; +import org.n52.faroe.settings.ChoiceSettingDefinition; +import org.n52.faroe.settings.DateTimeSettingDefinition; +import org.n52.faroe.settings.FileSettingDefinition; +import org.n52.faroe.settings.IntegerSettingDefinition; +import org.n52.faroe.settings.MultilingualStringSettingDefinition; +import org.n52.faroe.settings.NumericSettingDefinition; +import org.n52.faroe.settings.StringSettingDefinition; +import org.n52.faroe.settings.UriSettingDefinition; + /** - * * Interface for setting definitions that can be used within the Service. Defined settings will be presented in the * administrator and installer view. * + * @param The type of the value + * @author Christian Autermann * @see SettingDefinitionGroup * @see SettingsService * @see org.n52.faroe.settings.FileSettingDefinition - * @see org.n52.faroe.settings.BooleanSettingDefinition + * @see BooleanSettingDefinition * @see org.n52.faroe.settings.IntegerSettingDefinition * @see org.n52.faroe.settings.NumericSettingDefinition * @see org.n52.faroe.settings.StringSettingDefinition * @see org.n52.faroe.settings.UriSettingDefinition - * @param The type of the value - * - * @author Christian Autermann * @since 1.0.0 */ +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") +@JsonSubTypes(value = { + @JsonSubTypes.Type(value = BooleanSettingDefinition.class, + name = JSONSettingConstants.BOOLEAN_TYPE), + @JsonSubTypes.Type(value = StringSettingDefinition.class, + name = JSONSettingConstants.STRING_TYPE), + @JsonSubTypes.Type(value = ChoiceSettingDefinition.class, + name = JSONSettingConstants.CHOICE_TYPE), + @JsonSubTypes.Type(value = DateTimeSettingDefinition.class, + name = JSONSettingConstants.TIME_INSTANT_TYPE), + @JsonSubTypes.Type(value = FileSettingDefinition.class, + name = JSONSettingConstants.FILE_TYPE), + @JsonSubTypes.Type(value = IntegerSettingDefinition.class, + name = JSONSettingConstants.INTEGER_TYPE), + @JsonSubTypes.Type(value = MultilingualStringSettingDefinition.class, + name = JSONSettingConstants.MULTILINGUAL_TYPE), + @JsonSubTypes.Type(value = NumericSettingDefinition.class, + name = JSONSettingConstants.NUMBER_TYPE), + @JsonSubTypes.Type(value = UriSettingDefinition.class, + name = JSONSettingConstants.URI_TYPE) +}) public interface SettingDefinition extends Ordered, Serializable { /** * @return the unique key of this definition @@ -53,7 +85,7 @@ public interface SettingDefinition extends Ordered, Serializable { String getDescription(); /** - * @return wether this setting is optional or required. + * @return weather this setting is optional or required. */ boolean isOptional(); @@ -62,6 +94,7 @@ public interface SettingDefinition extends Ordered, Serializable { */ T getDefaultValue(); + @JsonIgnore default Optional getOptionalDefaultValue() { if (hasDefaultValue()) { return Optional.of(getDefaultValue()); @@ -125,7 +158,6 @@ default SettingDefinitionGroup getGroup(SettingDefinitionGroup defaultGroup) { * Sets whether this setting is optional or can be null. By default all settings are required. * * @param optional if this setting is optional - * */ SettingDefinition setOptional(boolean optional); @@ -147,5 +179,6 @@ default SettingDefinitionGroup getGroup(SettingDefinitionGroup defaultGroup) { /** * @return the type of the value of this definition */ + @JsonIgnore SettingType getType(); } diff --git a/faroe/core/src/main/java/org/n52/faroe/SettingType.java b/faroe/core/src/main/java/org/n52/faroe/SettingType.java index b4f41484d..26a93fbd5 100644 --- a/faroe/core/src/main/java/org/n52/faroe/SettingType.java +++ b/faroe/core/src/main/java/org/n52/faroe/SettingType.java @@ -18,6 +18,8 @@ import java.io.File; import java.net.URI; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; import org.joda.time.DateTime; import org.n52.janmayen.i18n.LocalizedString; @@ -69,6 +71,7 @@ public enum SettingType { */ CHOICE; + @JsonCreator public static SettingType fromString(String type) { switch (type) { case JSONSettingConstants.INTEGER_TYPE: @@ -120,6 +123,7 @@ public static String toString(SettingType type) { } @Override + @JsonValue public String toString() { return toString(this); } diff --git a/faroe/core/src/main/java/org/n52/faroe/SettingValue.java b/faroe/core/src/main/java/org/n52/faroe/SettingValue.java index 6783487ba..36c6903ae 100644 --- a/faroe/core/src/main/java/org/n52/faroe/SettingValue.java +++ b/faroe/core/src/main/java/org/n52/faroe/SettingValue.java @@ -17,6 +17,8 @@ import java.io.Serializable; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + /** * Holder for generic settings. Implementations are {@link SettingsService} specific. * diff --git a/faroe/core/src/main/java/org/n52/faroe/SettingsChangeEvent.java b/faroe/core/src/main/java/org/n52/faroe/SettingsChangeEvent.java index afdc796ea..5efa92479 100644 --- a/faroe/core/src/main/java/org/n52/faroe/SettingsChangeEvent.java +++ b/faroe/core/src/main/java/org/n52/faroe/SettingsChangeEvent.java @@ -31,12 +31,22 @@ public class SettingsChangeEvent implements Event { private final SettingDefinition setting; + private final String settings; private final SettingValue oldValue; private final SettingValue newValue; @SuppressFBWarnings({"EI_EXPOSE_REP2"}) public SettingsChangeEvent(SettingDefinition setting, SettingValue oldValue, SettingValue newValue) { this.setting = setting; + this.settings = null; + this.oldValue = oldValue; + this.newValue = newValue; + } + + + public SettingsChangeEvent(String settings, SettingValue oldValue, SettingValue newValue) { + this.setting = null; + this.settings = settings; this.oldValue = oldValue; this.newValue = newValue; } @@ -45,6 +55,10 @@ public SettingDefinition getSetting() { return setting; } + public String getSettings() { + return settings; + } + @SuppressFBWarnings({"EI_EXPOSE_REP"}) public SettingValue getOldValue() { return oldValue; @@ -65,7 +79,8 @@ public boolean hasOldValue() { @Override public String toString() { - return String.format("SettingsChangeEvent[setting=%s, oldValue=%s, newValue=%s", - getSetting(), getOldValue(), getNewValue()); + return String.format("SettingsChangeEvent[setting=%s, settings=%s, oldValue=%s, newValue=%s", + getSetting(), getSettings(), getOldValue(), getNewValue()); } + } diff --git a/faroe/core/src/main/java/org/n52/faroe/SettingsDao.java b/faroe/core/src/main/java/org/n52/faroe/SettingsDao.java index 352433605..9e2e46d3e 100644 --- a/faroe/core/src/main/java/org/n52/faroe/SettingsDao.java +++ b/faroe/core/src/main/java/org/n52/faroe/SettingsDao.java @@ -51,6 +51,7 @@ public interface SettingsDao { */ void saveSettingValue(SettingValue setting); + void deleteAll(); } diff --git a/faroe/core/src/main/java/org/n52/faroe/SettingsDefinitionDao.java b/faroe/core/src/main/java/org/n52/faroe/SettingsDefinitionDao.java new file mode 100644 index 000000000..08a136aa3 --- /dev/null +++ b/faroe/core/src/main/java/org/n52/faroe/SettingsDefinitionDao.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2015-2022 52°North Spatial Information Research GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.n52.faroe; + +import java.util.Collection; + +public interface SettingsDefinitionDao extends SettingsDao { + + Collection> getAllSettings(); + + void saveSettings(Collection> settings); + +} diff --git a/faroe/core/src/main/java/org/n52/faroe/SettingsService.java b/faroe/core/src/main/java/org/n52/faroe/SettingsService.java index d22c658d5..38a78fca8 100644 --- a/faroe/core/src/main/java/org/n52/faroe/SettingsService.java +++ b/faroe/core/src/main/java/org/n52/faroe/SettingsService.java @@ -72,6 +72,8 @@ public interface SettingsService { */ void deleteSetting(SettingDefinition setting) throws ConfigurationError; + + public void deleteSetting(String setting) throws ConfigurationError; /** * Get the definition that is defined with the specified key. * @@ -82,7 +84,7 @@ public interface SettingsService { SettingDefinition getDefinitionByKey(String key); /** - * @return the keys for all definitions + * @return the titles for all definitions */ Set getKeys(); @@ -136,4 +138,5 @@ public interface SettingsService { void addSettings(Collection> defs); + } diff --git a/faroe/core/src/main/java/org/n52/faroe/SettingsServiceImpl.java b/faroe/core/src/main/java/org/n52/faroe/SettingsServiceImpl.java index eb4a676fb..cc056d7b6 100644 --- a/faroe/core/src/main/java/org/n52/faroe/SettingsServiceImpl.java +++ b/faroe/core/src/main/java/org/n52/faroe/SettingsServiceImpl.java @@ -35,7 +35,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.inject.Inject; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -84,7 +83,7 @@ public void setSettingValueFactory(SettingValueFactory settingValueFactory) { @Inject @SuppressFBWarnings({ "EI_EXPOSE_REP2" }) - public void setSettingsManagerDao(SettingsDao settingsManagerDao) { + public void setSettingsManagerDao(SettingsDao settingsManagerDao) { this.settingsManagerDao = settingsManagerDao; } @@ -285,6 +284,16 @@ public void deleteSetting(SettingDefinition setting) throws ConfigurationErro } } + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void deleteSetting(String setting) throws ConfigurationError { + SettingValue oldValue = this.settingsManagerDao.getSettingValue(setting); + if (oldValue != null) { + applySetting(setting, oldValue, null); + this.settingsManagerDao.deleteSettingValue(setting); + this.serviceEventBus.submit(new SettingsChangeEvent(setting, oldValue, null)); + } + } + /** * @return the keys for all definitions */ @@ -345,6 +354,45 @@ private void applySetting(SettingDefinition setting, SettingValue oldValue } } + private void applySetting(String setting, SettingValue oldValue, SettingValue newValue) + throws ConfigurationError { + List changed = new LinkedList<>(); + ConfigurationError e = null; + configurableObjectsLock.readLock().lock(); + try { + Set cos = configurableObjects.get(setting); + if (cos != null) { + for (ConfigurableObject co : cos) { + try { + if (newValue != null) { + co.configure(newValue.getValue()); + } + } catch (ConfigurationError ce) { + e = ce; + break; + } finally { + changed.add(co); + } + } + if (e != null) { + LOG.debug("Reverting setting..."); + changed.stream().forEach(co -> { + try { + co.configure(oldValue.getValue()); + } catch (ConfigurationError ce) { + /* there is nothing we can do... */ + LOG.error("Error reverting setting!", ce); + } + }); + throw e; + } + } + } finally { + configurableObjectsLock.readLock().unlock(); + } + } + + private SettingValue getSettingValue(ConfigurableObject co) { return getSettingValue(co.getKey(), co.isRequired()); } diff --git a/faroe/json/pom.xml b/faroe/json/pom.xml index bca1fa530..5e6a94beb 100644 --- a/faroe/json/pom.xml +++ b/faroe/json/pom.xml @@ -43,6 +43,18 @@ com.fasterxml.jackson.core jackson-databind + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + org.slf4j slf4j-api diff --git a/faroe/json/src/main/java/org/n52/faroe/json/CRUDSettingsDao.java b/faroe/json/src/main/java/org/n52/faroe/json/CRUDSettingsDao.java new file mode 100644 index 000000000..293fb7af1 --- /dev/null +++ b/faroe/json/src/main/java/org/n52/faroe/json/CRUDSettingsDao.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015-2022 52°North Spatial Information Research GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.n52.faroe.json; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import org.n52.faroe.JSONSettingConstants; +import org.n52.faroe.SettingDefinition; +import org.n52.faroe.SettingsDefinitionDao; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class CRUDSettingsDao extends JsonSettingsDao implements SettingsDefinitionDao { + + private final ObjectMapper objectMapper = createObjectMapper(); + + @Override + public Collection> getAllSettings() { + readLock().lock(); + + try { + ObjectNode settings = getConfiguration().with(JSONSettingConstants.SETTING_DEFINITIONS); + List> list = new ArrayList<>(settings.size()); + for (JsonNode setting : settings) { + list.add(objectMapper.treeToValue(setting, SettingDefinition.class)); + } + return list; + + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } finally { + readLock().unlock(); + } + } + + @Override + public void saveSettings(Collection> settings) { + settings.forEach(this::saveSetting); + } + + private void saveSetting(SettingDefinition setting) { + writeLock().lock(); + try { + ObjectNode settings = getConfiguration().with(JSONSettingConstants.SETTING_DEFINITIONS); + settings.set(setting.getKey(), objectMapper.valueToTree(setting)); + } finally { + writeLock().unlock(); + } + configuration().scheduleWrite(); + } + + private static ObjectMapper createObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new Jdk8Module()); + return mapper; + } +} diff --git a/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingValue.java b/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingValue.java index 7fa6e2bf8..137a5dc12 100644 --- a/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingValue.java +++ b/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingValue.java @@ -17,12 +17,13 @@ import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.n52.faroe.SettingType; import org.n52.faroe.SettingValue; import com.google.common.base.MoreObjects; - /** * TODO JavaDoc * @@ -35,7 +36,10 @@ public class JsonSettingValue implements SettingValue { private String key; private T value; - public JsonSettingValue(SettingType type, String key, T value) { + @JsonCreator + public JsonSettingValue(@JsonProperty("type") SettingType type, + @JsonProperty("key") String key, + @JsonProperty("value") T value) { this.type = type; this.key = key; this.value = value; @@ -94,9 +98,9 @@ public int hashCode() { @Override public String toString() { return MoreObjects.toStringHelper(this) - .add("type", getType()) - .add("key", getKey()) - .add("value", getValue()) - .toString(); + .add("type", getType()) + .add("key", getKey()) + .add("value", getValue()) + .toString(); } } diff --git a/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingsDao.java b/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingsDao.java index a9e9d7551..05d5d12db 100644 --- a/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingsDao.java +++ b/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingsDao.java @@ -15,17 +15,15 @@ */ package org.n52.faroe.json; -import java.util.Optional; -import java.util.Set; - -import javax.inject.Inject; - +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.n52.faroe.JSONSettingConstants; import org.n52.faroe.SettingValue; import org.n52.faroe.SettingsDao; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; +import javax.inject.Inject; +import java.util.Optional; +import java.util.Set; /** * @@ -36,6 +34,7 @@ public class JsonSettingsDao extends AbstractJsonDao implements SettingsDao { private JsonSettingsEncoder settingsEncoder; private JsonSettingsDecoder settingsDecoder; + @Inject public void setSettingsEncoder(JsonSettingsEncoder settingsEncoder) { this.settingsEncoder = settingsEncoder; @@ -47,7 +46,7 @@ protected JsonSettingsEncoder getSettingsEncoder() { @Inject public void setSettingsDecoder(Optional settingsDecoder) { - this.settingsDecoder = settingsDecoder.isPresent() ? settingsDecoder.get() : new JsonSettingsDecoder(); + this.settingsDecoder = settingsDecoder.orElseGet(JsonSettingsDecoder::new); } protected JsonSettingsDecoder getSettingsDecoder() { @@ -110,4 +109,6 @@ public void saveSettingValue(SettingValue value) { public void deleteAll() { this.configuration().delete(); } + + } diff --git a/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingsFile.java b/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingsFile.java new file mode 100644 index 000000000..55253ba3d --- /dev/null +++ b/faroe/json/src/main/java/org/n52/faroe/json/JsonSettingsFile.java @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2015-2022 52°North Spatial Information Research GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.n52.faroe.json; + + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.n52.faroe.ConfigurationError; +import org.n52.faroe.FileSettingsConfiguration; +import org.n52.janmayen.ConfigLocationProvider; +import org.n52.janmayen.Debouncer; +import org.n52.janmayen.Json; +import org.n52.janmayen.Producer; +import org.n52.janmayen.lifecycle.Destroyable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +public class JsonSettingsFile implements Destroyable, +Producer, +FileSettingsConfiguration{ + + private static final Logger LOG = LoggerFactory.getLogger(JsonSettingsFile.class); + private static final String DEFAULT_FILE_NAME = "settings.json"; + private static final int DEFAULT_WRITE_TIMEOUT = 1000; + private static final String CONFIG_PATH = "config"; + private static final String WEB_INF_PATH = "WEB-INF"; + private String fileName = DEFAULT_FILE_NAME; + private int writeTimeout = DEFAULT_WRITE_TIMEOUT; + private Debouncer debouncer; + private ObjectNode settings; + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private File file; + private boolean readonly; + private ConfigLocationProvider configLocationProvider; + private final JsonNodeFactory nodeFactory = Json.nodeFactory(); + + public void init() { + writeLock().lock(); + try { + this.debouncer = new Debouncer(this.writeTimeout, this::persist); + Path path = buildPath(); + Path parent = path.getParent(); + if (parent != null) { + if (!Files.isSymbolicLink(parent)) { + Files.createDirectories(parent); + } + } else { + throw new RuntimeException("Error while creating config file path."); + } + this.file = path.toFile(); + this.refresh(); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + writeLock().unlock(); + } + } + + private Path buildPath() { + if (configLocationProvider != null && configLocationProvider.get() != null) { + return Paths.get(configLocationProvider.get(), WEB_INF_PATH, CONFIG_PATH, this.fileName); + } + return Paths.get(WEB_INF_PATH, CONFIG_PATH, this.fileName); + } + + private synchronized void persist() { + if (!readonly) { + readLock().lock(); + try { + LOG.debug("Writing configuration file"); + try (FileOutputStream fos = new FileOutputStream(this.file)) { + Json.print(fos, this.settings); + } + } catch (IOException e) { + throw new ConfigurationError("Could not persist configuration", e); + } finally { + readLock().unlock(); + } + } + } + + public void delete() { + writeLock().lock(); + try { + if (this.file.exists() && this.file.isFile()) { + if (!this.file.delete()) { + throw new ConfigurationError("Can not delete configuration file %s", file + .getAbsolutePath()); + } + } + } finally { + writeLock().unlock(); + } + } + + public void setWriteTimeout(int writeTimeout) { + this.writeTimeout = writeTimeout; + } + + + public synchronized void setReadonly(boolean readonly) { + this.readonly = readonly; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public void setConfigLocationProvider(ConfigLocationProvider configLocationProvider) { + this.configLocationProvider = configLocationProvider; + } + + + @Override + public Path getPath() { + return this.file.toPath(); + } + + public Lock readLock() { + return this.lock.readLock(); + } + + public Lock writeLock() { + return this.lock.writeLock(); + } + + public void scheduleWrite() { + this.debouncer.call(); + } + + + @Override + public void refresh() { + writeLock().lock(); + try { + this.settings = readSettings(this.file) + .orElseGet(nodeFactory::objectNode); + } finally { + writeLock().unlock(); + } + } + + private Optional readSettings(File f) { + if (!f.exists()) { + return Optional.empty(); + } + if (!f.isFile()) { + throw new ConfigurationError("%s is not a file", f.getAbsolutePath()); + } + if (!f.canRead()) { + throw new ConfigurationError("%s is not a readable file", f.getAbsolutePath()); + } + try { + JsonNode node = Json.loadFile(f); + if (!node.isObject()) { + throw new ConfigurationError("%s does not contain a JSON object", f.getAbsolutePath()); + } + return Optional.of((ObjectNode) node); + } catch (IOException ex) { + throw new ConfigurationError("Could not read " + f.getAbsolutePath(), ex); + } + } + + @SuppressFBWarnings({"EI_EXPOSE_REP2"}) + public void set(ObjectNode settings) { + this.settings = settings; + } + + + @Override + public ObjectNode get() { + return this.settings; + } + + + @Override + public void destroy() { + LOG.info("Destroying {}", System.identityHashCode(this)); + this.debouncer.finish(); + } + public String toString() { + return "JsonConfiguration{" + "file=" + file + '}'; + } + +} diff --git a/faroe/pom.xml b/faroe/pom.xml index 7739dd66d..64c7a2bf6 100644 --- a/faroe/pom.xml +++ b/faroe/pom.xml @@ -32,5 +32,6 @@ core annotations utils + rest diff --git a/faroe/rest/.gitignore b/faroe/rest/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/faroe/rest/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/faroe/rest/WEB-INF/config/configuration.json b/faroe/rest/WEB-INF/config/configuration.json new file mode 100644 index 000000000..1001ff1bd --- /dev/null +++ b/faroe/rest/WEB-INF/config/configuration.json @@ -0,0 +1,62 @@ +{ + "settingDefinitions" : { + "serviceProvider.isrequired" : { + "type" : "boolean", + "order" : 0.0, + "optional" : true, + "title" : "Required", + "description" : "Is this field required", + "group" : { + "order" : 0.0, + "title" : "Service Provider", + "description" : null, + "showInDefaultSettings" : true + }, + "defaultValue" : true, + "key" : "serviceProvider.isrequired", + "optionalDefaultValue" : true + }, + "serviceProvider.eval" : { + "type" : "boolean", + "order" : 0.0, + "optional" : true, + "title" : "Eval", + "description" : "Project eval for GSOC22", + "group" : { + "order" : 0.0, + "title" : "Service Provider", + "description" : null, + "showInDefaultSettings" : true + }, + "defaultValue" : false, + "key" : "serviceProvider.eval", + "optionalDefaultValue" : false + }, + "serviceProvider.evaluation" : { + "type" : "string", + "order" : 0.0, + "optional" : true, + "title" : "Eval", + "description" : "Project eval for GSOC22", + "group" : { + "order" : 0.0, + "title" : "Service Provider", + "description" : null, + "showInDefaultSettings" : true + }, + "defaultValue" : "Pass/Fail", + "key" : "serviceProvider.evaluation", + "optionalDefaultValue" : "Pass/Fail" + } + }, + "settings" : { + "serviceProvider.isrequired" : { + "type" : "boolean", + "value" : false + }, + "serviceProvider.eval" : { + "type" : "boolean", + "value" : true + } + } +} \ No newline at end of file diff --git a/faroe/rest/pom.xml b/faroe/rest/pom.xml new file mode 100644 index 000000000..6b427451d --- /dev/null +++ b/faroe/rest/pom.xml @@ -0,0 +1,157 @@ + + + + 4.0.0 + + org.n52.arctic-sea + faroe-parent + 9.7.0-SNAPSHOT + + org.n52.arctic-sea + faroe-rest + faroe-rest + REST API for Arctic Sea + + + org.springframework.boot + spring-boot-starter-web + provided + + + org.springframework.boot + spring-boot-test + provided + + + org.springframework.boot + spring-boot + provided + + + org.springframework.boot + spring-boot-autoconfigure + provided + + + org.springframework.boot + spring-boot-starter-test + provided + + + org.springframework + spring-web + provided + + + org.springframework + spring-context + provided + + + org.springframework + spring-beans + provided + + + ${project.groupId} + faroe + ${project.version} + provided + + + ${project.groupId} + faroe-json + provided + + + ${project.groupId} + faroe-utils + provided + + + org.junit.jupiter + junit-jupiter-api + test + + + ${project.groupId} + iceland + provided + + + javax.inject + javax.inject + provided + + + joda-time + joda-time + + + com.fasterxml.jackson.datatype + jackson-datatype-hibernate5 + + + javax.enterprise + cdi-api + + + runtime + + + javax.enterprise + cdi-api + 1.2 + provided + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + runtime + + + org.n52.arctic-sea + janmayen + + + org.springframework + spring-webmvc + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + src/main/resources + + **/*.xml + + + + + + diff --git a/faroe/rest/src/main/java/org/n52/faroeREST/springrest/SpringrestApplication.java b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/SpringrestApplication.java new file mode 100644 index 000000000..dcfe5e83a --- /dev/null +++ b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/SpringrestApplication.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015-2022 52°North Spatial Information Research GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.n52.faroeREST.springrest; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@ImportResource({"classpath:/faroe.xml", + "classpath:/settings-service.xml", + "classpath:/settings-service-identification.xml", + "classpath:/settings-service-provider.xml"}) + +@SpringBootApplication +public class SpringrestApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringrestApplication.class, args); + } + + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurer() { + + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("http://localhost:3000") + .allowedMethods("GET","PUT", "POST", "DELETE"); + } + }; + } + +} diff --git a/faroe/rest/src/main/java/org/n52/faroeREST/springrest/controller/APIController.java b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/controller/APIController.java new file mode 100644 index 000000000..b32611725 --- /dev/null +++ b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/controller/APIController.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2015-2022 52°North Spatial Information Research GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.n52.faroeREST.springrest.controller; + +import java.util.Collection; +import java.util.Set; + +import org.n52.faroe.SettingDefinition; +import org.n52.faroe.SettingValue; +import org.n52.faroe.json.JsonSettingValue; +import org.n52.faroeREST.springrest.settings.SettingsAPI; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class APIController { + + @Autowired + private SettingsAPI api; + + @GetMapping(path = "/definitions") + public Collection> getSettingDefinitions() { + return this.api.getSettingDefinitions(); + + } + + @PostMapping(path = "/definitions", consumes = "application/json") + public void addSettingDefinitions(@RequestBody Collection> value) { + this.api.addSettingDefinitions(value); + } + + @GetMapping(path = "/definitions/groups") + public Set getGroups() { + return this.api.getGroups(); + } + + @GetMapping(path = "/definitions/groups/{groupTitle}") + public Collection> getSettingDefinitionByTitle(@PathVariable String groupTitle) { + return this.api.getSettingsByTitle(groupTitle); + } + + @PutMapping(path = "/settings", consumes = "application/json") + public void updateSettingValue(@RequestBody JsonSettingValue value) { + this.api.updateSettingValue(value); + } + + @GetMapping("/settings") + public Collection> getSettingValues() { + return this.api.getSettingValues(); + } + + @GetMapping("/settings/{groupTitle}") + public Collection> getSettingValuesByGroup(String groupTitle) { + return this.api.getSettingValuesByGroup(groupTitle); + } + + @DeleteMapping("/settings/{setting}") + public void deleteSettingValue(@PathVariable String setting) { + this.api.deleteSettingValue(setting); + } +} diff --git a/faroe/rest/src/main/java/org/n52/faroeREST/springrest/entities/Groups.java b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/entities/Groups.java new file mode 100644 index 000000000..ee87cbf11 --- /dev/null +++ b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/entities/Groups.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015-2022 52°North Spatial Information Research GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.n52.faroeREST.springrest.entities; + +public class Groups { + + private String title; + private String description; + + public Groups(String title, String description) { + super(); + this.title = title; + this.description = description; + } + + public Groups() { + super(); + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String toString() { + return "Groups [title=" + title + ", description=" + description + "]"; + } + +} diff --git a/faroe/rest/src/main/java/org/n52/faroeREST/springrest/settings/LocalConfigLocation.java b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/settings/LocalConfigLocation.java new file mode 100644 index 000000000..47349b6e3 --- /dev/null +++ b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/settings/LocalConfigLocation.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015-2022 52°North Spatial Information Research GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.n52.faroeREST.springrest.settings; + +import org.n52.janmayen.ConfigLocationProvider; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class LocalConfigLocation implements ConfigLocationProvider { + + @Override + public String get() { + return Paths.get(".").toAbsolutePath().toString(); + } + +} diff --git a/faroe/rest/src/main/java/org/n52/faroeREST/springrest/settings/SettingsAPI.java b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/settings/SettingsAPI.java new file mode 100644 index 000000000..f2871de4b --- /dev/null +++ b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/settings/SettingsAPI.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2015-2022 52°North Spatial Information Research GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.n52.faroeREST.springrest.settings; + +import java.util.*; + +import org.n52.faroe.SettingDefinition; +import org.n52.faroe.SettingValue; + +public interface SettingsAPI { + + public Collection> getSettingValues(); + + public Collection> getSettingDefinitions(); + + public Set getGroups(); + + public Collection> getSettingsByTitle(String groupTitle); + + public void addSettingDefinitions(Collection> group); + + public void updateSettingValue(SettingValue group); + + public void deleteSettingValue(String setting); + + Collection> getSettingValuesByGroup(String title); +} diff --git a/faroe/rest/src/main/java/org/n52/faroeREST/springrest/settings/SettingsAPIImpl.java b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/settings/SettingsAPIImpl.java new file mode 100644 index 000000000..80c538d80 --- /dev/null +++ b/faroe/rest/src/main/java/org/n52/faroeREST/springrest/settings/SettingsAPIImpl.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2015-2022 52°North Spatial Information Research GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.n52.faroeREST.springrest.settings; + +import org.joda.time.DateTime; +import org.n52.faroe.SettingDefinition; +import org.n52.faroe.SettingDefinitionGroup; +import org.n52.faroe.SettingType; +import org.n52.faroe.SettingValue; +import org.n52.faroe.SettingsDefinitionDao; +import org.n52.faroe.SettingsService; +import org.n52.faroe.settings.ChoiceSettingDefinition; +import org.n52.janmayen.i18n.MultilingualString; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import java.io.File; +import java.io.Serializable; +import java.net.URI; +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +@Service +public class SettingsAPIImpl implements InitializingBean, SettingsAPI { + + @Inject + private SettingsService service; + + @Inject + private SettingsDefinitionDao dao; + + public void afterPropertiesSet() { + service.addSettings(dao.getAllSettings()); + } + + @Override + public Collection> getSettingDefinitions() { + return service.getSettingDefinitions(); + + } + + @Override + public Collection> getSettingValues() { + return service.getSettingDefinitions().stream().map(definition -> { + SettingValue setting = service.getSetting(definition.getKey()); + if (setting == null) { + if (definition.hasDefaultValue()) { + return createDefaultSettingValue(definition); + } else { + return new NullSetting(definition); + } + } + return setting; + }).collect(Collectors.toList()); + } + + private SettingValue createDefaultSettingValue(SettingDefinition definition) { + switch (definition.getType()) { + case BOOLEAN: + return service.getSettingFactory() + .newBooleanSettingValue(definition.getKey(), (Boolean) definition.getDefaultValue()); + case FILE: + return service.getSettingFactory() + .newFileSettingValue(definition.getKey(), (File) definition.getDefaultValue()); + case INTEGER: + return service.getSettingFactory() + .newIntegerSettingValue(definition.getKey(), (Integer) definition.getDefaultValue()); + case NUMERIC: + return service.getSettingFactory() + .newNumericSettingValue(definition.getKey(), (Double) definition.getDefaultValue()); + case STRING: + return service.getSettingFactory() + .newStringSettingValue(definition.getKey(), (String) definition.getDefaultValue()); + case URI: + return service.getSettingFactory() + .newUriSettingValue(definition.getKey(), (URI) definition.getDefaultValue()); + case TIMEINSTANT: + return service.getSettingFactory() + .newDateTimeSettingValue(definition.getKey(), (DateTime) definition.getDefaultValue()); + case MULTILINGUAL_STRING: + return service.getSettingFactory() + .newMultiLingualStringSettingValue(definition.getKey(), (MultilingualString) definition.getDefaultValue()); + case CHOICE: + return service.getSettingFactory() + .newChoiceSettingValue(definition.getKey(), (String) definition.getDefaultValue()); + default: + throw new IllegalArgumentException(String.format("Type %s not supported", definition.getType())); + } + } + + @Override + public Collection> getSettingsByTitle(String groupTitle) { + return service.getSettingDefinitions().stream() + .filter(definition -> definition.getGroup().getTitle().equalsIgnoreCase(groupTitle)) + .collect(Collectors.toList()); + } + + @Override + public Set getGroups() { + return service.getSettingDefinitions().stream().map(SettingDefinition::getGroup) + .map(SettingDefinitionGroup::getTitle).collect(Collectors.toSet()); + } + + @SuppressWarnings("unchecked") + @Override + public void addSettingDefinitions(Collection> group) { + if (group.stream().anyMatch(settingDefinition -> service.getKeys().contains(settingDefinition.getKey()))) { + throw new IllegalArgumentException("definition already exists"); + } + + dao.saveSettings(group); + service.addSettings(group); + } + + @Override + public void updateSettingValue(SettingValue group) { + service.changeSetting(group); + } + + @Override + public void deleteSettingValue(String setting) { + service.deleteSetting(setting); + } + + @Override + public Collection> getSettingValuesByGroup(String title) { + return service.getSettingDefinitions().stream() + .filter(definition -> definition.getGroup().getTitle().equalsIgnoreCase(title)) + .map(definition -> service.getSetting(definition)) + .collect(Collectors.toList()); + } + + private static class NullSetting implements SettingValue { + private final SettingDefinition definition; + + public NullSetting(SettingDefinition definition) {this.definition = definition;} + + @Override + public String getKey() { + return definition.getKey(); + } + + @Override + public Object getValue() { + return null; + } + + @Override + public void setKey(String key) { + throw new UnsupportedOperationException(); + } + + @Override + public void setValue(Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public SettingType getType() { + return definition.getType(); + } + + } +} diff --git a/faroe/rest/src/main/resources/application.properties b/faroe/rest/src/main/resources/application.properties new file mode 100644 index 000000000..bf323d887 --- /dev/null +++ b/faroe/rest/src/main/resources/application.properties @@ -0,0 +1,2 @@ +server.port=8090 +spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/faroe/rest/src/main/resources/faroe.xml b/faroe/rest/src/main/resources/faroe.xml new file mode 100644 index 000000000..83d57df06 --- /dev/null +++ b/faroe/rest/src/main/resources/faroe.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/faroe/rest/src/main/resources/settings-service-identification.xml b/faroe/rest/src/main/resources/settings-service-identification.xml new file mode 100644 index 000000000..6f8f274cb --- /dev/null +++ b/faroe/rest/src/main/resources/settings-service-identification.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/faroe/rest/src/main/resources/settings-service-provider.xml b/faroe/rest/src/main/resources/settings-service-provider.xml new file mode 100644 index 000000000..93c3ffa9d --- /dev/null +++ b/faroe/rest/src/main/resources/settings-service-provider.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/faroe/rest/src/main/resources/settings-service.xml b/faroe/rest/src/main/resources/settings-service.xml new file mode 100644 index 000000000..5ae537ea8 --- /dev/null +++ b/faroe/rest/src/main/resources/settings-service.xml @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/faroe/rest/src/test/java/org/n52/faroeREST/springrest/SpringrestApplicationTests.java b/faroe/rest/src/test/java/org/n52/faroeREST/springrest/SpringrestApplicationTests.java new file mode 100644 index 000000000..7e3719f09 --- /dev/null +++ b/faroe/rest/src/test/java/org/n52/faroeREST/springrest/SpringrestApplicationTests.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2015-2022 52°North Spatial Information Research GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.n52.faroeREST.springrest; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SpringrestApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/iceland/statistics/core/src/test/java/org/n52/iceland/statistics/mock/MockSettingsService.java b/iceland/statistics/core/src/test/java/org/n52/iceland/statistics/mock/MockSettingsService.java index cf19b57df..a2d253d80 100644 --- a/iceland/statistics/core/src/test/java/org/n52/iceland/statistics/mock/MockSettingsService.java +++ b/iceland/statistics/core/src/test/java/org/n52/iceland/statistics/mock/MockSettingsService.java @@ -43,6 +43,11 @@ public void deleteAll() { public void deleteSetting(SettingDefinition setting) throws ConfigurationError { } + @Override + public void deleteSetting(String setting) throws ConfigurationError { + + } + @Override public SettingDefinition getDefinitionByKey(String key) { throw new UnsupportedOperationException(); diff --git a/janmayen/src/main/java/org/n52/janmayen/i18n/LocalizedString.java b/janmayen/src/main/java/org/n52/janmayen/i18n/LocalizedString.java index 93dcbf7bb..f0f0f5019 100644 --- a/janmayen/src/main/java/org/n52/janmayen/i18n/LocalizedString.java +++ b/janmayen/src/main/java/org/n52/janmayen/i18n/LocalizedString.java @@ -19,6 +19,9 @@ import java.util.Locale; import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import com.google.common.base.Strings; @@ -40,7 +43,8 @@ public LocalizedString(String value) { this(null, value); } - public LocalizedString(Locale lang, String value) { + @JsonCreator + public LocalizedString(@JsonProperty("lang") Locale lang, @JsonProperty("lang") String value) { Preconditions.checkArgument(!Strings.isNullOrEmpty(value)); this.text = value; this.lang = lang == null ? NULL_LOCALE : lang; @@ -61,6 +65,7 @@ public Locale getLang() { return this.lang; } + @JsonIgnore public String getLangString() { String country = this.lang.getISO3Country(); String language = this.lang.getISO3Language(); @@ -74,9 +79,9 @@ public String getLangString() { @Override public String toString() { return MoreObjects.toStringHelper(this) - .add("lang", getLang()) - .add("text", getText()) - .toString(); + .add("lang", getLang()) + .add("text", getText()) + .toString(); } @Override diff --git a/janmayen/src/main/java/org/n52/janmayen/i18n/MultilingualString.java b/janmayen/src/main/java/org/n52/janmayen/i18n/MultilingualString.java index 0a5561592..cd4699381 100644 --- a/janmayen/src/main/java/org/n52/janmayen/i18n/MultilingualString.java +++ b/janmayen/src/main/java/org/n52/janmayen/i18n/MultilingualString.java @@ -25,7 +25,13 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.JsonValue; import org.n52.janmayen.Optionals; import org.n52.janmayen.stream.StreamingIterable; @@ -118,19 +124,27 @@ public MultilingualString setLocalizations(Map localizations) { return this; } + @JsonValue + private Map getLocalizationsJSON() { + return this.localizations.values().stream() + .collect(Collectors.toMap(e -> LocaleHelper.encode(e.getLang()), LocalizedString::getText)); + } + public MultilingualString only(Locale... locale) { return only(Arrays.asList(locale)); } public MultilingualString only(Iterable locales) { MultilingualString mls = new MultilingualString(); - for (Locale locale : locales) { - Optional localization = getLocalization(locale); - if (localization.isPresent()) { - mls.addLocalization(localization.get()); - } - } + locales.forEach(locale -> getLocalization(locale).ifPresent(mls::addLocalization)); return mls; } + @JsonCreator + private static MultilingualString fromStringMap(Map localizations) { + MultilingualString ms = new MultilingualString(); + ms.setLocalizations(localizations); + return ms; + } + } diff --git a/pom.xml b/pom.xml index 07c7ef7b4..aeb34e6f1 100644 --- a/pom.xml +++ b/pom.xml @@ -152,6 +152,7 @@ 3.17.0 2.13.3 5.8.2 + 2.7.1 4.6.1 2.2 4.4.15 @@ -162,7 +163,6 @@ - ${project.groupId} @@ -487,6 +487,14 @@ spring-beans ${version.spring} + + + org.springframework.boot + spring-boot-dependencies + ${version.spring-boot} + pom + import + org.springframework spring-core @@ -1192,6 +1200,11 @@ + + org.springframework.boot + spring-boot-maven-plugin + ${version.spring-boot} + org.apache.maven.plugins maven-javadoc-plugin