diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..ce44319
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,6 @@
+This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+# Changelog for org.gcube.spatial.data.gcube-sdi-suite
+
+## [v1.0.0-SNAPSHOT] - 2021-2-11
+First release
diff --git a/FUNDING.md b/FUNDING.md
new file mode 100644
index 0000000..9e48b94
--- /dev/null
+++ b/FUNDING.md
@@ -0,0 +1,26 @@
+# Acknowledgments
+
+The projects leading to this software have received funding from a series of European Union programmes including:
+
+- the Sixth Framework Programme for Research and Technological Development
+ - [DILIGENT](https://cordis.europa.eu/project/id/004260) (grant no. 004260).
+- the Seventh Framework Programme for research, technological development and demonstration
+ - [D4Science](https://cordis.europa.eu/project/id/212488) (grant no. 212488);
+ - [D4Science-II](https://cordis.europa.eu/project/id/239019) (grant no.239019);
+ - [ENVRI](https://cordis.europa.eu/project/id/283465) (grant no. 283465);
+ - [iMarine](https://cordis.europa.eu/project/id/283644) (grant no. 283644);
+ - [EUBrazilOpenBio](https://cordis.europa.eu/project/id/288754) (grant no. 288754).
+- the H2020 research and innovation programme
+ - [SoBigData](https://cordis.europa.eu/project/id/654024) (grant no. 654024);
+ - [PARTHENOS](https://cordis.europa.eu/project/id/654119) (grant no. 654119);
+ - [EGI-Engage](https://cordis.europa.eu/project/id/654142) (grant no. 654142);
+ - [ENVRI PLUS](https://cordis.europa.eu/project/id/654182) (grant no. 654182);
+ - [BlueBRIDGE](https://cordis.europa.eu/project/id/675680) (grant no. 675680);
+ - [PerformFISH](https://cordis.europa.eu/project/id/727610) (grant no. 727610);
+ - [AGINFRA PLUS](https://cordis.europa.eu/project/id/731001) (grant no. 731001);
+ - [DESIRA](https://cordis.europa.eu/project/id/818194) (grant no. 818194);
+ - [ARIADNEplus](https://cordis.europa.eu/project/id/823914) (grant no. 823914);
+ - [RISIS 2](https://cordis.europa.eu/project/id/824091) (grant no. 824091);
+ - [EOSC-Pillar](https://cordis.europa.eu/project/id/857650) (grant no. 857650);
+ - [Blue Cloud](https://cordis.europa.eu/project/id/862409) (grant no. 862409);
+ - [SoBigData-PlusPlus](https://cordis.europa.eu/project/id/871042) (grant no. 871042);
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..3af0507
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,312 @@
+# European Union Public Licence V. 1.1
+
+
+EUPL © the European Community 2007
+
+
+This European Union Public Licence (the “EUPL”) applies to the Work or Software
+(as defined below) which is provided under the terms of this Licence. Any use of
+the Work, other than as authorised under this Licence is prohibited (to the
+extent such use is covered by a right of the copyright holder of the Work).
+
+The Original Work is provided under the terms of this Licence when the Licensor
+(as defined below) has placed the following notice immediately following the
+copyright notice for the Original Work:
+
+Licensed under the EUPL V.1.1
+
+or has expressed by any other mean his willingness to license under the EUPL.
+
+
+
+## 1. Definitions
+
+In this Licence, the following terms have the following meaning:
+
+- The Licence: this Licence.
+
+- The Original Work or the Software: the software distributed and/or
+ communicated by the Licensor under this Licence, available as Source Code and
+ also as Executable Code as the case may be.
+
+- Derivative Works: the works or software that could be created by the Licensee,
+ based upon the Original Work or modifications thereof. This Licence does not
+ define the extent of modification or dependence on the Original Work required
+ in order to classify a work as a Derivative Work; this extent is determined by
+ copyright law applicable in the country mentioned in Article 15.
+
+- The Work: the Original Work and/or its Derivative Works.
+
+- The Source Code: the human-readable form of the Work which is the most
+ convenient for people to study and modify.
+
+- The Executable Code: any code which has generally been compiled and which is
+ meant to be interpreted by a computer as a program.
+
+- The Licensor: the natural or legal person that distributes and/or communicates
+ the Work under the Licence.
+
+- Contributor(s): any natural or legal person who modifies the Work under the
+ Licence, or otherwise contributes to the creation of a Derivative Work.
+
+- The Licensee or “You”: any natural or legal person who makes any usage of the
+ Software under the terms of the Licence.
+
+- Distribution and/or Communication: any act of selling, giving, lending,
+ renting, distributing, communicating, transmitting, or otherwise making
+ available, on-line or off-line, copies of the Work or providing access to its
+ essential functionalities at the disposal of any other natural or legal
+ person.
+
+
+
+## 2. Scope of the rights granted by the Licence
+
+The Licensor hereby grants You a world-wide, royalty-free, non-exclusive,
+sub-licensable licence to do the following, for the duration of copyright vested
+in the Original Work:
+
+- use the Work in any circumstance and for all usage, reproduce the Work, modify
+- the Original Work, and make Derivative Works based upon the Work, communicate
+- to the public, including the right to make available or display the Work or
+- copies thereof to the public and perform publicly, as the case may be, the
+- Work, distribute the Work or copies thereof, lend and rent the Work or copies
+- thereof, sub-license rights in the Work or copies thereof.
+
+Those rights can be exercised on any media, supports and formats, whether now
+known or later invented, as far as the applicable law permits so.
+
+In the countries where moral rights apply, the Licensor waives his right to
+exercise his moral right to the extent allowed by law in order to make effective
+the licence of the economic rights here above listed.
+
+The Licensor grants to the Licensee royalty-free, non exclusive usage rights to
+any patents held by the Licensor, to the extent necessary to make use of the
+rights granted on the Work under this Licence.
+
+
+
+## 3. Communication of the Source Code
+
+The Licensor may provide the Work either in its Source Code form, or as
+Executable Code. If the Work is provided as Executable Code, the Licensor
+provides in addition a machine-readable copy of the Source Code of the Work
+along with each copy of the Work that the Licensor distributes or indicates, in
+a notice following the copyright notice attached to the Work, a repository where
+the Source Code is easily and freely accessible for as long as the Licensor
+continues to distribute and/or communicate the Work.
+
+
+
+## 4. Limitations on copyright
+
+Nothing in this Licence is intended to deprive the Licensee of the benefits from
+any exception or limitation to the exclusive rights of the rights owners in the
+Original Work or Software, of the exhaustion of those rights or of other
+applicable limitations thereto.
+
+
+
+## 5. Obligations of the Licensee
+
+The grant of the rights mentioned above is subject to some restrictions and
+obligations imposed on the Licensee. Those obligations are the following:
+
+Attribution right: the Licensee shall keep intact all copyright, patent or
+trademarks notices and all notices that refer to the Licence and to the
+disclaimer of warranties. The Licensee must include a copy of such notices and a
+copy of the Licence with every copy of the Work he/she distributes and/or
+communicates. The Licensee must cause any Derivative Work to carry prominent
+notices stating that the Work has been modified and the date of modification.
+
+Copyleft clause: If the Licensee distributes and/or communicates copies of the
+Original Works or Derivative Works based upon the Original Work, this
+Distribution and/or Communication will be done under the terms of this Licence
+or of a later version of this Licence unless the Original Work is expressly
+distributed only under this version of the Licence. The Licensee (becoming
+Licensor) cannot offer or impose any additional terms or conditions on the Work
+or Derivative Work that alter or restrict the terms of the Licence.
+
+Compatibility clause: If the Licensee Distributes and/or Communicates Derivative
+Works or copies thereof based upon both the Original Work and another work
+licensed under a Compatible Licence, this Distribution and/or Communication can
+be done under the terms of this Compatible Licence. For the sake of this clause,
+“Compatible Licence” refers to the licences listed in the appendix attached to
+this Licence. Should the Licensee’s obligations under the Compatible Licence
+conflict with his/her obligations under this Licence, the obligations of the
+Compatible Licence shall prevail.
+
+Provision of Source Code: When distributing and/or communicating copies of the
+Work, the Licensee will provide a machine-readable copy of the Source Code or
+indicate a repository where this Source will be easily and freely available for
+as long as the Licensee continues to distribute and/or communicate the Work.
+
+Legal Protection: This Licence does not grant permission to use the trade names,
+trademarks, service marks, or names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the copyright notice.
+
+
+
+## 6. Chain of Authorship
+
+The original Licensor warrants that the copyright in the Original Work granted
+hereunder is owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each Contributor warrants that the copyright in the modifications he/she brings
+to the Work are owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each time You accept the Licence, the original Licensor and subsequent
+Contributors grant You a licence to their contributions to the Work, under the
+terms of this Licence.
+
+
+
+## 7. Disclaimer of Warranty
+
+The Work is a work in progress, which is continuously improved by numerous
+contributors. It is not a finished work and may therefore contain defects or
+“bugs” inherent to this type of software development.
+
+For the above reason, the Work is provided under the Licence on an “as is” basis
+and without warranties of any kind concerning the Work, including without
+limitation merchantability, fitness for a particular purpose, absence of defects
+or errors, accuracy, non-infringement of intellectual property rights other than
+copyright as stated in Article 6 of this Licence.
+
+This disclaimer of warranty is an essential part of the Licence and a condition
+for the grant of any rights to the Work.
+
+
+
+## 8. Disclaimer of Liability
+
+Except in the cases of wilful misconduct or damages directly caused to natural
+persons, the Licensor will in no event be liable for any direct or indirect,
+material or moral, damages of any kind, arising out of the Licence or of the use
+of the Work, including without limitation, damages for loss of goodwill, work
+stoppage, computer failure or malfunction, loss of data or any commercial
+damage, even if the Licensor has been advised of the possibility of such
+damage. However, the Licensor will be liable under statutory product liability
+laws as far such laws apply to the Work.
+
+
+
+## 9. Additional agreements
+
+While distributing the Original Work or Derivative Works, You may choose to
+conclude an additional agreement to offer, and charge a fee for, acceptance of
+support, warranty, indemnity, or other liability obligations and/or services
+consistent with this Licence. However, in accepting such obligations, You may
+act only on your own behalf and on your sole responsibility, not on behalf of
+the original Licensor or any other Contributor, and only if You agree to
+indemnify, defend, and hold each Contributor harmless for any liability incurred
+by, or claims asserted against such Contributor by the fact You have accepted
+any such warranty or additional liability.
+
+
+
+## 10. Acceptance of the Licence
+
+The provisions of this Licence can be accepted by clicking on an icon “I agree”
+placed under the bottom of a window displaying the text of this Licence or by
+affirming consent in any other similar way, in accordance with the rules of
+applicable law. Clicking on that icon indicates your clear and irrevocable
+acceptance of this Licence and all of its terms and conditions.
+
+Similarly, you irrevocably accept this Licence and all of its terms and
+conditions by exercising any rights granted to You by Article 2 of this Licence,
+such as the use of the Work, the creation by You of a Derivative Work or the
+Distribution and/or Communication by You of the Work or copies thereof.
+
+
+
+## 11. Information to the public
+
+In case of any Distribution and/or Communication of the Work by means of
+electronic communication by You (for example, by offering to download the Work
+from a remote location) the distribution channel or media (for example, a
+website) must at least provide to the public the information requested by the
+applicable law regarding the Licensor, the Licence and the way it may be
+accessible, concluded, stored and reproduced by the Licensee.
+
+
+
+## 12. Termination of the Licence
+
+The Licence and the rights granted hereunder will terminate automatically upon
+any breach by the Licensee of the terms of the Licence.
+
+Such a termination will not terminate the licences of any person who has
+received the Work from the Licensee under the Licence, provided such persons
+remain in full compliance with the Licence.
+
+
+
+## 13. Miscellaneous
+
+Without prejudice of Article 9 above, the Licence represents the complete
+agreement between the Parties as to the Work licensed hereunder.
+
+If any provision of the Licence is invalid or unenforceable under applicable
+law, this will not affect the validity or enforceability of the Licence as a
+whole. Such provision will be construed and/or reformed so as necessary to make
+it valid and enforceable.
+
+The European Commission may publish other linguistic versions and/or new
+versions of this Licence, so far this is required and reasonable, without
+reducing the scope of the rights granted by the Licence. New versions of the
+Licence will be published with a unique version number.
+
+All linguistic versions of this Licence, approved by the European Commission,
+have identical value. Parties can take advantage of the linguistic version of
+their choice.
+
+
+
+## 14. Jurisdiction
+
+Any litigation resulting from the interpretation of this License, arising
+between the European Commission, as a Licensor, and any Licensee, will be
+subject to the jurisdiction of the Court of Justice of the European Communities,
+as laid down in article 238 of the Treaty establishing the European Community.
+
+Any litigation arising between Parties, other than the European Commission, and
+resulting from the interpretation of this License, will be subject to the
+exclusive jurisdiction of the competent court where the Licensor resides or
+conducts its primary business.
+
+
+
+## 15. Applicable Law
+
+This Licence shall be governed by the law of the European Union country where
+the Licensor resides or has his registered office.
+
+This licence shall be governed by the Belgian law if:
+
+- a litigation arises between the European Commission, as a Licensor, and any
+- Licensee; the Licensor, other than the European Commission, has no residence
+- or registered office inside a European Union country.
+
+
+
+## Appendix
+
+
+
+“Compatible Licences” according to article 5 EUPL are:
+
+
+- GNU General Public License (GNU GPL) v. 2
+
+- Open Software License (OSL) v. 2.1, v. 3.0
+
+- Common Public License v. 1.0
+
+- Eclipse Public License v. 1.0
+
+- Cecill v. 2.0
+
diff --git a/README.md b/README.md
index 7b74897..85dd719 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,52 @@
-# gcube-cms-suite
+gCube CMS Suite
+--------------------------------------------------
+
+gCube CMS Suite is a set of components designed to manage complex space-temporal Documents defined by metadata Profiles.
+
+## Built with
+* [gCube SmartGears] (https://gcube.wiki.gcube-system.org/gcube/SmartGears) - The gCube SmartGears framework
+* [OpenJDK](https://openjdk.java.net/) - The JDK used
+* [JAX-RS](https://github.com/eclipse-ee4j/jaxrs-api) - Java™ API for RESTful Web Services
+* [Jersey](https://jersey.github.io/) - JAX-RS runtime
+* [Maven](https://maven.apache.org/) - Dependency Management
+
+## Documentation
+
+Documentation can be found [here](https://gcube.wiki.gcube-system.org/gcube/GeoPortal_Service).
+
+## Change log
+
+See [CHANGELOG.md](CHANGELOG.md).
+
+## License
+
+This project is licensed under the EUPL V.1.1 License - see the [LICENSE.md](LICENSE.md) file for details.
+
+## About the gCube Framework
+This software is part of the [gCubeFramework](https://www.gcube-system.org/ "gCubeFramework"): an
+open-source software toolkit used for building and operating Hybrid Data
+Infrastructures enabling the dynamic deployment of Virtual Research Environments
+by favouring the realisation of reuse oriented policies.
+
+The projects leading to this software have received funding from a series of European Union programmes including:
+
+- the Sixth Framework Programme for Research and Technological Development
+ - DILIGENT (grant no. 004260).
+- the Seventh Framework Programme for research, technological development and demonstration
+ - D4Science (grant no. 212488);
+ - D4Science-II (grant no.239019);
+ - ENVRI (grant no. 283465);
+ - iMarine(grant no. 283644);
+ - EUBrazilOpenBio (grant no. 288754).
+- the H2020 research and innovation programme
+ - SoBigData (grant no. 654024);
+ - PARTHENOS (grant no. 654119);
+ - EGIEngage (grant no. 654142);
+ - ENVRIplus (grant no. 654182);
+ - BlueBRIDGE (grant no. 675680);
+ - PerformFish (grant no. 727610);
+ - AGINFRAplus (grant no. 731001);
+ - DESIRA (grant no. 818194);
+ - ARIADNEplus (grant no. 823914);
+ - RISIS2 (grant no. 824091);
diff --git a/geoportal-client/CHANGELOG.md b/geoportal-client/CHANGELOG.md
new file mode 100644
index 0000000..edc4e93
--- /dev/null
+++ b/geoportal-client/CHANGELOG.md
@@ -0,0 +1,27 @@
+This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+# Changelog for org.gcube.application.geoportal-client
+
+## [v1.0.5-SNAPSHOT] - 2021-09-20
+Refactored repositories
+
+## [v1.0.4-SNAPSHOT] - 2020-11-11
+Serialization utils
+Queries & Filters support
+Test Reports
+UseCases
+Fixes #21897
+
+## [v1.0.3] - 2020-11-11
+Stateful Concessioni Manager client over mongo
+
+## [v1.0.2] - 2020-11-11
+Fixed dulicate dependency declaration
+
+## [v1.0.1] - 2020-11-11
+Excluded common-calls 1.2.0
+
+
+## [v1.0.0] - 2020-11-11
+
+First release
\ No newline at end of file
diff --git a/geoportal-client/FUNDING.md b/geoportal-client/FUNDING.md
new file mode 100644
index 0000000..9e48b94
--- /dev/null
+++ b/geoportal-client/FUNDING.md
@@ -0,0 +1,26 @@
+# Acknowledgments
+
+The projects leading to this software have received funding from a series of European Union programmes including:
+
+- the Sixth Framework Programme for Research and Technological Development
+ - [DILIGENT](https://cordis.europa.eu/project/id/004260) (grant no. 004260).
+- the Seventh Framework Programme for research, technological development and demonstration
+ - [D4Science](https://cordis.europa.eu/project/id/212488) (grant no. 212488);
+ - [D4Science-II](https://cordis.europa.eu/project/id/239019) (grant no.239019);
+ - [ENVRI](https://cordis.europa.eu/project/id/283465) (grant no. 283465);
+ - [iMarine](https://cordis.europa.eu/project/id/283644) (grant no. 283644);
+ - [EUBrazilOpenBio](https://cordis.europa.eu/project/id/288754) (grant no. 288754).
+- the H2020 research and innovation programme
+ - [SoBigData](https://cordis.europa.eu/project/id/654024) (grant no. 654024);
+ - [PARTHENOS](https://cordis.europa.eu/project/id/654119) (grant no. 654119);
+ - [EGI-Engage](https://cordis.europa.eu/project/id/654142) (grant no. 654142);
+ - [ENVRI PLUS](https://cordis.europa.eu/project/id/654182) (grant no. 654182);
+ - [BlueBRIDGE](https://cordis.europa.eu/project/id/675680) (grant no. 675680);
+ - [PerformFISH](https://cordis.europa.eu/project/id/727610) (grant no. 727610);
+ - [AGINFRA PLUS](https://cordis.europa.eu/project/id/731001) (grant no. 731001);
+ - [DESIRA](https://cordis.europa.eu/project/id/818194) (grant no. 818194);
+ - [ARIADNEplus](https://cordis.europa.eu/project/id/823914) (grant no. 823914);
+ - [RISIS 2](https://cordis.europa.eu/project/id/824091) (grant no. 824091);
+ - [EOSC-Pillar](https://cordis.europa.eu/project/id/857650) (grant no. 857650);
+ - [Blue Cloud](https://cordis.europa.eu/project/id/862409) (grant no. 862409);
+ - [SoBigData-PlusPlus](https://cordis.europa.eu/project/id/871042) (grant no. 871042);
diff --git a/geoportal-client/LICENSE.md b/geoportal-client/LICENSE.md
new file mode 100644
index 0000000..3af0507
--- /dev/null
+++ b/geoportal-client/LICENSE.md
@@ -0,0 +1,312 @@
+# European Union Public Licence V. 1.1
+
+
+EUPL © the European Community 2007
+
+
+This European Union Public Licence (the “EUPL”) applies to the Work or Software
+(as defined below) which is provided under the terms of this Licence. Any use of
+the Work, other than as authorised under this Licence is prohibited (to the
+extent such use is covered by a right of the copyright holder of the Work).
+
+The Original Work is provided under the terms of this Licence when the Licensor
+(as defined below) has placed the following notice immediately following the
+copyright notice for the Original Work:
+
+Licensed under the EUPL V.1.1
+
+or has expressed by any other mean his willingness to license under the EUPL.
+
+
+
+## 1. Definitions
+
+In this Licence, the following terms have the following meaning:
+
+- The Licence: this Licence.
+
+- The Original Work or the Software: the software distributed and/or
+ communicated by the Licensor under this Licence, available as Source Code and
+ also as Executable Code as the case may be.
+
+- Derivative Works: the works or software that could be created by the Licensee,
+ based upon the Original Work or modifications thereof. This Licence does not
+ define the extent of modification or dependence on the Original Work required
+ in order to classify a work as a Derivative Work; this extent is determined by
+ copyright law applicable in the country mentioned in Article 15.
+
+- The Work: the Original Work and/or its Derivative Works.
+
+- The Source Code: the human-readable form of the Work which is the most
+ convenient for people to study and modify.
+
+- The Executable Code: any code which has generally been compiled and which is
+ meant to be interpreted by a computer as a program.
+
+- The Licensor: the natural or legal person that distributes and/or communicates
+ the Work under the Licence.
+
+- Contributor(s): any natural or legal person who modifies the Work under the
+ Licence, or otherwise contributes to the creation of a Derivative Work.
+
+- The Licensee or “You”: any natural or legal person who makes any usage of the
+ Software under the terms of the Licence.
+
+- Distribution and/or Communication: any act of selling, giving, lending,
+ renting, distributing, communicating, transmitting, or otherwise making
+ available, on-line or off-line, copies of the Work or providing access to its
+ essential functionalities at the disposal of any other natural or legal
+ person.
+
+
+
+## 2. Scope of the rights granted by the Licence
+
+The Licensor hereby grants You a world-wide, royalty-free, non-exclusive,
+sub-licensable licence to do the following, for the duration of copyright vested
+in the Original Work:
+
+- use the Work in any circumstance and for all usage, reproduce the Work, modify
+- the Original Work, and make Derivative Works based upon the Work, communicate
+- to the public, including the right to make available or display the Work or
+- copies thereof to the public and perform publicly, as the case may be, the
+- Work, distribute the Work or copies thereof, lend and rent the Work or copies
+- thereof, sub-license rights in the Work or copies thereof.
+
+Those rights can be exercised on any media, supports and formats, whether now
+known or later invented, as far as the applicable law permits so.
+
+In the countries where moral rights apply, the Licensor waives his right to
+exercise his moral right to the extent allowed by law in order to make effective
+the licence of the economic rights here above listed.
+
+The Licensor grants to the Licensee royalty-free, non exclusive usage rights to
+any patents held by the Licensor, to the extent necessary to make use of the
+rights granted on the Work under this Licence.
+
+
+
+## 3. Communication of the Source Code
+
+The Licensor may provide the Work either in its Source Code form, or as
+Executable Code. If the Work is provided as Executable Code, the Licensor
+provides in addition a machine-readable copy of the Source Code of the Work
+along with each copy of the Work that the Licensor distributes or indicates, in
+a notice following the copyright notice attached to the Work, a repository where
+the Source Code is easily and freely accessible for as long as the Licensor
+continues to distribute and/or communicate the Work.
+
+
+
+## 4. Limitations on copyright
+
+Nothing in this Licence is intended to deprive the Licensee of the benefits from
+any exception or limitation to the exclusive rights of the rights owners in the
+Original Work or Software, of the exhaustion of those rights or of other
+applicable limitations thereto.
+
+
+
+## 5. Obligations of the Licensee
+
+The grant of the rights mentioned above is subject to some restrictions and
+obligations imposed on the Licensee. Those obligations are the following:
+
+Attribution right: the Licensee shall keep intact all copyright, patent or
+trademarks notices and all notices that refer to the Licence and to the
+disclaimer of warranties. The Licensee must include a copy of such notices and a
+copy of the Licence with every copy of the Work he/she distributes and/or
+communicates. The Licensee must cause any Derivative Work to carry prominent
+notices stating that the Work has been modified and the date of modification.
+
+Copyleft clause: If the Licensee distributes and/or communicates copies of the
+Original Works or Derivative Works based upon the Original Work, this
+Distribution and/or Communication will be done under the terms of this Licence
+or of a later version of this Licence unless the Original Work is expressly
+distributed only under this version of the Licence. The Licensee (becoming
+Licensor) cannot offer or impose any additional terms or conditions on the Work
+or Derivative Work that alter or restrict the terms of the Licence.
+
+Compatibility clause: If the Licensee Distributes and/or Communicates Derivative
+Works or copies thereof based upon both the Original Work and another work
+licensed under a Compatible Licence, this Distribution and/or Communication can
+be done under the terms of this Compatible Licence. For the sake of this clause,
+“Compatible Licence” refers to the licences listed in the appendix attached to
+this Licence. Should the Licensee’s obligations under the Compatible Licence
+conflict with his/her obligations under this Licence, the obligations of the
+Compatible Licence shall prevail.
+
+Provision of Source Code: When distributing and/or communicating copies of the
+Work, the Licensee will provide a machine-readable copy of the Source Code or
+indicate a repository where this Source will be easily and freely available for
+as long as the Licensee continues to distribute and/or communicate the Work.
+
+Legal Protection: This Licence does not grant permission to use the trade names,
+trademarks, service marks, or names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the copyright notice.
+
+
+
+## 6. Chain of Authorship
+
+The original Licensor warrants that the copyright in the Original Work granted
+hereunder is owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each Contributor warrants that the copyright in the modifications he/she brings
+to the Work are owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each time You accept the Licence, the original Licensor and subsequent
+Contributors grant You a licence to their contributions to the Work, under the
+terms of this Licence.
+
+
+
+## 7. Disclaimer of Warranty
+
+The Work is a work in progress, which is continuously improved by numerous
+contributors. It is not a finished work and may therefore contain defects or
+“bugs” inherent to this type of software development.
+
+For the above reason, the Work is provided under the Licence on an “as is” basis
+and without warranties of any kind concerning the Work, including without
+limitation merchantability, fitness for a particular purpose, absence of defects
+or errors, accuracy, non-infringement of intellectual property rights other than
+copyright as stated in Article 6 of this Licence.
+
+This disclaimer of warranty is an essential part of the Licence and a condition
+for the grant of any rights to the Work.
+
+
+
+## 8. Disclaimer of Liability
+
+Except in the cases of wilful misconduct or damages directly caused to natural
+persons, the Licensor will in no event be liable for any direct or indirect,
+material or moral, damages of any kind, arising out of the Licence or of the use
+of the Work, including without limitation, damages for loss of goodwill, work
+stoppage, computer failure or malfunction, loss of data or any commercial
+damage, even if the Licensor has been advised of the possibility of such
+damage. However, the Licensor will be liable under statutory product liability
+laws as far such laws apply to the Work.
+
+
+
+## 9. Additional agreements
+
+While distributing the Original Work or Derivative Works, You may choose to
+conclude an additional agreement to offer, and charge a fee for, acceptance of
+support, warranty, indemnity, or other liability obligations and/or services
+consistent with this Licence. However, in accepting such obligations, You may
+act only on your own behalf and on your sole responsibility, not on behalf of
+the original Licensor or any other Contributor, and only if You agree to
+indemnify, defend, and hold each Contributor harmless for any liability incurred
+by, or claims asserted against such Contributor by the fact You have accepted
+any such warranty or additional liability.
+
+
+
+## 10. Acceptance of the Licence
+
+The provisions of this Licence can be accepted by clicking on an icon “I agree”
+placed under the bottom of a window displaying the text of this Licence or by
+affirming consent in any other similar way, in accordance with the rules of
+applicable law. Clicking on that icon indicates your clear and irrevocable
+acceptance of this Licence and all of its terms and conditions.
+
+Similarly, you irrevocably accept this Licence and all of its terms and
+conditions by exercising any rights granted to You by Article 2 of this Licence,
+such as the use of the Work, the creation by You of a Derivative Work or the
+Distribution and/or Communication by You of the Work or copies thereof.
+
+
+
+## 11. Information to the public
+
+In case of any Distribution and/or Communication of the Work by means of
+electronic communication by You (for example, by offering to download the Work
+from a remote location) the distribution channel or media (for example, a
+website) must at least provide to the public the information requested by the
+applicable law regarding the Licensor, the Licence and the way it may be
+accessible, concluded, stored and reproduced by the Licensee.
+
+
+
+## 12. Termination of the Licence
+
+The Licence and the rights granted hereunder will terminate automatically upon
+any breach by the Licensee of the terms of the Licence.
+
+Such a termination will not terminate the licences of any person who has
+received the Work from the Licensee under the Licence, provided such persons
+remain in full compliance with the Licence.
+
+
+
+## 13. Miscellaneous
+
+Without prejudice of Article 9 above, the Licence represents the complete
+agreement between the Parties as to the Work licensed hereunder.
+
+If any provision of the Licence is invalid or unenforceable under applicable
+law, this will not affect the validity or enforceability of the Licence as a
+whole. Such provision will be construed and/or reformed so as necessary to make
+it valid and enforceable.
+
+The European Commission may publish other linguistic versions and/or new
+versions of this Licence, so far this is required and reasonable, without
+reducing the scope of the rights granted by the Licence. New versions of the
+Licence will be published with a unique version number.
+
+All linguistic versions of this Licence, approved by the European Commission,
+have identical value. Parties can take advantage of the linguistic version of
+their choice.
+
+
+
+## 14. Jurisdiction
+
+Any litigation resulting from the interpretation of this License, arising
+between the European Commission, as a Licensor, and any Licensee, will be
+subject to the jurisdiction of the Court of Justice of the European Communities,
+as laid down in article 238 of the Treaty establishing the European Community.
+
+Any litigation arising between Parties, other than the European Commission, and
+resulting from the interpretation of this License, will be subject to the
+exclusive jurisdiction of the competent court where the Licensor resides or
+conducts its primary business.
+
+
+
+## 15. Applicable Law
+
+This Licence shall be governed by the law of the European Union country where
+the Licensor resides or has his registered office.
+
+This licence shall be governed by the Belgian law if:
+
+- a litigation arises between the European Commission, as a Licensor, and any
+- Licensee; the Licensor, other than the European Commission, has no residence
+- or registered office inside a European Union country.
+
+
+
+## Appendix
+
+
+
+“Compatible Licences” according to article 5 EUPL are:
+
+
+- GNU General Public License (GNU GPL) v. 2
+
+- Open Software License (OSL) v. 2.1, v. 3.0
+
+- Common Public License v. 1.0
+
+- Eclipse Public License v. 1.0
+
+- Cecill v. 2.0
+
diff --git a/geoportal-client/README.md b/geoportal-client/README.md
new file mode 100644
index 0000000..b80f923
--- /dev/null
+++ b/geoportal-client/README.md
@@ -0,0 +1,50 @@
+GeoPortal - Client
+--------------------------------------------------
+
+GeoPortal - Client is the java library wrapping Geoportal REST Service
+
+## Built with
+* [Maven](https://maven.apache.org/) - Dependency Management
+
+## Documentation
+
+Documentation can be found [here](https://gcube.wiki.gcube-system.org/gcube/GeoPortal).
+
+## Change log
+
+See [CHANGELOG.md](CHANGELOG.md).
+
+## License
+
+This project is licensed under the EUPL V.1.1 License - see the [LICENSE.md](LICENSE.md) file for details.
+
+## About the gCube Framework
+This software is part of the [gCubeFramework](https://www.gcube-system.org/ "gCubeFramework"): an
+open-source software toolkit used for building and operating Hybrid Data
+Infrastructures enabling the dynamic deployment of Virtual Research Environments
+by favouring the realisation of reuse oriented policies.
+
+The projects leading to this software have received funding from a series of European Union programmes including:
+
+- the Sixth Framework Programme for Research and Technological Development
+ - DILIGENT (grant no. 004260).
+- the Seventh Framework Programme for research, technological development and demonstration
+ - D4Science (grant no. 212488);
+ - D4Science-II (grant no.239019);
+ - ENVRI (grant no. 283465);
+ - iMarine(grant no. 283644);
+ - EUBrazilOpenBio (grant no. 288754).
+- the H2020 research and innovation programme
+ - SoBigData (grant no. 654024);
+ - PARTHENOS (grant no. 654119);
+ - EGIEngage (grant no. 654142);
+ - ENVRIplus (grant no. 654182);
+ - BlueBRIDGE (grant no. 675680);
+ - PerformFish (grant no. 727610);
+ - AGINFRAplus (grant no. 731001);
+ - DESIRA (grant no. 818194);
+ - ARIADNEplus (grant no. 823914);
+ - RISIS2 (grant no. 824091);
+
+
+
diff --git a/geoportal-client/pom.xml b/geoportal-client/pom.xml
new file mode 100644
index 0000000..bfbc227
--- /dev/null
+++ b/geoportal-client/pom.xml
@@ -0,0 +1,139 @@
+
+ 4.0.0
+ org.gcube.application
+ geoportal-client
+ 1.0.5-SNAPSHOT
+ Geoportal Client
+
+
+
+ org.gcube.application.cms
+ gcube-cms-suite
+ 1.0.0-SNAPSHOT
+
+
+
+
+ https://code-repo.d4science.org/gCubeSystem
+ 1.0
+
+
+
+
+
+
+ scm:git:${gitBaseUrl}/${project.artifactId}.git
+ scm:git:${gitBaseUrl}/${project.artifactId}.git
+ ${gitBaseUrl}/${project.artifactId}.git
+
+
+
+
+
+
+
+ org.gcube.distribution
+ gcube-bom
+ 2.0.1
+ pom
+ import
+
+
+ org.gcube.distribution
+ gcube-smartgears-bom
+ 2.1.0
+ pom
+ test
+
+
+
+
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.14.8
+
+
+
+ org.gcube.application
+ geoportal-common
+ [1.0.0,2.0.0)
+
+
+
+
+ org.gcube.core
+ common-fw-clients
+
+
+
+ org.gcube.core
+ common-generic-clients
+
+
+
+
+
+
+ org.gcube.common
+ common-jaxrs-client
+ [1.0.0,2.0.0)
+
+
+
+
+ junit
+ junit
+ test
+ 4.11
+
+
+
+
+ org.gcube.common
+ storagehub-client-library
+ [1.0.0,2.0.0-SNAPSHOT)
+
+
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ 2.8.8
+
+
+
+ org.glassfish.jersey.media
+ jersey-media-json-jackson
+
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+
+ com.opencsv
+ opencsv
+ 3.9
+ test
+
+
+
+ com.github.cliftonlabs
+ json-simple
+ 3.1.0
+ test
+
+
+
+
+
+
\ No newline at end of file
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/DefaultMongoConcessioni.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/DefaultMongoConcessioni.java
new file mode 100644
index 0000000..c520d58
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/DefaultMongoConcessioni.java
@@ -0,0 +1,218 @@
+package org.gcube.application.geoportal.client;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.gcube.application.geoportal.client.utils.Serialization;
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.rest.AddSectionToConcessioneRequest;
+import org.gcube.application.geoportal.common.model.rest.Configuration;
+import org.gcube.application.geoportal.common.model.rest.QueryRequest;
+import org.gcube.application.geoportal.common.rest.InterfaceConstants;
+import org.gcube.application.geoportal.common.rest.MongoConcessioni;
+import org.gcube.common.clients.Call;
+import org.gcube.common.clients.delegates.ProxyDelegate;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.rmi.RemoteException;
+import java.util.Iterator;
+
+@RequiredArgsConstructor
+@Slf4j
+public class DefaultMongoConcessioni implements MongoConcessioni{
+
+ @NonNull
+ private final ProxyDelegate delegate;
+
+ private final ObjectMapper mapper=Serialization.mapper;
+
+ @Override
+ public Concessione createNew(Concessione c) throws Exception {
+ log.debug("Serializing {} ",c);
+ final String serialized=mapper.writeValueAsString(c);
+ Call call= endpoint -> {
+ Response resp= endpoint.request(MediaType.APPLICATION_JSON).post(Entity.entity(serialized, MediaType.APPLICATION_JSON));
+ return check(resp,Concessione.class);
+ };
+ Concessione toReturn = delegate.make(call);
+ log.info("Registered {}",toReturn);
+ return toReturn;
+ }
+
+ @Override
+ public void deleteById(String id) throws Exception {
+ deleteById(id,false);
+ }
+
+ @Override
+ public void deleteById(String id,Boolean force) throws Exception {
+ log.debug("Deleting by id {}",id);
+ delegate.make((Call) endpoint -> {
+ check(endpoint.path(id).queryParam(InterfaceConstants.Parameters.FORCE,force).request(MediaType.APPLICATION_JSON).delete(),null);
+ log.info("Deleted by id {}",id);
+ return null;
+ });
+ }
+
+ @Override
+ public Concessione getById(String id) throws Exception {
+ log.debug("Loading by id {}",id);
+ Call call= endpoint -> {
+ Response resp= endpoint.path(id).request(MediaType.APPLICATION_JSON).get();
+ return check(resp,Concessione.class);
+ };
+ Concessione toReturn = delegate.make(call);
+ log.debug("Loaded {}",toReturn);
+ return toReturn;
+ }
+
+ @Override
+ public Iterator getList() throws Exception {
+ log.debug("Getting list");
+ Call> call= endpoint -> mapper.readerFor(Concessione.class).readValues(
+ endpoint.request(MediaType.APPLICATION_JSON).get(InputStream.class));
+ return delegate.make(call);
+ }
+
+ @Override
+ public Concessione publish(String id) throws Exception {
+ log.info("Publishing {} ",id);
+ Call call= endpoint -> {
+ Response resp= endpoint.path(InterfaceConstants.Methods.PUBLISH_PATH).
+ path(id).request(MediaType.APPLICATION_JSON).put(Entity.entity(id, MediaType.APPLICATION_JSON));
+ return check(resp,Concessione.class);
+ };
+ Concessione toReturn = delegate.make(call);
+ log.debug("Published {} ",toReturn);
+ return toReturn;
+ }
+
+ @Override
+ public void unPublish(String id) throws Exception {
+ log.info("Publishing {} ",id);
+
+ Call call= endpoint -> {
+ Response resp= endpoint.path(InterfaceConstants.Methods.PUBLISH_PATH).
+ path(id).request(MediaType.APPLICATION_JSON).delete();
+ check(resp,null);
+ return null;
+ };
+ delegate.make(call);
+ log.debug("UnPublished {} ",id);
+ }
+
+ @Override
+ public Configuration getCurrentConfiguration() throws Exception {
+ return delegate.make(webTarget -> check(webTarget.path(InterfaceConstants.Methods.CONFIGURATION_PATH).
+ request(MediaType.APPLICATION_JSON).get(),Configuration.class));
+ }
+
+ @Override
+ public Iterator search(String s) throws Exception {
+ log.debug("Searching for {}",s);
+ Call> call= endpoint -> {
+ Response resp =endpoint.path(InterfaceConstants.Methods.SEARCH_PATH).request(MediaType.APPLICATION_JSON).
+ post(Entity.entity(s,MediaType.APPLICATION_JSON));
+ return checkCollection(resp,Concessione.class);
+ };
+ return delegate.make(call);
+ }
+
+ @Override
+ public Iterator query(QueryRequest queryRequest) throws Exception {
+ log.debug("Querying for {}",queryRequest);
+ return queryForType(queryRequest,Concessione.class);
+ }
+
+ @Override
+ public String queryForJSON(QueryRequest queryRequest) throws Exception {
+ return null;
+ }
+
+ @Override
+ public Iterator queryForType(QueryRequest queryRequest, Class aClass) throws Exception {
+ log.debug("Querying for {}",queryRequest);
+ Call> call= endpoint -> {
+ Response resp =endpoint.path(InterfaceConstants.Methods.QUERY_PATH).request(MediaType.APPLICATION_JSON).
+ post(Entity.entity(queryRequest,MediaType.APPLICATION_JSON));
+ return checkCollection(resp,aClass);
+ };
+ return delegate.make(call);
+ }
+
+
+ @Override
+ public Concessione registerFileSet(String id, AddSectionToConcessioneRequest request) throws Exception {
+ log.info("Registering {} in {}",request,id);
+ Call call= endpoint -> {
+ Response resp= endpoint.path(InterfaceConstants.Methods.REGISTER_FILES_PATH).
+ path(id).request(MediaType.APPLICATION_JSON).post(Entity.entity(mapper.writeValueAsString(request),
+ MediaType.APPLICATION_JSON));
+ return check(resp,Concessione.class);
+ };
+ Concessione toReturn = delegate.make(call);
+ log.debug("Registered Fileset {} result is {} ",request,toReturn);
+ return toReturn;
+ }
+
+ @Override
+ public Concessione cleanFileSet(String id, String path)throws Exception{
+ log.info("Cleaning Fileset at {} in {}",path,id);
+ Call call= endpoint -> {
+ Response resp= endpoint.path(InterfaceConstants.Methods.DELETE_FILES_PATH).
+ path(id).request(MediaType.APPLICATION_JSON).post(Entity.entity(path,
+ MediaType.APPLICATION_JSON));
+ return check(resp,Concessione.class);
+ };
+ Concessione toReturn = delegate.make(call);
+ log.debug("Cleaned path {} result {} ",path,toReturn);
+ return toReturn;
+ }
+
+ @Override
+ public Concessione update(String id, String jsonUpdate) throws Exception {
+ throw new Exception("To implement");
+ }
+
+ @Override
+ public Concessione replace(Concessione replacement) throws Exception {
+ log.info("Replacing {}",replacement);
+ Call call= endpoint -> {
+ Response resp= endpoint.
+ request(MediaType.APPLICATION_JSON).
+ put(Entity.entity(mapper.writeValueAsString(replacement),
+ MediaType.APPLICATION_JSON));
+ return check(resp,Concessione.class);
+ };
+ Concessione toReturn = delegate.make(call);
+ log.debug("Reloaded {} ",toReturn);
+ return toReturn;
+ }
+
+
+ protected static T check(Response resp, Class clazz) throws IOException {
+ String resString=resp.readEntity(String.class);
+ if(resp.getStatus()<200||resp.getStatus()>=300)
+ throw new RemoteException("RESP STATUS IS "+resp.getStatus()+". Message : "+resString);
+ System.out.println("Resp String is "+resString);
+ if(clazz!=null)
+ return Serialization.read(resString, clazz);
+ else return null;
+ }
+
+ protected static Iterator checkCollection(Response resp, Class clazz) throws IOException {
+ if(resp.getStatus()<200||resp.getStatus()>=300)
+ throw new RemoteException("RESP STATUS IS "+resp.getStatus()+". Message : "+resp.readEntity(String.class));
+ if(clazz!=null)
+ return Serialization.readCollection((InputStream) resp.getEntity(), clazz);
+ else return null;
+ }
+
+
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/DefaultProjects.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/DefaultProjects.java
new file mode 100644
index 0000000..37415f2
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/DefaultProjects.java
@@ -0,0 +1,93 @@
+package org.gcube.application.geoportal.client;
+
+import java.rmi.RemoteException;
+import java.util.Iterator;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+
+import org.gcube.application.geoportal.common.model.project.Project;
+import org.gcube.application.geoportal.common.rest.ProjectsI;
+import org.gcube.common.clients.Call;
+import org.gcube.common.clients.delegates.ProxyDelegate;
+
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class DefaultProjects implements ProjectsI{
+
+ @NonNull
+ private final ProxyDelegate delegate;
+
+ @Override
+ public void deleteById(String profileId, String projectId) throws RemoteException {
+ deleteById(profileId,projectId,false);
+ }
+ @Override
+ public void deleteById(String profileId, String projectId,Boolean force) throws RemoteException {
+// Call call= new Call() {
+//
+// @Override
+// public String call(WebTarget endpoint) throws Exception {
+// endpoint.path(profileId).path(projectId).request(MediaType.APPLICATION_JSON).delete();
+// }
+// };
+// try{
+// delegate.make(call);
+// }catch(Exception e) {
+//// throw new RemoteException(e);
+// }
+ }
+
+ @Override
+ public Iterator getAll() throws RemoteException {
+ Call> call=new Call>(){
+ @Override
+ public Iterator call(WebTarget endpoint) throws Exception {
+ throw new Exception("Client method not ready");
+ }
+ };
+ try{
+ return delegate.make(call);
+ }catch(Exception e) {
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Iterator getByFilter(String filter) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Iterator getByFilter(String filter, String profileId) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Project getById(String profileId, String id) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Iterator getByProfile(String profileId) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Project registrNew(String profileId, String jsonDocument) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Project update(String profileId, String projectId, String jsonDocument) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/GeoPortalClient.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/GeoPortalClient.java
new file mode 100644
index 0000000..f3a0a83
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/GeoPortalClient.java
@@ -0,0 +1,8 @@
+package org.gcube.application.geoportal.client;
+
+public class GeoPortalClient {
+
+
+
+
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/GeoportalAbstractPlugin.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/GeoportalAbstractPlugin.java
new file mode 100644
index 0000000..abbe88d
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/GeoportalAbstractPlugin.java
@@ -0,0 +1,72 @@
+package org.gcube.application.geoportal.client;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.gcube.application.geoportal.client.legacy.ConcessioniManagerI;
+import org.gcube.application.geoportal.client.legacy.ConcessioniPlugin;
+import org.gcube.application.geoportal.client.legacy.MongoConcessioniPlugin;
+import org.gcube.application.geoportal.client.legacy.StatefulMongoConcessioni;
+import org.gcube.application.geoportal.client.legacy.StatefulMongoConcessioniPlugin;
+import org.gcube.application.geoportal.common.rest.ConcessioniI;
+import org.gcube.application.geoportal.common.rest.InterfaceConstants;
+import org.gcube.application.geoportal.common.rest.MongoConcessioni;
+import org.gcube.common.clients.Plugin;
+import org.gcube.common.clients.ProxyBuilder;
+import org.gcube.common.clients.ProxyBuilderImpl;
+import org.gcube.common.clients.config.ProxyConfig;
+
+import lombok.AllArgsConstructor;
+
+@AllArgsConstructor
+public abstract class GeoportalAbstractPlugin implements Plugin{
+
+
+
+ private static ConcessioniPlugin concessioni_plugin=new ConcessioniPlugin();
+
+ private static MongoConcessioniPlugin mongo_concessioni_plugin=new MongoConcessioniPlugin();
+
+ private static StatefulMongoConcessioniPlugin stateful_mongo_concessioni_plugin=new StatefulMongoConcessioniPlugin();
+
+ public static ProxyBuilder concessioni() {
+ return new ProxyBuilderImpl(concessioni_plugin);
+ }
+
+ public static ProxyBuilder mongoConcessioni(){
+ return new ProxyBuilderImpl(mongo_concessioni_plugin);
+ }
+
+ public static ProxyBuilder statefulMongoConcessioni(){
+ return new ProxyBuilderImpl(stateful_mongo_concessioni_plugin);
+ }
+
+
+ @Override
+ public Exception convert(Exception fault, ProxyConfig, ?> config) {
+ return fault;
+ }
+
+
+ @Override
+ public String name() {
+ return InterfaceConstants.APPLICATION_BASE_PATH+InterfaceConstants.APPLICATION_PATH;
+ }
+
+ @Override
+ public String namespace() {
+ return InterfaceConstants.NAMESPACE;
+ }
+
+ @Override
+ public String serviceClass() {
+ return InterfaceConstants.SERVICE_CLASS;
+ }
+
+ @Override
+ public String serviceName() {
+ return InterfaceConstants.SERVICE_NAME;
+ }
+
+
+
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/ProjectsPlugin.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/ProjectsPlugin.java
new file mode 100644
index 0000000..aaa17a5
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/ProjectsPlugin.java
@@ -0,0 +1,41 @@
+package org.gcube.application.geoportal.client;
+
+import javax.ws.rs.client.WebTarget;
+import javax.xml.namespace.QName;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.ws.EndpointReference;
+
+import org.gcube.application.geoportal.common.rest.InterfaceConstants;
+import org.gcube.application.geoportal.common.rest.ProjectsI;
+import org.gcube.common.calls.jaxrs.GcubeService;
+import org.gcube.common.calls.jaxrs.TargetFactory;
+import org.gcube.common.clients.config.ProxyConfig;
+import org.gcube.common.clients.delegates.ProxyDelegate;
+import org.w3c.dom.Node;
+
+public class ProjectsPlugin extends GeoportalAbstractPlugin{
+
+
+ @Override
+ public Exception convert(Exception fault, ProxyConfig, ?> config) {
+ return fault;
+ }
+
+ @Override
+ public ProjectsI newProxy(ProxyDelegate delegate) {
+ return new DefaultProjects(delegate);
+ }
+
+ @Override
+ public WebTarget resolve(EndpointReference address, ProxyConfig, ?> config) throws Exception {
+ DOMResult result = new DOMResult();
+ address.writeTo(result);
+ Node node =result.getNode();
+ Node child=node.getFirstChild();
+ String addressString = child.getTextContent();
+ GcubeService service = GcubeService.service().
+ withName(new QName(InterfaceConstants.NAMESPACE,InterfaceConstants.Methods.PROJECTS)).
+ andPath(InterfaceConstants.Methods.PROJECTS);
+ return TargetFactory.stubFor(service).at(addressString);
+ }
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/ConcessioniManager.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/ConcessioniManager.java
new file mode 100644
index 0000000..ea840ca
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/ConcessioniManager.java
@@ -0,0 +1,136 @@
+package org.gcube.application.geoportal.client.legacy;
+
+import static org.gcube.application.geoportal.client.GeoportalAbstractPlugin.concessioni;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.legacy.InputStreamDescriptor;
+import org.gcube.application.geoportal.common.model.legacy.LayerConcessione;
+import org.gcube.application.geoportal.common.model.legacy.RelazioneScavo;
+import org.gcube.application.geoportal.common.model.legacy.UploadedImage;
+import org.gcube.application.geoportal.common.model.legacy.report.PublicationReport;
+import org.gcube.application.geoportal.common.rest.ConcessioniI;
+
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MappingIterator;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class ConcessioniManager{
+
+ private static ObjectMapper mapper = new ObjectMapper();
+
+ private static ObjectReader concessioniReader=null;
+ private static ObjectReader collectionReader=null;
+
+ static {
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
+ mapper.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false);
+ mapper.setSerializationInclusion(Include.NON_NULL);
+ // mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ mapper.registerModule(new JavaTimeModule());
+ mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
+
+
+ concessioniReader=mapper.readerFor(Concessione.class);
+ collectionReader=mapper.readerFor(Collection.class);
+ }
+
+ private ConcessioniI service;
+
+ private static enum ImplementationType{
+
+ }
+
+ public ConcessioniManager() {
+ service=concessioni().build();
+ }
+
+
+
+
+
+ public Concessione getById(String id) throws Exception {
+ log.info("Reading by ID "+id);
+ try {
+ String result=service.readById(id);
+ log.debug("Reading json object : "+result);
+ return concessioniReader.readValue(result);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw e;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ public static String toJson(Object obj) throws JsonProcessingException {
+ return mapper.writeValueAsString(obj);
+ }
+
+
+ public ArrayList getList() throws Exception{
+ log.info("Getting list");
+ try {
+ String result=service.getAll();
+ log.debug("Reading json object : "+result);
+
+
+ Collection coll=collectionReader.readValue(result);
+// JsonArray array=Json.createReader(new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8))).readArray();
+ ArrayList toReturn=new ArrayList();
+
+// MappingIterator it=concessioniReader.readValues(result);
+// while(it.hasNext())
+// toReturn.add(it.next());
+
+ for(String s: coll) {
+ toReturn.add(concessioniReader.readValue(s));
+ }
+
+
+// for(int i=0;i{
+
+
+
+ @Override
+ public Exception convert(Exception fault, ProxyConfig, ?> config) {
+ return fault;
+ }
+
+ @Override
+ public ConcessioniI newProxy(ProxyDelegate delegate) {
+ return new DefaultConcessioni(delegate);
+ }
+
+
+ @Override
+ public WebTarget resolve(EndpointReference address, ProxyConfig, ?> config) throws Exception {
+ DOMResult result = new DOMResult();
+ address.writeTo(result);
+ Node node =result.getNode();
+ Node child=node.getFirstChild();
+ String addressString = child.getTextContent();
+ GcubeService service = GcubeService.service().
+ withName(new QName(InterfaceConstants.NAMESPACE,InterfaceConstants.Methods.CONCESSIONI)).
+ andPath(InterfaceConstants.Methods.CONCESSIONI);
+ return TargetFactory.stubFor(service).at(addressString);
+ }
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/DefaultConcessioni.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/DefaultConcessioni.java
new file mode 100644
index 0000000..1bf3a42
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/DefaultConcessioni.java
@@ -0,0 +1,71 @@
+package org.gcube.application.geoportal.client.legacy;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+
+import org.gcube.application.geoportal.common.rest.ConcessioniI;
+import org.gcube.common.clients.Call;
+import org.gcube.common.clients.delegates.ProxyDelegate;
+
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class DefaultConcessioni implements ConcessioniI{
+
+ @NonNull
+ private final ProxyDelegate delegate;
+
+ @Override
+ public String create(final String toCreate) throws Exception {
+ Call call= new Call(){
+ @Override
+ public String call(WebTarget endpoint) throws Exception {
+ return endpoint.request(MediaType.APPLICATION_JSON).put(Entity.entity(toCreate, MediaType.APPLICATION_JSON)).readEntity(String.class);
+ }
+ };
+ return delegate.make(call);
+ }
+
+
+ @Override
+ public String readById(final String readById) throws Exception {
+ Call call= new Call(){
+ @Override
+ public String call(WebTarget endpoint) throws Exception {
+ return endpoint.path(readById).request(MediaType.APPLICATION_JSON).get().readEntity(String.class);
+ }
+ };
+ return delegate.make(call);
+ }
+
+ @Override
+ public String getAll() throws Exception {
+ Call call= new Call(){
+ @Override
+ public String call(WebTarget endpoint) throws Exception {
+ return endpoint.request(MediaType.APPLICATION_JSON).get().readEntity(String.class);
+ }
+ };
+ return delegate.make(call);
+ }
+
+// @Override
+// public String update(final String id, final String updated) throws Exception {
+// Call call= new Call(){
+// @Override
+// public String call(WebTarget endpoint) throws Exception {
+// return endpoint.path(id).request(MediaType.APPLICATION_JSON).put(Entity.entity(updated, MediaType.APPLICATION_JSON)).readEntity(String.class);
+// }
+// };
+// return delegate.make(call);
+// }
+
+
+ @Override
+ public String addSection(String arg0, String arg1) throws Exception {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/MongoConcessioniPlugin.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/MongoConcessioniPlugin.java
new file mode 100644
index 0000000..0b16b7d
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/MongoConcessioniPlugin.java
@@ -0,0 +1,41 @@
+package org.gcube.application.geoportal.client.legacy;
+
+import javax.ws.rs.client.WebTarget;
+import javax.xml.namespace.QName;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.ws.EndpointReference;
+
+import org.gcube.application.geoportal.client.DefaultMongoConcessioni;
+import org.gcube.application.geoportal.client.GeoportalAbstractPlugin;
+import org.gcube.application.geoportal.common.rest.InterfaceConstants;
+import org.gcube.application.geoportal.common.rest.MongoConcessioni;
+import org.gcube.common.calls.jaxrs.GcubeService;
+import org.gcube.common.calls.jaxrs.TargetFactory;
+import org.gcube.common.clients.config.ProxyConfig;
+import org.gcube.common.clients.delegates.ProxyDelegate;
+import org.w3c.dom.Node;
+
+public class MongoConcessioniPlugin extends GeoportalAbstractPlugin{
+
+
+
+ @Override
+ public WebTarget resolve(EndpointReference address, ProxyConfig, ?> config) throws Exception {
+ DOMResult result = new DOMResult();
+ address.writeTo(result);
+ Node node =result.getNode();
+ Node child=node.getFirstChild();
+ String addressString = child.getTextContent();
+ GcubeService service = GcubeService.service().
+ withName(new QName(InterfaceConstants.NAMESPACE,InterfaceConstants.Methods.MONGO_CONCESSIONI)).
+ andPath(InterfaceConstants.Methods.MONGO_CONCESSIONI);
+ return TargetFactory.stubFor(service).at(addressString);
+ }
+
+ @Override
+ public MongoConcessioni newProxy(ProxyDelegate delegate) {
+ return new DefaultMongoConcessioni(delegate);
+ }
+
+
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/StatefulMongoConcessioni.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/StatefulMongoConcessioni.java
new file mode 100644
index 0000000..27d7e24
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/StatefulMongoConcessioni.java
@@ -0,0 +1,135 @@
+package org.gcube.application.geoportal.client.legacy;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+
+import javax.ws.rs.client.WebTarget;
+
+import org.gcube.application.geoportal.client.DefaultMongoConcessioni;
+import org.gcube.application.geoportal.client.utils.FileSets;
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.legacy.Concessione.Paths;
+import org.gcube.application.geoportal.common.model.legacy.InputStreamDescriptor;
+import org.gcube.application.geoportal.common.model.legacy.LayerConcessione;
+import org.gcube.application.geoportal.common.model.legacy.RelazioneScavo;
+import org.gcube.application.geoportal.common.model.legacy.UploadedImage;
+import org.gcube.application.geoportal.common.model.rest.AddSectionToConcessioneRequest;
+import org.gcube.application.geoportal.common.rest.TempFile;
+import org.gcube.application.geoportal.common.utils.StorageUtils;
+import org.gcube.common.clients.delegates.ProxyDelegate;
+import org.gcube.contentmanagement.blobstorage.transport.backend.RemoteBackendException;
+
+
+public class StatefulMongoConcessioni extends DefaultMongoConcessioni implements ConcessioniManagerI{
+
+
+
+ public StatefulMongoConcessioni(ProxyDelegate delegate) {
+ super(delegate);
+ }
+
+ private Concessione currentC=null;
+ private StorageUtils storage=new StorageUtils();
+
+
+ // Override methods to handle state
+ @Override
+ public Concessione createNew(Concessione c) throws Exception {
+ currentC=super.createNew(c);
+ return currentC;
+ }
+
+ @Override
+ public Concessione getById(String id) throws Exception {
+ currentC= super.getById(id);
+ return currentC;
+ }
+
+ @Override
+ public Concessione publish() throws Exception {
+ if(currentC==null) throw new Exception("Invalid operation : current Concessione is null.");
+ currentC=super.publish(currentC.getMongo_id());
+ return currentC;
+ }
+
+
+ @Override
+ public void delete() throws Exception {
+ if(currentC==null) throw new Exception("Invalid operation : current Concessione is null.");
+ super.deleteById(currentC.getMongo_id());
+ currentC=null;
+ }
+
+ @Override
+ public Concessione addImmagineRappresentativa(UploadedImage toAdd, TempFile f) throws Exception {
+ if(currentC==null) throw new Exception("Invalid operation : current Concessione is null.");
+ if(currentC.getImmaginiRappresentative()==null) currentC.setImmaginiRappresentative(new ArrayList());
+ currentC.getImmaginiRappresentative().add(toAdd);
+ currentC=replace(currentC);
+
+
+ currentC=super.registerFileSet(currentC.getMongo_id(),
+ FileSets.build(Paths.imgByIndex(currentC.getImmaginiRappresentative().size()-1),f).getTheRequest());
+ return currentC;
+ }
+
+ @Override
+ public Concessione addPiantaFineScavo(LayerConcessione toAdd, TempFile... files) throws Exception {
+ if(currentC==null) throw new Exception("Invalid operation : current Concessione is null.");
+ if(currentC.getPianteFineScavo()==null) currentC.setPianteFineScavo(new ArrayList<>());
+ currentC.getPianteFineScavo().add(toAdd);
+ currentC=replace(currentC);
+
+
+ currentC=super.registerFileSet(currentC.getMongo_id(),
+ FileSets.build(Paths.piantaByIndex(currentC.getPianteFineScavo().size()-1),files).getTheRequest());
+ return currentC;
+ }
+
+ @Override
+ public Concessione setPosizionamento(LayerConcessione toSet, TempFile... files) throws Exception {
+ if(currentC==null) throw new Exception("Invalid operation : current Concessione is null.");
+ currentC.setPosizionamentoScavo(toSet);
+ currentC=replace(currentC);
+
+
+ currentC=super.registerFileSet(currentC.getMongo_id(),
+ FileSets.build(Paths.POSIZIONAMENTO,files).getTheRequest());
+ return currentC;
+ }
+
+ @Override
+ public Concessione setRelazioneScavo(RelazioneScavo toSet, TempFile... files) throws Exception {
+ if(currentC==null) throw new Exception("Invalid operation : current Concessione is null.");
+ currentC.setRelazioneScavo(toSet);
+ currentC=replace(currentC);
+
+
+ currentC=super.registerFileSet(currentC.getMongo_id(),
+ FileSets.build(Paths.RELAZIONE,files).getTheRequest());
+ return currentC;
+ }
+
+
+
+ @Override
+ public Concessione addImmagineRappresentativa(UploadedImage toAdd, InputStreamDescriptor f) throws Exception {
+ return addImmagineRappresentativa(toAdd,FileSets.asTemp(storage,f));
+ }
+
+ @Override
+ public Concessione addPiantaFineScavo(LayerConcessione toAdd, InputStreamDescriptor... files) throws Exception {
+ return addPiantaFineScavo(toAdd, FileSets.asTemp(storage,files));
+ }
+
+ @Override
+ public Concessione setPosizionamento(LayerConcessione toSet, InputStreamDescriptor... files) throws Exception {
+ return setPosizionamento(toSet,FileSets.asTemp(storage,files));
+ }
+
+ @Override
+ public Concessione setRelazioneScavo(RelazioneScavo toSet, InputStreamDescriptor f) throws Exception {
+ return setRelazioneScavo(toSet,FileSets.asTemp(storage,f));
+ }
+
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/StatefulMongoConcessioniPlugin.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/StatefulMongoConcessioniPlugin.java
new file mode 100644
index 0000000..e3df770
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/legacy/StatefulMongoConcessioniPlugin.java
@@ -0,0 +1,38 @@
+package org.gcube.application.geoportal.client.legacy;
+
+import javax.ws.rs.client.WebTarget;
+import javax.xml.namespace.QName;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.ws.EndpointReference;
+
+import org.gcube.application.geoportal.client.GeoportalAbstractPlugin;
+import org.gcube.application.geoportal.common.rest.InterfaceConstants;
+import org.gcube.common.calls.jaxrs.GcubeService;
+import org.gcube.common.calls.jaxrs.TargetFactory;
+import org.gcube.common.clients.config.ProxyConfig;
+import org.gcube.common.clients.delegates.ProxyDelegate;
+import org.w3c.dom.Node;
+
+public class StatefulMongoConcessioniPlugin extends GeoportalAbstractPlugin{
+
+
+ @Override
+ public WebTarget resolve(EndpointReference address, ProxyConfig, ?> config) throws Exception {
+ DOMResult result = new DOMResult();
+ address.writeTo(result);
+ Node node =result.getNode();
+ Node child=node.getFirstChild();
+ String addressString = child.getTextContent();
+ GcubeService service = GcubeService.service().
+ withName(new QName(InterfaceConstants.NAMESPACE,InterfaceConstants.Methods.MONGO_CONCESSIONI)).
+ andPath(InterfaceConstants.Methods.MONGO_CONCESSIONI);
+ return TargetFactory.stubFor(service).at(addressString);
+ }
+
+ @Override
+ public ConcessioniManagerI newProxy(ProxyDelegate delegate) {
+ return new StatefulMongoConcessioni(delegate);
+ }
+
+
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/model/CommunicationException.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/model/CommunicationException.java
new file mode 100644
index 0000000..fd34809
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/model/CommunicationException.java
@@ -0,0 +1,36 @@
+package org.gcube.application.geoportal.client.model;
+
+import lombok.Data;
+
+@Data
+public class CommunicationException extends Exception {
+
+ private String remoteMessage;
+ private Integer responseHTTPCode;
+
+ public CommunicationException() {
+ // TODO Auto-generated constructor stub
+ }
+
+ public CommunicationException(String message) {
+ super(message);
+ // TODO Auto-generated constructor stub
+ }
+
+ public CommunicationException(Throwable cause) {
+ super(cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ public CommunicationException(String message, Throwable cause) {
+ super(message, cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ public CommunicationException(String message, Throwable cause, boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/utils/FileSets.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/utils/FileSets.java
new file mode 100644
index 0000000..5698731
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/utils/FileSets.java
@@ -0,0 +1,86 @@
+package org.gcube.application.geoportal.client.utils;
+
+import org.gcube.application.geoportal.common.model.legacy.InputStreamDescriptor;
+import org.gcube.application.geoportal.common.model.rest.AddSectionToConcessioneRequest;
+import org.gcube.application.geoportal.common.rest.TempFile;
+import org.gcube.application.geoportal.common.utils.StorageUtils;
+import org.gcube.contentmanagement.blobstorage.transport.backend.RemoteBackendException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+public class FileSets {
+
+ public static class RequestBuilder {
+ AddSectionToConcessioneRequest theRequest=new AddSectionToConcessioneRequest();
+
+ public RequestBuilder add(TempFile... f){
+ if(theRequest.getStreams()==null)
+ theRequest.setStreams(new ArrayList());
+ for(TempFile temp: f )
+ theRequest.getStreams().add(temp);
+ return this;
+ }
+
+ public RequestBuilder add(TempFile f){
+ if(theRequest.getStreams()==null)
+ theRequest.setStreams(new ArrayList());
+ theRequest.getStreams().add(f);
+ return this;
+ }
+
+ public RequestBuilder setPath(String path){
+ theRequest.setDestinationPath(path);
+ return this;
+ }
+
+
+
+
+
+ public AddSectionToConcessioneRequest getTheRequest(){return theRequest;}
+ }
+
+
+ public static RequestBuilder build(String path) {
+ return new RequestBuilder().setPath(path);
+ }
+
+ public static RequestBuilder build(String path, TempFile...files) {
+ return new RequestBuilder().setPath(path).add(files);
+ }
+
+ public static TempFile asTemp(StorageUtils storage,InputStreamDescriptor descriptor) throws RemoteBackendException, FileNotFoundException {
+ return storage.putOntoStorage(descriptor.getStream(), descriptor.getFilename());
+ }
+
+ public static TempFile[] asTemp(StorageUtils storage,InputStreamDescriptor... descriptors) throws RemoteBackendException, FileNotFoundException {
+ ArrayList toReturn=new ArrayList();
+ for(InputStreamDescriptor desc:descriptors)
+ toReturn.add(storage.putOntoStorage(desc.getStream(), desc.getFilename()));
+ return toReturn.toArray(new TempFile[toReturn.size()]);
+ }
+
+ public static AddSectionToConcessioneRequest prepareRequestFromFolder(StorageUtils storage, String path, File directory) throws FileNotFoundException {
+
+ File[] children =directory.listFiles();
+ System.out.println("Found "+children+ " files to push");
+ InputStreamDescriptor[] iss=new InputStreamDescriptor[children.length];
+ return prepareRequest(storage,path,children);
+
+ }
+
+ public static AddSectionToConcessioneRequest prepareRequest(StorageUtils storage, String path, File... toUpload) throws FileNotFoundException {
+
+ FileSets.RequestBuilder builder = FileSets.build(path);
+ for (File f : toUpload) {
+ if(!f.isDirectory())
+ builder.add(FileSets.asTemp(storage, new InputStreamDescriptor(new FileInputStream(f), f.getName())));
+ }
+ return builder.getTheRequest();
+ }
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/utils/Queries.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/utils/Queries.java
new file mode 100644
index 0000000..83d9664
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/utils/Queries.java
@@ -0,0 +1,42 @@
+package org.gcube.application.geoportal.client.utils;
+
+import org.apache.commons.io.IOUtils;
+import org.bson.Document;
+import org.gcube.application.geoportal.common.model.rest.QueryRequest;
+import org.gcube.application.geoportal.common.utils.Files;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+
+public class Queries {
+
+
+
+
+
+ public static QueryRequest parse(String json) throws IOException {
+ Document queryDocument=Document.parse(json);
+ QueryRequest req=new QueryRequest();
+ if(queryDocument.containsKey("ordering"))
+ req.setOrdering(Serialization.read(((Document)queryDocument.get("ordering")).toJson(),QueryRequest.OrderedRequest.class));
+ if(queryDocument.containsKey("paging"))
+ req.setPaging(Serialization.read(((Document)queryDocument.get("paging")).toJson(),QueryRequest.PagedRequest.class));
+ req.setProjection(queryDocument.get("projection",Document.class));
+ req.setFilter(queryDocument.get("filter",Document.class));
+
+ return req;
+ };
+
+ public static QueryRequest readPath(String jsonFilePath) throws IOException{
+ return parse(Files.readFileAsString(jsonFilePath, Charset.defaultCharset()));
+ }
+
+ public static QueryRequest readFile(File jsonFile)throws IOException{
+ return parse(Files.readFileAsString(jsonFile.getAbsolutePath(), Charset.defaultCharset()));
+ }
+ public static QueryRequest read(InputStream is)throws IOException{
+ return parse(IOUtils.toString(is));
+ }
+}
diff --git a/geoportal-client/src/main/java/org/gcube/application/geoportal/client/utils/Serialization.java b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/utils/Serialization.java
new file mode 100644
index 0000000..e4f45ef
--- /dev/null
+++ b/geoportal-client/src/main/java/org/gcube/application/geoportal/client/utils/Serialization.java
@@ -0,0 +1,41 @@
+package org.gcube.application.geoportal.client.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.format.DateTimeFormatter;
+import java.util.Iterator;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+public class Serialization {
+
+public static final DateTimeFormatter FULL_FORMATTER=DateTimeFormatter.ofPattern("uuuuMMdd_HH-mm-ss");
+
+ public static ObjectMapper mapper;
+
+ static {
+ mapper=new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
+ mapper.registerModule(new JavaTimeModule());
+ }
+
+ public static T read(String jsonString,Class clazz) throws JsonProcessingException, IOException {
+ return mapper.readerFor(clazz).readValue(jsonString);
+ }
+
+
+ public static String write(Object obj) throws JsonProcessingException, IOException {
+ return mapper.writeValueAsString(obj);
+ }
+
+ public static Iterator readCollection(String jsonString, Class clazz) throws IOException {
+ return mapper.readerFor(clazz).readValues(jsonString);
+ }
+
+ public static Iterator readCollection(InputStream is, Class clazz) throws IOException {
+ return mapper.readerFor(clazz).readValues(is);
+ }
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/StorageTests.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/StorageTests.java
new file mode 100644
index 0000000..5942bcb
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/StorageTests.java
@@ -0,0 +1,34 @@
+package org.gcube.application.geoportal;
+
+import org.gcube.application.geoportal.clients.TokenSetter;
+import org.gcube.application.geoportal.common.rest.TempFile;
+import org.gcube.application.geoportal.common.utils.Files;
+import org.gcube.application.geoportal.common.utils.StorageUtils;
+import org.gcube.common.storagehub.client.dsl.StorageHubClient;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+public class StorageTests {
+
+ public static void main(String[] args) throws FileNotFoundException {
+ FileInputStream fis =new FileInputStream(Files.getFileFromResources("concessioni/relazione.pdf"));
+ String filename= "relazione.pdf";
+
+ String sourceContext="/d4science.research-infrastructures.eu";
+ String targetContext="/pred4s/preprod/preVRE";
+
+ TokenSetter.set(sourceContext);
+
+ StorageHubClient sgClient=new StorageHubClient();
+
+ TokenSetter.set(targetContext);
+
+ TempFile file= new StorageUtils().putOntoStorage(fis,filename);
+
+
+ System.out.println(new StorageUtils().getUrlById(file.getId()));
+
+ }
+
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/BasicVreTests.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/BasicVreTests.java
new file mode 100644
index 0000000..d6cb21b
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/BasicVreTests.java
@@ -0,0 +1,14 @@
+package org.gcube.application.geoportal.clients;
+
+import org.junit.BeforeClass;
+
+public class BasicVreTests {
+
+ @BeforeClass
+ public static void setScope(){
+// TokenSetter.set("/gcube/devNext/NextNext");
+ TokenSetter.set("/gcube/devsec/devVRE");
+ }
+
+
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/StatefulClientTests.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/StatefulClientTests.java
new file mode 100644
index 0000000..e46aa7e
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/StatefulClientTests.java
@@ -0,0 +1,113 @@
+package org.gcube.application.geoportal.clients;
+
+import static org.gcube.application.geoportal.client.GeoportalAbstractPlugin.statefulMongoConcessioni;
+import static org.junit.Assert.*;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+import org.gcube.application.geoportal.client.legacy.ConcessioniManagerI;
+import org.gcube.application.geoportal.client.utils.Serialization;
+import org.gcube.application.geoportal.common.model.TestModel;
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.legacy.InputStreamDescriptor;
+import org.gcube.application.geoportal.common.model.legacy.LayerConcessione;
+import org.gcube.application.geoportal.common.model.legacy.UploadedImage;
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport.ValidationStatus;
+import org.gcube.application.geoportal.common.rest.TempFile;
+import org.gcube.application.geoportal.common.utils.Files;
+import org.gcube.application.geoportal.common.utils.StorageUtils;
+import org.gcube.contentmanagement.blobstorage.transport.backend.RemoteBackendException;
+import org.junit.Test;
+
+
+public class StatefulClientTests extends BasicVreTests{
+
+
+
+ private Concessione publishNew() throws Exception {
+ ConcessioniManagerI manager=statefulMongoConcessioni().build();
+ StorageUtils storage=new StorageUtils();
+
+
+ Concessione toRegister= TestModel.prepareEmptyConcessione();
+ toRegister.setNome("Mock module");
+ manager.createNew(toRegister);
+
+ UploadedImage toRegisterImg=TestModel.prepareConcessione().getImmaginiRappresentative().get(0);
+
+ // TEMP Files are hosted in INFRASTRUCTURE's VOLATILE AREA
+ TempFile toUpload=storage.putOntoStorage(new FileInputStream(Files.getFileFromResources("concessioni/immagine.png")), "immagine.png");
+ manager.addImmagineRappresentativa(toRegisterImg, toUpload);
+
+ //Alternative Method
+ InputStreamDescriptor isDesc=new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/immagine.png")), "immagine.png");
+ manager.addImmagineRappresentativa(toRegisterImg, isDesc);
+
+
+
+ //Relazione
+ manager.setRelazioneScavo(TestModel.prepareConcessione().getRelazioneScavo(),
+ storage.putOntoStorage(new FileInputStream(Files.getFileFromResources("concessioni/relazione.pdf")), "relazione_it.pdf"),
+ storage.putOntoStorage(new FileInputStream(Files.getFileFromResources("concessioni/relazione.pdf")), "relazione_en.pdf"));
+
+ // Posizionamento scavo
+ manager.setPosizionamento(TestModel.prepareConcessione().getPosizionamentoScavo(),
+ storage.putOntoStorage(new FileInputStream(Files.getFileFromResources("concessioni/pos.shp")), "pos.shp"));
+
+ // Piante
+ manager.addPiantaFineScavo(TestModel.prepareConcessione().getPianteFineScavo().get(0),
+ storage.putOntoStorage(new FileInputStream(Files.getFileFromResources("concessioni/pianta.shp")), "pianta.shp"),
+ storage.putOntoStorage(new FileInputStream(Files.getFileFromResources("concessioni/pianta.shx")), "pianta.shx"));
+
+ return manager.publish();
+ }
+
+
+
+ @Test
+ public void testRegisterNew() throws RemoteBackendException, FileNotFoundException, Exception {
+ Concessione published=publishNew();
+
+
+ // VARIOUS CHECKS
+ assertNotNull(published.getReport());
+ assertEquals(published.getReport().getStatus(),ValidationStatus.PASSED);
+
+ assertEquals(published.getImmaginiRappresentative().size(),2);
+ assertEquals(published.getPianteFineScavo().size(),1);
+ assertNotNull(published.getPosizionamentoScavo().getWmsLink());
+ for(LayerConcessione l : published.getPianteFineScavo())
+ assertNotNull(l.getWmsLink());
+ assertNotNull(published.getCentroidLat());
+ assertNotNull(published.getCentroidLong());
+
+ System.out.println(Serialization.write(published));
+ System.out.println(Serialization.write(published.getReport()));
+ }
+
+ @Test
+ public void delete() throws Exception {
+ ConcessioniManagerI manager=statefulMongoConcessioni().build();
+ StorageUtils storage=new StorageUtils();
+
+ manager.createNew(TestModel.prepareEmptyConcessione());
+
+ manager.delete();
+ }
+
+ @Test
+ public void replace() {
+
+ }
+
+ @Test
+ public void getById() {
+
+ }
+
+ @Test
+ public void list() {
+
+ }
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/StatelessClientTests.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/StatelessClientTests.java
new file mode 100644
index 0000000..b01957a
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/StatelessClientTests.java
@@ -0,0 +1,216 @@
+package org.gcube.application.geoportal.clients;
+
+import static org.gcube.application.geoportal.client.GeoportalAbstractPlugin.mongoConcessioni;
+import static org.gcube.application.geoportal.client.GeoportalAbstractPlugin.statefulMongoConcessioni;
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.gcube.application.geoportal.client.legacy.ConcessioniManagerI;
+import org.gcube.application.geoportal.client.utils.Queries;
+import org.gcube.application.geoportal.client.utils.Serialization;
+import org.gcube.application.geoportal.common.model.TestModel;
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.legacy.Concessione.Paths;
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport.ValidationStatus;
+import org.gcube.application.geoportal.common.model.rest.AddSectionToConcessioneRequest;
+import org.gcube.application.geoportal.common.rest.MongoConcessioni;
+import org.gcube.application.geoportal.common.utils.Files;
+import org.gcube.application.geoportal.common.utils.StorageUtils;
+import org.junit.Test;
+
+public class StatelessClientTests extends BasicVreTests{
+
+
+ private MongoConcessioni client=mongoConcessioni().build();
+
+ @Test
+ public void testCreateNew() throws Exception {
+ Concessione c= client.createNew(TestModel.prepareEmptyConcessione());
+ assertNotNull(c);
+ assertNotNull(c.getMongo_id());
+ }
+
+ @Test
+ public void testDeleteById() throws Exception {
+ Concessione c= client.createNew(TestModel.prepareEmptyConcessione());
+ client.deleteById(c.getMongo_id());
+ }
+
+ @Test
+ public void testList() throws Exception {
+ final AtomicLong counter=new AtomicLong();
+ long before=System.currentTimeMillis();
+ client.getList().forEachRemaining((Concessione c)-> {counter.addAndGet(1);});
+ System.out.println("Loaded "+counter+" in "+(System.currentTimeMillis()-before)+" ms");
+ }
+
+ @Test
+ public void testReplace() throws Exception {
+ Concessione c= client.createNew(TestModel.prepareEmptyConcessione());
+
+ String title="My new shiny Title";
+ c.setNome(title);
+ Concessione c1=client.replace(c);
+ assertEquals(title, c1.getNome());
+ }
+
+ @Test
+ public void testUploadFileSet() throws Exception {
+ Concessione c= client.createNew(TestModel.prepareConcessione());
+ assertNotNull(c.getRelazioneScavo());
+ AddSectionToConcessioneRequest request=
+ new AddSectionToConcessioneRequest(Paths.RELAZIONE,
+ Collections.singletonList(new StorageUtils().putOntoStorage(
+ new FileInputStream(Files.getFileFromResources("concessioni/relazione.pdf")), "relazione.pdf")));
+
+ c= client.registerFileSet(c.getMongo_id(), request);
+
+ assertNotNull(c.getRelazioneScavo().getActualContent());
+ assertNotNull(c.getRelazioneScavo().getActualContent().get(0));
+ }
+
+ @Test
+ public void testPublsh() throws Exception {
+ publish(true);
+ }
+
+
+ public Concessione publish(Boolean verify) throws Exception {
+ return publish(verify,client);
+ }
+
+
+
+ public static Concessione publish(Boolean verify,MongoConcessioni client) throws Exception {
+ Concessione c= client.createNew(TestModel.prepareConcessione());
+
+ String mongoId=c.getMongo_id();
+
+ AddSectionToConcessioneRequest request=
+ new AddSectionToConcessioneRequest(Paths.RELAZIONE,
+ Collections.singletonList(new StorageUtils().putOntoStorage(
+ new FileInputStream(Files.getFileFromResources("concessioni/relazione.pdf")), "relazione.pdf")));
+
+ client.registerFileSet(mongoId, request);
+
+ request=
+ new AddSectionToConcessioneRequest(Paths.imgByIndex(0),
+ Collections.singletonList(new StorageUtils().putOntoStorage(
+ new FileInputStream(Files.getFileFromResources("concessioni/immagine.png")), "immagine.png")));
+
+ client.registerFileSet(mongoId, request);
+
+
+ request=
+ new AddSectionToConcessioneRequest(Paths.POSIZIONAMENTO,
+ Collections.singletonList(new StorageUtils().putOntoStorage(
+ new FileInputStream(Files.getFileFromResources("concessioni/pos.shp")), "pos.shp")));
+
+ client.registerFileSet(mongoId, request);
+
+ request=
+ new AddSectionToConcessioneRequest(Paths.piantaByIndex(0),
+ Collections.singletonList(new StorageUtils().putOntoStorage(
+ new FileInputStream(Files.getFileFromResources("concessioni/pianta.shp")), "pianta.shp")));
+
+ client.registerFileSet(mongoId, request);
+
+
+ c=client.publish(mongoId);
+
+ if(verify)
+ assertTrue(c.getReport().getStatus().equals(ValidationStatus.PASSED));
+
+ return c;
+ }
+
+
+ @Test
+ public void getConfiguration() throws Exception {
+ System.out.println(client.getCurrentConfiguration());
+ }
+
+ @Test
+ public void searches() throws Exception {
+ for(File filterFile:new File("src/test/resources/concessioni/filters").listFiles()) {
+ String query=Files.readFileAsString(filterFile.getAbsolutePath(), Charset.defaultCharset());
+ System.out.println("Count for "+filterFile.getName()+"\t"+ count(client.search(query)));
+ }
+ }
+
+
+ @Test
+ public void query() throws Exception {
+ // No Transformation
+ System.out.print("First Registered \t");
+ Iterator queriedDocuments=client.query(
+ Queries.readPath("src/test/resources/concessioni/queries/firstRegistered.json"));
+ // Expected one result
+ assertTrue(count(queriedDocuments)==1);
+
+
+
+ System.out.print("Last Registered \t");
+ // Expected one result
+ queriedDocuments=client.query(
+ Queries.readPath("src/test/resources/concessioni/queries/lastRegistered.json"));
+ assertTrue(count(queriedDocuments)==1);
+
+ queriedDocuments.forEachRemaining((Concessione c)->{System.out.println(c.getNome());});
+
+
+ // Transformations
+ System.out.println(
+ client.queryForJSON(
+ Queries.readPath("src/test/resources/concessioni/queries/lastNameRegisteredByFabio.json")));
+
+ System.out.println(
+ client.queryForJSON(
+ Queries.readPath("src/test/resources/concessioni/queries/publicationWarningMessages.json")));
+
+
+
+
+
+
+// String query=Files.readFileAsString(filterFile.getAbsolutePath(), Charset.defaultCharset());
+// System.out.println("Count for "+filterFile.getName()+"\t"+ count(client.search(query)));
+// }
+ }
+
+ @Test
+ public void testCleanFileSet() throws Exception {
+
+ Concessione c=publish(false);
+ client.unPublish(c.getMongo_id());
+
+ //Precheck to be sure
+ assertFalse(c.getPosizionamentoScavo().getActualContent().isEmpty());
+ assertFalse(c.getPianteFineScavo().get(0).getActualContent().isEmpty());
+
+ //Clear pos
+ c=client.cleanFileSet(c.getMongo_id(),Paths.POSIZIONAMENTO);
+ assertTrue(c.getPosizionamentoScavo().getActualContent().isEmpty());
+
+ //Clear pianta [0]
+ c=client.cleanFileSet(c.getMongo_id(),Paths.piantaByIndex(0));
+ assertTrue(c.getPianteFineScavo().get(0).getActualContent().isEmpty());
+ }
+
+
+ // UTILS
+
+ public static long count(Iterator> iterator){
+ AtomicLong l=new AtomicLong(0);
+ iterator.forEachRemaining(el->{l.incrementAndGet();});
+ return l.get();
+ }
+
+
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/TokenSetter.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/TokenSetter.java
new file mode 100644
index 0000000..ae53e71
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/TokenSetter.java
@@ -0,0 +1,35 @@
+package org.gcube.application.geoportal.clients;
+
+import java.util.Properties;
+
+import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
+import org.gcube.common.scope.api.ScopeProvider;
+
+public class TokenSetter {
+
+
+
+ private static Properties props=new Properties();
+
+ static{
+ try {
+ props.load(TokenSetter.class.getResourceAsStream("/tokens.properties"));
+ } catch (Exception e) {
+ throw new RuntimeException("YOU NEED TO SET TOKEN FILE IN CONFIGURATION");
+ }
+ }
+
+
+ public static void set(String scope){
+ try{
+ if(!props.containsKey(scope)) throw new RuntimeException("No token found for scope : "+scope);
+ SecurityTokenProvider.instance.set(props.getProperty(scope));
+ }catch(Exception e){
+ e.printStackTrace(System.err);
+ throw e;
+ }
+ ScopeProvider.instance.set(scope);
+ }
+
+
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/legacy/ConcessioniTests.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/legacy/ConcessioniTests.java
new file mode 100644
index 0000000..afb1726
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/clients/legacy/ConcessioniTests.java
@@ -0,0 +1,81 @@
+package org.gcube.application.geoportal.clients.legacy;
+
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.gcube.application.geoportal.client.legacy.ConcessioniManager;
+import org.gcube.application.geoportal.clients.BasicVreTests;
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.legacy.GeoServerContent;
+import org.gcube.application.geoportal.common.model.legacy.LayerConcessione;
+import org.gcube.application.geoportal.common.model.legacy.PersistedContent;
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport.ValidationStatus;
+import org.junit.Test;
+
+public class ConcessioniTests extends BasicVreTests {
+
+ static boolean STOP_ON_FAIL=true;
+
+
+
+ @Test
+ public void readAll() throws Exception {
+ ConcessioniManager manager=new ConcessioniManager();
+ ArrayList found=manager.getList();
+ System.out.println("Found "+found.size()+" elements.");
+ final AtomicLong byId=new AtomicLong(0);
+
+ final ArrayList validIDs=new ArrayList<>();
+
+ final ArrayList imgs=new ArrayList();
+ final AtomicLong error=new AtomicLong(0);
+
+ final ArrayList piante=new ArrayList();
+ final ArrayList pos=new ArrayList();
+ final ArrayList wmsLink=new ArrayList();
+
+ found.forEach((Concessione c )->{
+ try {
+ manager.getById(c.getId()+"");
+ byId.incrementAndGet();
+ if(c.validate().getStatus().equals(ValidationStatus.PASSED))
+ validIDs.add(c.getId());
+ if(c.getImmaginiRappresentative()!=null&&c.getImmaginiRappresentative().size()>0)
+ imgs.add(c.getId());
+ if(c.getPianteFineScavo()!=null)
+ c.getPianteFineScavo().forEach((LayerConcessione l)->{
+ if(l.getActualContent()!=null)
+ l.getActualContent().forEach((PersistedContent p)->{
+ if(p instanceof GeoServerContent) piante.add(c.getId());
+ });
+ if(l.getWmsLink()!=null) wmsLink.add(c.getId());
+ });
+
+ if(c.getPosizionamentoScavo()!=null) {
+ LayerConcessione l=c.getPosizionamentoScavo();
+ l.getActualContent().forEach((PersistedContent p)->{
+ if(p instanceof GeoServerContent) pos.add(c.getId());
+ });
+ if(l.getWmsLink()!=null) wmsLink.add(c.getId());
+ }
+ }catch(Throwable t) {
+ error.incrementAndGet();
+ if(STOP_ON_FAIL) {
+ throw new RuntimeException(t);
+ }else t.printStackTrace(System.err);
+ }
+ });
+ System.out.println("Valid count "+validIDs.size()+ "Load BY ID : "+byId.get()+" Error : "+error.get()+" OUT OF "+found.size());
+ System.out.println("Valid IDS "+validIDs);
+ System.out.println("With imgs : "+imgs);
+ System.out.println("With piante : "+piante);
+ System.out.println("With pos : "+pos);
+ System.out.println("With wmsLink : "+wmsLink);
+ }
+
+
+
+
+
+
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/common/model/Serializations.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/common/model/Serializations.java
new file mode 100644
index 0000000..993c926
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/common/model/Serializations.java
@@ -0,0 +1,33 @@
+package org.gcube.application.geoportal.common.model;
+
+import org.gcube.application.geoportal.client.utils.Serialization;
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class Serializations {
+
+ @Test
+ public void readOne(){}
+
+ @Test
+ public void readMulti() throws IOException {
+
+ Iterator it=Serialization.readCollection(
+ new FileInputStream(new File("src/test/resources/concessioni/ConcessioniList.json")),
+ Concessione.class);
+ AtomicLong l=new AtomicLong(0);
+ it.forEachRemaining(element->{l.incrementAndGet();});
+
+
+ Assert.assertTrue(l.get()==4);
+ }
+
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/common/model/TestModel.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/common/model/TestModel.java
new file mode 100644
index 0000000..aac4795
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/common/model/TestModel.java
@@ -0,0 +1,130 @@
+package org.gcube.application.geoportal.common.model;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.UUID;
+
+import org.bson.types.ObjectId;
+import org.gcube.application.geoportal.common.model.legacy.AccessPolicy;
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.legacy.LayerConcessione;
+import org.gcube.application.geoportal.common.model.legacy.RelazioneScavo;
+import org.gcube.application.geoportal.common.model.legacy.UploadedImage;
+
+
+
+public class TestModel {
+
+
+ public static Concessione prepareEmptyConcessione() {
+ Concessione concessione=new Concessione();
+
+ // Generic fields
+
+ // Concessione fields
+
+ concessione.setNome("MONGO Italia, forse, ma su ");
+ concessione.setIntroduzione("This is my MONGO project");
+ concessione.setDescrizioneContenuto("It contains this and that");
+
+ concessione.setAuthors(Arrays.asList(new String[] {"Some one","Some, oneelse"}));
+
+ concessione.setContributore("Contrib 1");
+ concessione.setTitolari(Arrays.asList(new String[] {"Some one","Some, oneelse"}));
+ concessione.setResponsabile("Someone");
+ concessione.setEditore("Editore");
+
+ concessione.setFontiFinanziamento(Arrays.asList(new String[] {"Big pharma","Pentagon"}));
+
+
+ concessione.setSoggetto(Arrays.asList(new String[] {"Research Excavation","Archeology"}));
+
+
+ concessione.setDataInizioProgetto(LocalDateTime.now());
+ concessione.setDataFineProgetto(LocalDateTime.now());
+
+ concessione.setLicenzaID("CC-BY");
+
+ concessione.setTitolareLicenza(Arrays.asList(new String[] {"Qualcun altro"}));
+ concessione.setTitolareCopyright(Arrays.asList(new String[] {"Chiedilo in giro"}));
+
+ concessione.setParoleChiaveLibere(Arrays.asList(new String[] {"Robba","Stuff"}));
+ concessione.setParoleChiaveICCD(Arrays.asList(new String[] {"vattelapesca","somthing something"}));
+
+
+// concessione.setCentroidLat(43.0); //N-S
+// concessione.setCentroidLong(9.0); //E-W
+//
+ return concessione;
+ }
+
+ public static final Concessione setIds(Concessione c) {
+// c.setMongo_id(rnd());
+ c.getRelazioneScavo().setMongo_id(rnd());
+ c.getPosizionamentoScavo().setMongo_id(rnd());
+ c.getPianteFineScavo().forEach((LayerConcessione l)->{l.setMongo_id(rnd());});
+ c.getImmaginiRappresentative().forEach((UploadedImage i)->{i.setMongo_id(rnd());});
+ return c;
+ }
+
+ public static final String rnd() {
+ return new ObjectId().toHexString();
+ }
+ public static Concessione prepareConcessione() {
+ return prepareConcessione(4,2);
+ }
+
+ public static Concessione prepareConcessione(int pianteCount ,int imgsCount) {
+
+ Concessione concessione=prepareEmptyConcessione();
+
+
+
+ // Attachments
+
+ // Relazione scavo
+ RelazioneScavo relScavo=new RelazioneScavo();
+
+ relScavo.setAbstractEng("simple abstract section");
+ relScavo.setAbstractIta("semplice sezione abstract");
+ relScavo.setResponsabili(concessione.getAuthors());
+
+ concessione.setRelazioneScavo(relScavo);
+ //Immagini rappresentative
+ ArrayList imgs=new ArrayList<>();
+ for(int i=0;i piante=new ArrayList();
+ for(int i=0;i toSkipIds=new ArrayList<>();
+// toSkipIds.add("6102c8dd02ad3d05b5f81df4");
+// toSkipIds.add("610415af02ad3d05b5f81ee3");
+
+ AtomicLong count=new AtomicLong(0);
+ AtomicLong nullCount=new AtomicLong(0);
+ AtomicLong errCount=new AtomicLong(0);
+
+
+ Iterator it=null;
+// it=manager.getList();
+ it=manager.search("{\"centroidLat\" : 0}");
+
+ it.forEachRemaining((Concessione c)->{
+ try{
+ String currentId=c.getMongo_id();
+ if(currentId==null) {
+ System.out.println("ID IS NULL " + c);
+ nullCount.incrementAndGet();
+ }
+ else
+ if(toSkipIds.contains(currentId))
+ System.out.println("Skipping "+currentId);
+ else {
+ System.out.println("Deleting " + c.getMongo_id());
+ manager.deleteById(c.getMongo_id(),true);
+ }
+ }catch(Throwable throwable){
+ System.err.println(throwable);
+ errCount.incrementAndGet();
+ }finally {
+ count.incrementAndGet();
+ }
+ });
+
+ System.out.println("Done "+count.get()+" [null : "+nullCount.get()+", err : "+errCount.get()+"]");
+
+ }
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/EditFileSet.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/EditFileSet.java
new file mode 100644
index 0000000..fdc5187
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/EditFileSet.java
@@ -0,0 +1,67 @@
+package org.gcube.application.geoportal.usecases;
+
+import org.gcube.application.geoportal.client.utils.FileSets;
+import org.gcube.application.geoportal.clients.TokenSetter;
+import org.gcube.application.geoportal.common.model.legacy.AssociatedContent;
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.legacy.InputStreamDescriptor;
+import org.gcube.application.geoportal.common.model.rest.AddSectionToConcessioneRequest;
+import org.gcube.application.geoportal.common.rest.MongoConcessioni;
+import org.gcube.application.geoportal.common.utils.StorageUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+import static org.gcube.application.geoportal.client.GeoportalAbstractPlugin.mongoConcessioni;
+
+public class EditFileSet {
+
+ public static void main(String[] args) throws Exception {
+ // params
+ String context="/gcube/devsec/devVRE";
+ String publishOption="true";
+
+ String toUpdateId="6131f42502ad3d2580412da7";
+ String toEditPath= Concessione.Paths.piantaByIndex(0);
+ String folderPath="/Users/fabioisti/Documents/GNA_Ferrandina_2020_inserimento/New Folder With Items/topografia/Piante";
+
+ //Check params
+ Boolean publish = Boolean.parseBoolean(publishOption);
+ File sourceFolder=new File(folderPath);
+ if(!sourceFolder.canRead()) throw new Exception("Cannot read from "+folderPath);
+
+ System.out.println("!!!!!!! SETTING CONTEXT "+context);
+ TokenSetter.set(context);
+
+
+ //Prepare Fileset
+ System.out.println("Preparing request..");
+ StorageUtils storage=new StorageUtils();
+ AddSectionToConcessioneRequest request= FileSets.prepareRequestFromFolder(storage,toEditPath,sourceFolder);
+
+ MongoConcessioni client=mongoConcessioni().build();
+
+ // Unpublish
+ System.out.println("Unpublishing "+toUpdateId);
+ client.unPublish(toUpdateId);
+
+ // update Fileset
+ System.out.println("Removing old fileset.. ");
+ client.cleanFileSet(toUpdateId,toEditPath);
+
+ System.out.println("Sending new Fileset ..");
+ Concessione result= client.registerFileSet(toUpdateId,request);
+
+ if(publish)
+ result = client.publish(toUpdateId);
+
+ System.out.println("Done ");
+ System.out.println("Result : "+result);
+
+
+ }
+
+
+
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/Export.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/Export.java
new file mode 100644
index 0000000..4db84af
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/Export.java
@@ -0,0 +1,159 @@
+package org.gcube.application.geoportal.usecases;
+
+import lombok.extern.slf4j.Slf4j;
+import org.gcube.application.geoportal.client.legacy.ConcessioniManagerI;
+import org.gcube.application.geoportal.client.utils.Serialization;
+import org.gcube.application.geoportal.clients.TokenSetter;
+import org.gcube.application.geoportal.common.model.legacy.*;
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport;
+import org.gcube.application.geoportal.common.rest.TempFile;
+import org.gcube.application.geoportal.common.utils.Files;
+import org.gcube.application.geoportal.common.utils.StorageUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.gcube.application.geoportal.client.GeoportalAbstractPlugin.statefulMongoConcessioni;
+
+@Slf4j
+/*
+Pushes concessioni JSON from folder to geoportal-service
+ */
+public class Export {
+
+
+ public static void main(String[] args) {
+
+ File dir= new File("/Users/fabioisti/git/geoportal-client/import1628178107083");
+// String targetContext="/pred4s/preprod/preVRE";
+ String targetContext="/gcube/devsec/devVRE";
+
+
+
+ ArrayList found=new ArrayList<>();
+ for(File elementFolder:dir.listFiles())
+ for(File jsonFile:elementFolder.listFiles((dir1, name) -> {return name.endsWith(".json");}))
+ try {
+ log.info("Reading "+jsonFile.getAbsolutePath());
+ String json= Files.readFileAsString(jsonFile.getAbsolutePath(), Charset.defaultCharset());
+ found.add(Serialization.read(json,Concessione.class));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ System.out.println("Loaded "+found.size()+" elements from "+dir.getAbsolutePath());
+
+ TokenSetter.set(targetContext);
+ ConcessioniManagerI targetManager = statefulMongoConcessioni().build();
+ StorageUtils storage = new StorageUtils();
+
+ AtomicLong count = new AtomicLong(0);
+ AtomicLong warnCount = new AtomicLong(0);
+ AtomicLong errCount = new AtomicLong(0);
+
+ for (Concessione c : found) {
+ try {
+ log.info("Using {} {}",c.getNome(),c.getMongo_id());
+ Concessione result = push(c, targetManager, new File(dir.getAbsolutePath(),
+ c.getId() + ""), storage);
+ if (!result.getReport().getStatus().equals(ValidationReport.ValidationStatus.PASSED))
+ warnCount.incrementAndGet();
+ } catch (Throwable throwable) {
+ System.err.println(throwable);
+ errCount.incrementAndGet();
+ } finally {
+ count.incrementAndGet();
+ }
+ }
+
+ System.out.println("Done "+count.get()+" [warn : "+warnCount.get()+", err : "+errCount.get()+"]");
+ }
+
+ public static Concessione push(Concessione c, ConcessioniManagerI manager, File dir, StorageUtils storage) throws Exception {
+ // remove GIS references
+ LayerConcessione posizionamento= c.getPosizionamentoScavo();
+ c.setPosizionamentoScavo(null);
+
+ List piante=c.getPianteFineScavo();
+ c.setPianteFineScavo(new ArrayList());
+
+ List imgs=c.getImmaginiRappresentative();
+ c.setImmaginiRappresentative(new ArrayList());
+
+ List other=c.getGenericContent();
+ c.setGenericContent(new ArrayList());
+
+ RelazioneScavo rel=c.getRelazioneScavo();
+ c.setRelazioneScavo(null);
+
+
+ // remove source folder id
+ c.setFolderId(null);
+ c.setMongo_id(null);
+
+ // PUSH PROJECT
+ manager.createNew(c);
+
+
+ // UPLOAD WOrKSPaCE content
+ // Relazione
+ removeContent(rel);
+ manager.setRelazioneScavo(rel, fromPath(dir.toPath().toAbsolutePath()+File.separator+"rel",storage)[0]);
+
+ // Posizionamento
+ removeContent(posizionamento);
+ manager.setPosizionamento(posizionamento,
+ fromPath(dir.toPath().toAbsolutePath()+File.separator+"pos", storage));
+
+
+ //Piante
+ for(int i=0; i toReturn=new ArrayList<>();
+ for(File f : baseDir.toFile().listFiles()){
+ toReturn.add(storage.putOntoStorage(new FileInputStream(f),f.getName()));
+ }
+ log.info("Loaded {} files from {} ",toReturn.size(),path);
+ return toReturn.toArray(new TempFile[toReturn.size()]);
+ }
+
+
+ private static void removeContent(AssociatedContent c){ c.setActualContent(new ArrayList<>());}
+
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/Import.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/Import.java
new file mode 100644
index 0000000..5dea760
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/Import.java
@@ -0,0 +1,110 @@
+package org.gcube.application.geoportal.usecases;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
+import org.gcube.application.geoportal.client.legacy.ConcessioniManager;
+import org.gcube.application.geoportal.client.utils.Serialization;
+import org.gcube.application.geoportal.clients.TokenSetter;
+import org.gcube.application.geoportal.common.model.legacy.*;
+import org.gcube.common.storagehub.client.dsl.FileContainer;
+import org.gcube.common.storagehub.client.dsl.StorageHubClient;
+import org.gcube.common.storagehub.model.exceptions.StorageHubException;
+
+import java.io.*;
+import java.util.ArrayList;
+
+@Slf4j
+/*
+Imports Json concessioni into import
+ */
+public class Import {
+
+
+ public static void main(String[] args) throws Exception {
+
+// Path dir=Files.createTempDirectory(System.currentTimeMillis()+"");
+
+ File dir=new File("import"+System.currentTimeMillis());
+ dir.mkdirs();
+ String sourceContext="/d4science.research-infrastructures.eu/D4OS/GeoNA-Prototype";
+// String sourceContext="/pred4s/preprod/preVRE";
+
+
+
+ // GET FOM SOURCE
+ TokenSetter.set(sourceContext);
+
+ StorageHubClient sgClient=new StorageHubClient();
+
+
+// ConcessioniManagerI manager= statefulMongoConcessioni().build();
+
+ ConcessioniManager sourceManager = new ConcessioniManager();
+ ArrayList found=new ArrayList<>();
+ sourceManager.getList().forEach((Concessione c)->{
+ try {
+ File currentFolder=new File (dir.toString(),c.getId()+"");
+ currentFolder.mkdirs();
+
+ //Load locally
+ // POSIZIONAMENTO
+ loadFiles(c.getPosizionamentoScavo(),new File(currentFolder,"pos"),sgClient);
+ // RELAZIONE
+ loadFiles(c.getRelazioneScavo(),new File(currentFolder,"rel"),sgClient);
+ // IMGs
+ for(int i=0;i toSkipIds=new ArrayList<>();
+
+
+ AtomicLong count=new AtomicLong(0);
+ AtomicLong nullCount=new AtomicLong(0);
+ AtomicLong errCount=new AtomicLong(0);
+ manager.getList().forEachRemaining((Concessione c)->{
+ try{
+ String currentId=c.getMongo_id();
+ if(currentId==null) {
+ System.out.println("ID IS NULL " + c);
+ nullCount.incrementAndGet();
+ }
+ else
+ if(toSkipIds.contains(currentId))
+ System.out.println("Skipping "+currentId);
+ else {
+ System.out.println("Upublishing " + c.getMongo_id());
+ manager.unPublish(c.getMongo_id());
+
+ System.out.println("Republishing" + c.getMongo_id());
+ manager.publish(c.getMongo_id());
+ }
+ }catch(Throwable throwable){
+ System.err.println(throwable);
+ errCount.incrementAndGet();
+ }finally {
+ count.incrementAndGet();
+ }
+ });
+
+ System.out.println("Done "+count.get()+" [null : "+nullCount.get()+", err : "+errCount.get()+"]");
+
+ }
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/UnpublishSingle.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/UnpublishSingle.java
new file mode 100644
index 0000000..369ed4d
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/UnpublishSingle.java
@@ -0,0 +1,17 @@
+package org.gcube.application.geoportal.usecases;
+
+import org.gcube.application.geoportal.client.legacy.ConcessioniManagerI;
+import org.gcube.application.geoportal.clients.TokenSetter;
+
+import static org.gcube.application.geoportal.client.GeoportalAbstractPlugin.statefulMongoConcessioni;
+
+public class UnpublishSingle {
+
+ public static void main(String[] args) throws Exception {
+ TokenSetter.set("/gcube/devsec/devVRE");
+
+ ConcessioniManagerI manager=statefulMongoConcessioni().build();
+
+ manager.publish("610415af02ad3d05b5f81ee3");
+ }
+}
diff --git a/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/mocks/MockFromFolder.java b/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/mocks/MockFromFolder.java
new file mode 100644
index 0000000..b7fb9ab
--- /dev/null
+++ b/geoportal-client/src/test/java/org/gcube/application/geoportal/usecases/mocks/MockFromFolder.java
@@ -0,0 +1,171 @@
+package org.gcube.application.geoportal.usecases.mocks;
+
+import com.opencsv.CSVReader;
+import lombok.extern.slf4j.Slf4j;
+import org.gcube.application.geoportal.client.legacy.ConcessioniManagerI;
+import org.gcube.application.geoportal.client.utils.FileSets;
+import org.gcube.application.geoportal.clients.StatelessClientTests;
+import org.gcube.application.geoportal.clients.TokenSetter;
+import org.gcube.application.geoportal.common.model.TestModel;
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.legacy.InputStreamDescriptor;
+import org.gcube.application.geoportal.common.model.legacy.UploadedImage;
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport;
+import org.gcube.application.geoportal.common.model.rest.AddSectionToConcessioneRequest;
+import org.gcube.application.geoportal.common.rest.MongoConcessioni;
+import org.gcube.application.geoportal.common.rest.TempFile;
+import org.gcube.application.geoportal.common.utils.Files;
+import org.gcube.application.geoportal.common.utils.StorageUtils;
+import org.gcube.contentmanagement.blobstorage.service.IClient;
+
+import java.io.*;
+import java.lang.reflect.Array;
+import java.util.*;
+
+import static org.gcube.application.geoportal.client.GeoportalAbstractPlugin.mongoConcessioni;
+import static org.gcube.application.geoportal.client.GeoportalAbstractPlugin.statefulMongoConcessioni;
+import static org.junit.Assert.assertTrue;
+
+@Slf4j
+public class MockFromFolder {
+
+ public static void main(String[] args) throws Exception {
+ //PARAMS
+ String context="/gcube/devsec/devVRE";
+
+ //Concessioni 04-03
+ //String packageBaseDir="/Users/fabioisti/Documents/Concessioni 04-03/";
+ //String csvDescriptor="src/test/resources/concessioni/concessioni04-03.csv";
+
+ //DATASET_GNA_01
+// String packageBaseDir="/Users/fabioisti/Documents/DATASET_GNA_01";
+// String csvDescriptor="src/test/resources/concessioni/DATASET_GNA_01.csv";
+
+ //DATASET_GNA_02
+ //String packageBaseDir="/Users/fabioisti/Documents/DATASET_GNA_02";
+ //String csvDescriptor="src/test/resources/concessioni/DATASET_GNA_02.csv";
+
+
+ // invio_08_02
+// String packageBaseDir="/Users/fabioisti/Documents/invio_08_05";
+// String csvDescriptor="src/test/resources/concessioni/invio_08_05.csv";
+
+ // concessioni 23_04
+ String packageBaseDir="/Users/fabioisti/Documents/Concessioni_23_04";
+ String csvDescriptor="src/test/resources/concessioni/concessioni_23_04.csv";
+
+
+
+
+ TokenSetter.set(context);
+
+ MongoConcessioni client=mongoConcessioni().build();
+ StorageUtils storage=new StorageUtils();
+
+
+ long publishedCount=0l;
+ long successcount=0l;
+ long entrycount=0l;
+
+ //Parse CSV descriptor
+ File baseDir=new File(packageBaseDir);
+ ArrayList pushed=new ArrayList<>();
+
+ CSVReader reader = new CSVReader(new FileReader(csvDescriptor));
+ String [] nextLine;
+ //reads one line at a time
+ while ((nextLine = reader.readNext()) != null)
+ {
+ entrycount++;
+ //Create new
+ String projectName = nextLine[0];
+ String positionPath = nextLine[1];
+ String piantePath = nextLine[2];
+
+
+ try {
+ //NB raggruppa per file
+ Map.Entry> posSets = clusterizeFiles(positionPath, baseDir).entrySet().stream().findFirst().get();
+ Map> pianteSets = clusterizeFiles(piantePath, baseDir);
+
+ // Sometimes they are the same
+ if(positionPath.equals(piantePath))
+ pianteSets.remove(posSets.getKey());
+
+ log.debug("Entry {} pos Size {} piante {} ",projectName,posSets.getValue().size(),pianteSets.size());
+
+ Concessione c = createMock(projectName, pianteSets, posSets.getValue(), client, storage);
+
+ publishedCount++;
+ if (c.getReport().getStatus().equals(ValidationReport.ValidationStatus.PASSED))
+ successcount++;
+ pushed.add(c);
+ }catch(Throwable t){
+ System.err.println("Problematic entry "+projectName);
+ t.printStackTrace(System.err);
+ }
+
+ }
+
+ System.out.println("Done "+publishedCount+" [SUCCESS : "+successcount+"] \t OUT OF :"+entrycount+" entries");
+
+ pushed.forEach(c -> {
+ try{
+ System.out.println(c.getNome()+"\t"+c.getMongo_id()+"\t"+c.getReport().getStatus());
+ }catch(Throwable t){
+ System.out.println(c.getNome()+"\t"+c.getMongo_id()+"\t PROBLEMATIC, NO REPORT");
+ }
+ });
+ }
+
+
+
+ private static Map> clusterizeFiles(String basePath,File packageFolder) throws IOException {
+ log.debug("Clusterizing "+basePath);
+
+ HashMap> toReturn = new HashMap<>();
+ File baseDir=new File(packageFolder,basePath);
+ for(File shp:baseDir.listFiles((dir,name)->{return name.endsWith(".shp");})) {
+ String basename=shp.getName().substring(0,shp.getName().lastIndexOf("."));
+ List fileset=new ArrayList<>();
+ for (File shpSet : baseDir.listFiles((dir, name) -> {return name.startsWith(basename);}))
+ fileset.add(shpSet);
+ log.debug("SHP {} Set size {} ",basename,fileset.size());
+ toReturn.put(basename,fileset);
+ }
+ return toReturn;
+ }
+
+ private static Concessione createMock(String baseName,Map> piante, List pos,
+ MongoConcessioni client, StorageUtils storage) throws Exception {
+
+ Concessione c=TestModel.prepareConcessione(piante.size(), 2);
+ c.setNome("Mock for "+baseName);
+ c= client.createNew(c);
+ String mongoId=c.getMongo_id();
+
+ // TEST DATA, DO NOT CARE
+ client.registerFileSet(mongoId, FileSets.prepareRequest(storage,
+ Concessione.Paths.RELAZIONE,new File ("src/test/resources/concessioni/relazione.pdf")));
+
+ client.registerFileSet(mongoId, FileSets.prepareRequest(storage,
+ Concessione.Paths.imgByIndex(0),new File("src/test/resources/concessioni/immagine.png")));
+
+ // POSIZIONAMENTO
+
+ client.registerFileSet(mongoId, FileSets.prepareRequest(storage,
+ Concessione.Paths.POSIZIONAMENTO,pos.toArray(new File[pos.size()])));
+
+ Map.Entry>[] entries= piante.entrySet().toArray(new Map.Entry[0]);
+ for( int i= 0; i< piante.size();i++)
+ client.registerFileSet(mongoId, FileSets.prepareRequest(storage,
+ Concessione.Paths.piantaByIndex(i),entries[i].getValue().toArray(new File[0])));
+
+ c=client.publish(mongoId);
+
+ System.out.println("@@@ Concessione "+c.getNome()+"\t STATUS : "+ c.getReport().getStatus());
+
+ return c;
+ }
+
+}
diff --git a/geoportal-client/src/test/resources/concessioni/Concessione.json b/geoportal-client/src/test/resources/concessioni/Concessione.json
new file mode 100644
index 0000000..612b021
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/Concessione.json
@@ -0,0 +1,747 @@
+{
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "centroidLat": 43.0,
+ "centroidLong": 9.0,
+ "contributore": "Contrib 1",
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "creationUser": "NO NAME",
+ "dataFineProgetto": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 17,
+ 6000000
+ ],
+ "dataInizioProgetto": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 16,
+ 994000000
+ ],
+ "descrizioneContenuto": "It contains this and that",
+ "editore": "Editore",
+ "folderId": "5f14252f-55df-4c9a-94d9-9ad190efbe6a",
+ "fontiFinanziamento": [
+ "Big pharma",
+ "Pentagon"
+ ],
+ "genericContent": [],
+ "id": 8,
+ "immaginiRappresentative": [
+ {
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 187,
+ "link": "https://data.dev.d4science.org/shub/E_VGFQSExUR1BmdzVHNjI5ZjFJeXE1TUFpWEkxUGllelIyWVZndndKZ3pBaGNPWlNGczdFaUNtMHVZaEd0dXc2Rw==",
+ "mimetype": "image/png",
+ "storageID": "6765deab-b157-494f-83e2-299032e1904c",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 35,
+ 177000000
+ ],
+ "didascalia": "You can see my image number 0",
+ "format": "TIFF",
+ "id": 67,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "My image number 0",
+ "type": "UploadedImage"
+ },
+ {
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 188,
+ "link": "https://data.dev.d4science.org/shub/E_NDVyQnBiMFJ1VDliYS83eEJvYS9vb1JrZ2tQN2orY3ZXNUJia25McFFtNlMrSS91NHNBN3pPVUNzTGN2aE9JOQ==",
+ "mimetype": "image/png",
+ "storageID": "4b4fb9f9-b96d-485d-80c9-713fad8a5c9b",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 35,
+ 177000000
+ ],
+ "didascalia": "You can see my image number 1",
+ "format": "TIFF",
+ "id": 68,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "My image number 1",
+ "type": "UploadedImage"
+ },
+ {
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 189,
+ "link": "https://data.dev.d4science.org/shub/E_YWw0TXVKa29KZFJOeDMwVlRDc29xMW0zSExYdGRJdmxZWEtJSGRVZ3ZBRVEwTnc1cEdMNG1iVVRBN2JDVG9WYQ==",
+ "mimetype": "image/png",
+ "storageID": "2690d6bc-2833-4797-81bb-1c1865f34f34",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 35,
+ 177000000
+ ],
+ "didascalia": "You can see my image number 2",
+ "format": "TIFF",
+ "id": 69,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "My image number 2",
+ "type": "UploadedImage"
+ },
+ {
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 190,
+ "link": "https://data.dev.d4science.org/shub/E_TU9ha0lGMTRhTDl6S2IzWDNmUWROVXZjZzJiSmNrS1BjZ3gycUJvVEI2b0ZDaGxuK1dUWmlsNW1DZE1ESUJPbA==",
+ "mimetype": "image/png",
+ "storageID": "244b0fe0-8f53-469a-9c5e-ac63e37d4622",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 35,
+ 177000000
+ ],
+ "didascalia": "You can see my image number 3",
+ "format": "TIFF",
+ "id": 70,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "My image number 3",
+ "type": "UploadedImage"
+ },
+ {
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 191,
+ "link": "https://data.dev.d4science.org/shub/E_NXZYZnV3RlFTYzRWOTBOMWt0cmFtVUtTU20xWTBQb3daRVV6RU8zTDc5RU9USnZVL3Y1VmpRNHNaajMyelVTMQ==",
+ "mimetype": "image/png",
+ "storageID": "6fab2082-08af-4899-9730-462b011b517d",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 35,
+ 177000000
+ ],
+ "didascalia": "You can see my image number 4",
+ "format": "TIFF",
+ "id": 71,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "My image number 4",
+ "type": "UploadedImage"
+ }
+ ],
+ "introduzione": "This is my project",
+ "lastUpdateTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "lastUpdateUser": "NO NAME",
+ "licenzaID": "CC-BY",
+ "nome": "Italia, forse",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "pianteFineScavo": [
+ {
+ "abstractSection": "Planimetria georeferenziata dell'area indagata al termine delle attività",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 196,
+ "link": "https://data.dev.d4science.org/shub/E_aTZqVlNzRlRVSUFVZXhBNVp2bDdYMDlRTnNwVlRGRXNqMlI3MkxTdXlrWVFJeDF0L3pLemtaTDBwWFA3TVJKUw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "debd7027-56fe-4cff-ae87-b0df94421035",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 193,
+ "link": "https://data.dev.d4science.org/shub/E_UWpOTUYvRTRvV2hCYS8wQ3BaSG5GdG00MXdyeVg2M3dnZk5ZSEd3a0RxdWs0YUJTalFMK1JJQ2x5dFlySTZ4Lw==",
+ "mimetype": "text/plain",
+ "storageID": "d44b073f-6828-4dfd-a1fc-1d5eed93abc5",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 195,
+ "link": "https://data.dev.d4science.org/shub/E_SXUrWi9OZW9MMXpTSzdraGhveXNpaVo3b0Fid1loc1BEdnlqVmdGaWd1U2czb1YxdDhPeHNBWmovV21xRmxXVw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "4e184a77-915b-4ebd-bcb8-08ac8138069b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 194,
+ "link": "https://data.dev.d4science.org/shub/E_RFZ0V2NUaDB5bCt4bGo5MnByZXZoRW5rWnRSWXFoRzdnQmxqTHlYSlhCeTU5RHZ3S2Ywa0ZDUCtUOCtZK3VkdQ==",
+ "mimetype": "text/plain",
+ "storageID": "f0f1fff4-6ee4-47c5-92be-2fd2c1ab5687",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 192,
+ "link": "https://data.dev.d4science.org/shub/E_cFZ6MFgvR1gzWmx0d2hvRmVnVTBQTEszdG1seEN3d2tBcHNsYkFXVlhKRUtucHZKb24xakEwa1IwQWJCTjc3cA==",
+ "mimetype": "application/x-dbf",
+ "storageID": "2c542d5a-ca89-42bb-87c9-1bceb8f0f03b",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "bbox": {
+ "maxLat": 90.0,
+ "maxLong": 180.0,
+ "minLat": -90.0,
+ "minLong": -180.0
+ },
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 72,
+ "layerID": null,
+ "layerName": null,
+ "layerUUID": null,
+ "licenseID": "CC-BY",
+ "metodoRaccoltaDati": "Fattobbene",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "policy": "RESTRICTED",
+ "record": null,
+ "responsabile": "Someone",
+ "scalaAcquisizione": "1:10000",
+ "subTopic": "Archeology",
+ "titolo": "Italia, forse pianta fine scavo",
+ "topicCategory": "Society",
+ "type": "LayerConcessione",
+ "valutazioneQualita": "Secondo me si",
+ "wmsLink": null
+ },
+ {
+ "abstractSection": "Planimetria georeferenziata dell'area indagata al termine delle attività",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 198,
+ "link": "https://data.dev.d4science.org/shub/E_UWpOTUYvRTRvV2hCYS8wQ3BaSG5GdG00MXdyeVg2M3dnZk5ZSEd3a0RxdWs0YUJTalFMK1JJQ2x5dFlySTZ4Lw==",
+ "mimetype": "text/plain",
+ "storageID": "d44b073f-6828-4dfd-a1fc-1d5eed93abc5",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 197,
+ "link": "https://data.dev.d4science.org/shub/E_cFZ6MFgvR1gzWmx0d2hvRmVnVTBQTEszdG1seEN3d2tBcHNsYkFXVlhKRUtucHZKb24xakEwa1IwQWJCTjc3cA==",
+ "mimetype": "application/x-dbf",
+ "storageID": "2c542d5a-ca89-42bb-87c9-1bceb8f0f03b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 200,
+ "link": "https://data.dev.d4science.org/shub/E_SXUrWi9OZW9MMXpTSzdraGhveXNpaVo3b0Fid1loc1BEdnlqVmdGaWd1U2czb1YxdDhPeHNBWmovV21xRmxXVw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "4e184a77-915b-4ebd-bcb8-08ac8138069b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 199,
+ "link": "https://data.dev.d4science.org/shub/E_RFZ0V2NUaDB5bCt4bGo5MnByZXZoRW5rWnRSWXFoRzdnQmxqTHlYSlhCeTU5RHZ3S2Ywa0ZDUCtUOCtZK3VkdQ==",
+ "mimetype": "text/plain",
+ "storageID": "f0f1fff4-6ee4-47c5-92be-2fd2c1ab5687",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 201,
+ "link": "https://data.dev.d4science.org/shub/E_aTZqVlNzRlRVSUFVZXhBNVp2bDdYMDlRTnNwVlRGRXNqMlI3MkxTdXlrWVFJeDF0L3pLemtaTDBwWFA3TVJKUw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "debd7027-56fe-4cff-ae87-b0df94421035",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "bbox": {
+ "maxLat": 90.0,
+ "maxLong": 180.0,
+ "minLat": -90.0,
+ "minLong": -180.0
+ },
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 73,
+ "layerID": null,
+ "layerName": null,
+ "layerUUID": null,
+ "licenseID": "CC-BY",
+ "metodoRaccoltaDati": "Fattobbene",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "policy": "RESTRICTED",
+ "record": null,
+ "responsabile": "Someone",
+ "scalaAcquisizione": "1:10000",
+ "subTopic": "Archeology",
+ "titolo": "Italia, forse pianta fine scavo",
+ "topicCategory": "Society",
+ "type": "LayerConcessione",
+ "valutazioneQualita": "Secondo me si",
+ "wmsLink": null
+ },
+ {
+ "abstractSection": "Planimetria georeferenziata dell'area indagata al termine delle attività",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 202,
+ "link": "https://data.dev.d4science.org/shub/E_cFZ6MFgvR1gzWmx0d2hvRmVnVTBQTEszdG1seEN3d2tBcHNsYkFXVlhKRUtucHZKb24xakEwa1IwQWJCTjc3cA==",
+ "mimetype": "application/x-dbf",
+ "storageID": "2c542d5a-ca89-42bb-87c9-1bceb8f0f03b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 204,
+ "link": "https://data.dev.d4science.org/shub/E_RFZ0V2NUaDB5bCt4bGo5MnByZXZoRW5rWnRSWXFoRzdnQmxqTHlYSlhCeTU5RHZ3S2Ywa0ZDUCtUOCtZK3VkdQ==",
+ "mimetype": "text/plain",
+ "storageID": "f0f1fff4-6ee4-47c5-92be-2fd2c1ab5687",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 205,
+ "link": "https://data.dev.d4science.org/shub/E_SXUrWi9OZW9MMXpTSzdraGhveXNpaVo3b0Fid1loc1BEdnlqVmdGaWd1U2czb1YxdDhPeHNBWmovV21xRmxXVw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "4e184a77-915b-4ebd-bcb8-08ac8138069b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 203,
+ "link": "https://data.dev.d4science.org/shub/E_UWpOTUYvRTRvV2hCYS8wQ3BaSG5GdG00MXdyeVg2M3dnZk5ZSEd3a0RxdWs0YUJTalFMK1JJQ2x5dFlySTZ4Lw==",
+ "mimetype": "text/plain",
+ "storageID": "d44b073f-6828-4dfd-a1fc-1d5eed93abc5",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 206,
+ "link": "https://data.dev.d4science.org/shub/E_aTZqVlNzRlRVSUFVZXhBNVp2bDdYMDlRTnNwVlRGRXNqMlI3MkxTdXlrWVFJeDF0L3pLemtaTDBwWFA3TVJKUw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "debd7027-56fe-4cff-ae87-b0df94421035",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "bbox": {
+ "maxLat": 90.0,
+ "maxLong": 180.0,
+ "minLat": -90.0,
+ "minLong": -180.0
+ },
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 74,
+ "layerID": null,
+ "layerName": null,
+ "layerUUID": null,
+ "licenseID": "CC-BY",
+ "metodoRaccoltaDati": "Fattobbene",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "policy": "RESTRICTED",
+ "record": null,
+ "responsabile": "Someone",
+ "scalaAcquisizione": "1:10000",
+ "subTopic": "Archeology",
+ "titolo": "Italia, forse pianta fine scavo",
+ "topicCategory": "Society",
+ "type": "LayerConcessione",
+ "valutazioneQualita": "Secondo me si",
+ "wmsLink": null
+ },
+ {
+ "abstractSection": "Planimetria georeferenziata dell'area indagata al termine delle attività",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 209,
+ "link": "https://data.dev.d4science.org/shub/E_RFZ0V2NUaDB5bCt4bGo5MnByZXZoRW5rWnRSWXFoRzdnQmxqTHlYSlhCeTU5RHZ3S2Ywa0ZDUCtUOCtZK3VkdQ==",
+ "mimetype": "text/plain",
+ "storageID": "f0f1fff4-6ee4-47c5-92be-2fd2c1ab5687",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 211,
+ "link": "https://data.dev.d4science.org/shub/E_aTZqVlNzRlRVSUFVZXhBNVp2bDdYMDlRTnNwVlRGRXNqMlI3MkxTdXlrWVFJeDF0L3pLemtaTDBwWFA3TVJKUw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "debd7027-56fe-4cff-ae87-b0df94421035",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 207,
+ "link": "https://data.dev.d4science.org/shub/E_cFZ6MFgvR1gzWmx0d2hvRmVnVTBQTEszdG1seEN3d2tBcHNsYkFXVlhKRUtucHZKb24xakEwa1IwQWJCTjc3cA==",
+ "mimetype": "application/x-dbf",
+ "storageID": "2c542d5a-ca89-42bb-87c9-1bceb8f0f03b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 208,
+ "link": "https://data.dev.d4science.org/shub/E_UWpOTUYvRTRvV2hCYS8wQ3BaSG5GdG00MXdyeVg2M3dnZk5ZSEd3a0RxdWs0YUJTalFMK1JJQ2x5dFlySTZ4Lw==",
+ "mimetype": "text/plain",
+ "storageID": "d44b073f-6828-4dfd-a1fc-1d5eed93abc5",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 210,
+ "link": "https://data.dev.d4science.org/shub/E_SXUrWi9OZW9MMXpTSzdraGhveXNpaVo3b0Fid1loc1BEdnlqVmdGaWd1U2czb1YxdDhPeHNBWmovV21xRmxXVw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "4e184a77-915b-4ebd-bcb8-08ac8138069b",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "bbox": {
+ "maxLat": 90.0,
+ "maxLong": 180.0,
+ "minLat": -90.0,
+ "minLong": -180.0
+ },
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 75,
+ "layerID": null,
+ "layerName": null,
+ "layerUUID": null,
+ "licenseID": "CC-BY",
+ "metodoRaccoltaDati": "Fattobbene",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "policy": "RESTRICTED",
+ "record": null,
+ "responsabile": "Someone",
+ "scalaAcquisizione": "1:10000",
+ "subTopic": "Archeology",
+ "titolo": "Italia, forse pianta fine scavo",
+ "topicCategory": "Society",
+ "type": "LayerConcessione",
+ "valutazioneQualita": "Secondo me si",
+ "wmsLink": null
+ }
+ ],
+ "policy": "OPEN",
+ "posizionamentoScavo": {
+ "abstractSection": "Posizionamento topografico georeferenziato dell’area interessata dalle indagini",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 214,
+ "link": "https://data.dev.d4science.org/shub/E_UjJoQkw2a0VlR3djQnVYMlNaME40VkdLL3pxV21DNmRrWXVZUlFhMk53aXJORVJmM29pcHpPdVc4aHZLUTRwcg==",
+ "mimetype": "text/plain",
+ "storageID": "fac45dad-4840-4fda-b613-0bfd831d8720",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 213,
+ "link": "https://data.dev.d4science.org/shub/E_T0lsR09LbVdqMExWT1ZwZWpZSW4zUXBqZlV2bCt6d3hMbnc5UDBvRW45eENONzB4cXNtZ216cXZFNWVzdjU0eg==",
+ "mimetype": "text/plain",
+ "storageID": "d599e90f-26e0-4b27-b85e-bedd286ff2d7",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 215,
+ "link": "https://data.dev.d4science.org/shub/E_U2NhMXUvMzRycE9YYkRmbHphdC82QlJJN2FEeVd0Y1FEQmxwSjNmcWRTUDZoZHhVQ1VPdjRMVVdOVDcxNTh5Yw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "f1080875-7f01-4658-9758-9388262ad12c",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 216,
+ "link": "https://data.dev.d4science.org/shub/E_RlBWRW5lUG9nbncxSC9ZQlRURmFSeTQ3Q0ZqdDhOK2luV01uWjUxMTZ4OHREa29US2t3K21RblpjaXFMTWtSSA==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "6b7eeb40-0cd1-4fe5-97b5-b7091e6b7531",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 212,
+ "link": "https://data.dev.d4science.org/shub/E_aHQxcDhoRGN0QXdXZTkwUmtKRlJsUFVqWjM4STY3U0JkVGU1L3l1a2t5WkhFWlc4blpoa0QxaDVRaHZCOXR2Nw==",
+ "mimetype": "application/x-dbf",
+ "storageID": "9af11436-2241-4a03-a95b-96849272bc25",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "bbox": {
+ "maxLat": 90.0,
+ "maxLong": 180.0,
+ "minLat": -90.0,
+ "minLong": -180.0
+ },
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 76,
+ "layerID": null,
+ "layerName": null,
+ "layerUUID": null,
+ "licenseID": "CC-BY",
+ "metodoRaccoltaDati": "Fattobbene",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "policy": "OPEN",
+ "record": null,
+ "responsabile": "Someone",
+ "scalaAcquisizione": "1:10000",
+ "subTopic": "Archeology",
+ "titolo": "Italia, forse posizionamento scavo",
+ "topicCategory": "Society",
+ "type": "LayerConcessione",
+ "valutazioneQualita": "Secondo me si",
+ "wmsLink": null
+ },
+ "recordType": "CONCESSIONE",
+ "relazioneScavo": {
+ "abstractSection": "simple abstract section",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 217,
+ "link": "https://data.dev.d4science.org/shub/E_a0JGWWNsY0tFc29CVC8xUW1ROUJhMnVaaWwxNk5TTk5TRlgvQW1tbkpLdDBuNFU3Rkg2VmlFVW53TEUzaEM4aA==",
+ "mimetype": "application/pdf",
+ "storageID": "e0cd721a-89e4-437d-9fba-2bfc197cb4c1",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 77,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "Italia, forse relazione di scavo",
+ "type": "RelazioneScavo"
+ },
+ "responsabile": "Someone",
+ "risorseCorrelate": [],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolareCopyright": "Chiedilo in giro",
+ "titolareLicenza": "Qualcun altro",
+ "titolari": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "version": "1.0.0"
+}
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/ConcessioniList.json b/geoportal-client/src/test/resources/concessioni/ConcessioniList.json
new file mode 100644
index 0000000..8258a73
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/ConcessioniList.json
@@ -0,0 +1 @@
+[{"mongo_id":"612fabe58b7a9ee012cf797b","id":0,"recordType":"CONCESSIONE","version":"1.0.0","licenzaID":"CC-BY","policy":"OPEN","nome":"Concessione : publish test","folderId":"5c312758-0233-461f-9b9c-2bf89402f488","lastUpdateTime":"2021-09-01T18:35:49.003","lastUpdateUser":null,"creationTime":"2021-09-01T18:35:49.003","creationUser":null,"report":{"objectName":"Publish report","errorMessages":[],"warningMessages":[],"children":[],"status":"PASSED"},"introduzione":"This is my MONGO project","descrizioneContenuto":"It contains this and that","authors":["Some one","Some, oneelse"],"contributore":"Contrib 1","titolari":["Some one","Some, oneelse"],"responsabile":"Someone","editore":"Editore","fontiFinanziamento":["Big pharma","Pentagon"],"soggetto":["Research Excavation","Archeology"],"risorseCorrelate":null,"dataInizioProgetto":"2021-09-01T18:35:43.733","dataFineProgetto":"2021-09-01T18:35:43.733","titolareLicenza":["Qualcun altro"],"titolareCopyright":["Chiedilo in giro"],"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"centroidLat":43.0,"centroidLong":9.0,"relazioneScavo":{"mongo_id":"612fabf68b7a9ee012cf7980","id":0,"policy":"OPEN","licenseID":"CC-BY","titolo":"Concessione : publish test relazione di scavo","creationTime":"2021-09-01T18:35:49.003","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/pdf","storageID":"60cf254f-bded-4a81-ad4e-4c5f21fdc007","link":"https://data.dev.d4science.org/shub/E_OEVWcE1VUE9SMmlJV0tqaWd2SWx5UkFNRFRqdkRKZEJFNFVGb1B4WDlBQ0Y3WGptL1J3Z1pXU3VWb0dnbEdTUw=="}],"abstractIta":"simple abstract section","abstractEng":null,"responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]},"immaginiRappresentative":[{"mongo_id":"612fac548b7a9ee012cf7995","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"My image number 0","creationTime":"2021-09-01T18:35:43.733","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"image/png","storageID":"18acfb57-6b59-4695-82c7-90d355e5153d","link":"https://data.dev.d4science.org/shub/E_aEN5a2FjaXMwWmhPRjdPUjhtR2NiOHhEb0ZLMDlvS2M3YytiQklxQ3AyWVpwOTBBTmhVK0hzZGNHUHpuV2ttRQ=="}],"didascalia":"You can see my image number 0","format":"TIFF","responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]},{"mongo_id":"612fac648b7a9ee012cf799a","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"My image number 1","creationTime":"2021-09-01T18:35:43.733","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"image/png","storageID":"ad6b709f-752b-431c-88f9-9e21d8febc56","link":"https://data.dev.d4science.org/shub/E_TkdpUXFKcWpybFFIWW5KUkl4dW5ZcklNdlE4WiszZ3d1enRweGYzaGk2UVF5WG5TcW1RQ2VORUswenFqMGpWUw=="}],"didascalia":"You can see my image number 1","format":"TIFF","responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]}],"posizionamentoScavo":{"mongo_id":"612fac198b7a9ee012cf7988","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"Concessione : publish test posizionamento scavo","creationTime":"2021-09-01T18:35:49.003","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"4a420c43-0a5f-49cc-a5da-671446fffff9","link":"https://data.dev.d4science.org/shub/E_OFNvWkFsVTNHVTFCZlZCbXFMekxqcnEwWkVYcG9QdDMyNUZIcVdBS3pSUHBMdFBnWjVlYndjMlVSZFRpd0pUWg=="},{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"07d2b7bb-fd7f-4517-aae9-fd4936e38911","link":"https://data.dev.d4science.org/shub/E_TlhEZUNKOTVIVEQ5aXl2SUg0elRuRnRsdlhpdjdUdU9jQkJhbWEreEhibjYrYldDd0REeWh1SWlYbklFajZkag=="},{"type":"GeoServerContent","id":0,"geoserverHostName":"geoserver-218.dev.d4science.org","geoserverPath":"/srv/geoserver_data/GNA/612fabe58b7a9ee012cf797b/612fac198b7a9ee012cf7988/pos","fileNames":["pos.shp","pos.shx"],"workspace":"gna_conc_612fabe58b7a9ee012cf797b","store":"pos_store","featureType":"pos"}],"layerUUID":null,"layerID":null,"layerName":"pos","wmsLink":"https://geoserver-218.dev.d4science.org/geoserver/gna_conc_612fabe58b7a9ee012cf797b/wms?service=WMS&version=1.1.0&request=GetMap&layers=gna_conc_612fabe58b7a9ee012cf797b:pos&styles=&bbox=8.620919,40.629750,8.621179,40.630258&srs=EPSG:4326&format=application/openlayers&width=400&height=400","workspace":"gna_conc_612fabe58b7a9ee012cf797b","abstractSection":"Posizionamento topografico georeferenziato dell’area interessata dalle indagini","topicCategory":"Society","subTopic":"Archeology","bbox":{"maxLat":40.630257904721645,"maxLong":8.621178639172953,"minLat":40.62975046683799,"minLong":8.62091913167495},"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"valutazioneQualita":"Secondo me si","metodoRaccoltaDati":"Fattobbene","scalaAcquisizione":"1:10000","authors":["Some one","Some, oneelse"],"responsabile":"Someone"},"pianteFineScavo":[{"mongo_id":"612fac3e8b7a9ee012cf7990","id":0,"policy":"RESTRICTED","licenseID":"CC-BY-4.0","titolo":"Concessione : publish test pianta fine scavo","creationTime":"2021-09-01T18:35:49.003","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"cd64f679-308c-44ae-90f7-fc3d0963422d","link":"https://data.dev.d4science.org/shub/E_Q2FhV3pTTnZuTnIwQzRRdUVSUmtTTGlwTVpRQ3hHanNmQnJvMHA0aHhxaHdPd1V4L0pqUnJpeXN4NGZHUS9NMA=="},{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"5a6c5577-6b83-4c90-acc2-9ae81ce0ffc6","link":"https://data.dev.d4science.org/shub/E_TXQzcXdDb3RlcGp0VlpYK3hTeHdUdGxiNWlveE5KYy9kVy90ajMrUG9nYTRmejFwREtPU0xqZC9Gbncrclcxbg=="},{"type":"GeoServerContent","id":0,"geoserverHostName":"geoserver-218.dev.d4science.org","geoserverPath":"/srv/geoserver_data/GNA/612fabe58b7a9ee012cf797b/612fac3e8b7a9ee012cf7990/pianta","fileNames":["pianta.shp","pianta.shx"],"workspace":"gna_conc_612fabe58b7a9ee012cf797b","store":"pianta_store","featureType":"pianta"}],"layerUUID":null,"layerID":null,"layerName":"pianta","wmsLink":"https://geoserver-218.dev.d4science.org/geoserver/gna_conc_612fabe58b7a9ee012cf797b/wms?service=WMS&version=1.1.0&request=GetMap&layers=gna_conc_612fabe58b7a9ee012cf797b:pianta&styles=&bbox=647502.891667,4470387.347517,647527.486073,4470417.525434&srs=EPSG:4326&format=application/openlayers&width=400&height=400","workspace":"gna_conc_612fabe58b7a9ee012cf797b","abstractSection":"Planimetria georeferenziata dell'area indagata al termine delle attività","topicCategory":"Society","subTopic":"Archeology","bbox":{"maxLat":4470417.525433567,"maxLong":647527.4860734959,"minLat":4470387.347516773,"minLong":647502.8916670183},"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"valutazioneQualita":"Secondo me si","metodoRaccoltaDati":"Fattobbene","scalaAcquisizione":"1:10000","authors":["Some one","Some, oneelse"],"responsabile":"Someone"}],"genericContent":[]},{"mongo_id":"612fac7d8b7a9ee012cf799d","id":0,"recordType":"CONCESSIONE","version":"1.0.0","licenzaID":"CC-BY","policy":"OPEN","nome":"Concessione : publish test","folderId":"2e797746-bd79-4dca-9e34-db32b2fc981f","lastUpdateTime":"2021-09-01T18:38:21.679","lastUpdateUser":null,"creationTime":"2021-09-01T18:38:21.679","creationUser":null,"report":{"objectName":"Publish report","errorMessages":[],"warningMessages":[],"children":[],"status":"PASSED"},"introduzione":"This is my MONGO project","descrizioneContenuto":"It contains this and that","authors":["Some one","Some, oneelse"],"contributore":"Contrib 1","titolari":["Some one","Some, oneelse"],"responsabile":"Someone","editore":"Editore","fontiFinanziamento":["Big pharma","Pentagon"],"soggetto":["Research Excavation","Archeology"],"risorseCorrelate":null,"dataInizioProgetto":"2021-09-01T18:38:20.695","dataFineProgetto":"2021-09-01T18:38:20.695","titolareLicenza":["Qualcun altro"],"titolareCopyright":["Chiedilo in giro"],"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"centroidLat":43.0,"centroidLong":9.0,"relazioneScavo":{"mongo_id":"612fac8e8b7a9ee012cf79a2","id":0,"policy":"OPEN","licenseID":"CC-BY","titolo":"Concessione : publish test relazione di scavo","creationTime":"2021-09-01T18:38:21.679","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/pdf","storageID":"7222cf6a-0e9e-40ec-99db-d108fe9842c5","link":"https://data.dev.d4science.org/shub/E_cnVaTWdPM2NscW9Ka1RUd0toMDRVbGRRK2hhSGhPWnIxYlk4L0tCS1FqNkZpb01vRHcwTVEyLzNZZUR0MGN4RQ=="}],"abstractIta":"simple abstract section","abstractEng":null,"responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]},"immaginiRappresentative":[{"mongo_id":"612face28b7a9ee012cf79b7","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"My image number 0","creationTime":"2021-09-01T18:38:20.695","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"image/png","storageID":"eb5a69f2-dc04-4d19-a2f5-0885a754c449","link":"https://data.dev.d4science.org/shub/E_VDlXY2Y1STBuWTc3SXREMis2OHZIMnF5NDdUYmkzWVJTT2JxS05HYi8rbnB1bUFhZFF4T0p5ZStNZGxyR2Rmdg=="}],"didascalia":"You can see my image number 0","format":"TIFF","responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]},{"mongo_id":"612facf28b7a9ee012cf79bc","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"My image number 1","creationTime":"2021-09-01T18:38:20.695","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"image/png","storageID":"d8c1da0b-4575-4457-9bc4-0a7c2c93fdf6","link":"https://data.dev.d4science.org/shub/E_cG9lTXl4a3dTRnp4azRWZG1rNHh1Q1dIYUQ4MjljaDZRUUEyVUdoN3czSWdJWUZlNTVFUzFRaXJhOEsxaTB2aw=="}],"didascalia":"You can see my image number 1","format":"TIFF","responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]}],"posizionamentoScavo":{"mongo_id":"612facae8b7a9ee012cf79aa","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"Concessione : publish test posizionamento scavo","creationTime":"2021-09-01T18:38:21.679","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"7152d15f-7e60-4095-bef8-5936981f9f67","link":"https://data.dev.d4science.org/shub/E_MzV5QllFaGdVZUpuN0ZkejVyT0F5dFc2SnpGaG85c09TaVR0RCtpS2J1SUNBZVFhS2RpZnFnakp3VkJHa2hEOQ=="},{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"043b47d3-7aa9-400d-b4dc-dc103fc78117","link":"https://data.dev.d4science.org/shub/E_QWVQNEhFUFZLbDJubVptaWVsZWRxUlc5cStLdC9UaGI4c3puQkdlWFpHTUVXcFVjR3UzSS9ieHQ1dGJrYnp5VQ=="},{"type":"GeoServerContent","id":0,"geoserverHostName":"geoserver-218.dev.d4science.org","geoserverPath":"/srv/geoserver_data/GNA/612fac7d8b7a9ee012cf799d/612facae8b7a9ee012cf79aa/pos","fileNames":["pos.shp","pos.shx"],"workspace":"gna_conc_612fac7d8b7a9ee012cf799d","store":"pos_store","featureType":"pos"}],"layerUUID":null,"layerID":null,"layerName":"pos","wmsLink":"https://geoserver-218.dev.d4science.org/geoserver/gna_conc_612fac7d8b7a9ee012cf799d/wms?service=WMS&version=1.1.0&request=GetMap&layers=gna_conc_612fac7d8b7a9ee012cf799d:pos&styles=&bbox=8.620919,40.629750,8.621179,40.630258&srs=EPSG:4326&format=application/openlayers&width=400&height=400","workspace":"gna_conc_612fac7d8b7a9ee012cf799d","abstractSection":"Posizionamento topografico georeferenziato dell’area interessata dalle indagini","topicCategory":"Society","subTopic":"Archeology","bbox":{"maxLat":40.630257904721645,"maxLong":8.621178639172953,"minLat":40.62975046683799,"minLong":8.62091913167495},"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"valutazioneQualita":"Secondo me si","metodoRaccoltaDati":"Fattobbene","scalaAcquisizione":"1:10000","authors":["Some one","Some, oneelse"],"responsabile":"Someone"},"pianteFineScavo":[{"mongo_id":"612facd38b7a9ee012cf79b2","id":0,"policy":"RESTRICTED","licenseID":"CC-BY-4.0","titolo":"Concessione : publish test pianta fine scavo","creationTime":"2021-09-01T18:38:21.679","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"2b01a062-e801-4f28-9fbc-0f6f783ecfdc","link":"https://data.dev.d4science.org/shub/E_eXRPd3ZiY0VhVWRTMkRrTnB3Y0d1WlN1Y3NRb2M4azMzMmViVUFnUkpDTFphdGZ5RmhYTXZUUXZLbXpjK2hFVg=="},{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"74e48df4-a266-4e66-a687-0659c2f6cddc","link":"https://data.dev.d4science.org/shub/E_Mml5V0tobXU1RjlRNU1rWGNJa2o5SThKeWJwSWQ5TGN2QVJEUnJ2RkNreWR2aFkrdzJrdEdYL0kwNitDSE8ySg=="},{"type":"GeoServerContent","id":0,"geoserverHostName":"geoserver-218.dev.d4science.org","geoserverPath":"/srv/geoserver_data/GNA/612fac7d8b7a9ee012cf799d/612facd38b7a9ee012cf79b2/pianta","fileNames":["pianta.shp","pianta.shx"],"workspace":"gna_conc_612fac7d8b7a9ee012cf799d","store":"pianta_store","featureType":"pianta"}],"layerUUID":null,"layerID":null,"layerName":"pianta","wmsLink":"https://geoserver-218.dev.d4science.org/geoserver/gna_conc_612fac7d8b7a9ee012cf799d/wms?service=WMS&version=1.1.0&request=GetMap&layers=gna_conc_612fac7d8b7a9ee012cf799d:pianta&styles=&bbox=647502.891667,4470387.347517,647527.486073,4470417.525434&srs=EPSG:4326&format=application/openlayers&width=400&height=400","workspace":"gna_conc_612fac7d8b7a9ee012cf799d","abstractSection":"Planimetria georeferenziata dell'area indagata al termine delle attività","topicCategory":"Society","subTopic":"Archeology","bbox":{"maxLat":4470417.525433567,"maxLong":647527.4860734959,"minLat":4470387.347516773,"minLong":647502.8916670183},"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"valutazioneQualita":"Secondo me si","metodoRaccoltaDati":"Fattobbene","scalaAcquisizione":"1:10000","authors":["Some one","Some, oneelse"],"responsabile":"Someone"}],"genericContent":[]},{"mongo_id":"6130a2808b7a9eef830a4401","id":0,"recordType":"CONCESSIONE","version":"1.0.0","licenzaID":"CC-BY","policy":"OPEN","nome":"Concessione : publish test","folderId":"36d9744b-739b-4560-9eeb-7e9ff3c64753","lastUpdateTime":"2021-09-02T12:08:00.057","lastUpdateUser":null,"creationTime":"2021-09-02T12:08:00.057","creationUser":null,"report":{"objectName":"Publish report","errorMessages":[],"warningMessages":[],"children":[],"status":"PASSED"},"introduzione":"This is my MONGO project","descrizioneContenuto":"It contains this and that","authors":["Some one","Some, oneelse"],"contributore":"Contrib 1","titolari":["Some one","Some, oneelse"],"responsabile":"Someone","editore":"Editore","fontiFinanziamento":["Big pharma","Pentagon"],"soggetto":["Research Excavation","Archeology"],"risorseCorrelate":null,"dataInizioProgetto":"2021-09-02T12:07:59.643","dataFineProgetto":"2021-09-02T12:07:59.643","titolareLicenza":["Qualcun altro"],"titolareCopyright":["Chiedilo in giro"],"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"centroidLat":43.0,"centroidLong":9.0,"relazioneScavo":{"mongo_id":"6130a2908b7a9eef830a4406","id":0,"policy":"OPEN","licenseID":"CC-BY","titolo":"Concessione : publish test relazione di scavo","creationTime":"2021-09-02T12:08:00.057","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/pdf","storageID":"da28aaa3-1ff2-4ca1-845b-d818c764cf3e","link":"https://data.dev.d4science.org/shub/E_bXdDOWJjaEExNzJlQ2wxaG9PNjRoSlU5eTBYdTUvTE1QRjRETnRBSDJXbzMyZXpXQkhqMVNyYXZiSWlCWXdwcg=="}],"abstractIta":"simple abstract section","abstractEng":null,"responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]},"immaginiRappresentative":[{"mongo_id":"6130a2e48b7a9eef830a441b","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"My image number 0","creationTime":"2021-09-02T12:07:59.644","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"image/png","storageID":"f5c859e1-0cfb-482a-ba63-b8e38d24c3eb","link":"https://data.dev.d4science.org/shub/E_UUxNU3NXS1BDUXBWblFEYW4rSzQxd3p6ci80SW5YdksvbGdoQmxwYTVDcUhZZllGcjlNeU1rMzVYd3FZcEFDcw=="}],"didascalia":"You can see my image number 0","format":"TIFF","responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]},{"mongo_id":"6130a2f98b7a9eef830a4420","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"My image number 1","creationTime":"2021-09-02T12:07:59.644","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"image/png","storageID":"0ee98859-7a38-4f39-8955-20fe1f2665a1","link":"https://data.dev.d4science.org/shub/E_aXdBNUlSemY2dzFWL2NyVWp6OTBZMTRlRVVNNE5vSUpIckhIVXlESGJySUVPR2owUjV0TlI0S241VGZab0RVeQ=="}],"didascalia":"You can see my image number 1","format":"TIFF","responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]}],"posizionamentoScavo":{"mongo_id":"6130a2b18b7a9eef830a440e","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"Concessione : publish test posizionamento scavo","creationTime":"2021-09-02T12:08:00.057","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"b4a99b19-ec8f-4660-8c32-e58b2789f323","link":"https://data.dev.d4science.org/shub/E_R05ENnJ2Vnd1SnJ3WDBiRHBqOVZQQUNqbGNxb2lHMzF2ZXN5b0U0UFBNQUVIMFJmRlgzdTVtQlVjZ1R0Q0o1MA=="},{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"240d2794-2005-463d-92e7-ac98d14de136","link":"https://data.dev.d4science.org/shub/E_RnBNRDNaT1NnRmRIY25QUlN4b3VhaVBOdTY3c3UvNkFIejhnT0R1ZE9ZRWJxUTRxcGg5Q2huN3c3azUxV2NwaQ=="},{"type":"GeoServerContent","id":0,"geoserverHostName":"geoserver-218.dev.d4science.org","geoserverPath":"/srv/geoserver_data/GNA/6130a2808b7a9eef830a4401/6130a2b18b7a9eef830a440e/pos","fileNames":["pos.shp","pos.shx"],"workspace":"gna_conc_6130a2808b7a9eef830a4401","store":"pos_store","featureType":"pos"}],"layerUUID":null,"layerID":null,"layerName":"pos","wmsLink":"https://geoserver-218.dev.d4science.org/geoserver/gna_conc_6130a2808b7a9eef830a4401/wms?service=WMS&version=1.1.0&request=GetMap&layers=gna_conc_6130a2808b7a9eef830a4401:pos&styles=&bbox=8.620919,40.629750,8.621179,40.630258&srs=EPSG:4326&format=application/openlayers&width=400&height=400","workspace":"gna_conc_6130a2808b7a9eef830a4401","abstractSection":"Posizionamento topografico georeferenziato dell’area interessata dalle indagini","topicCategory":"Society","subTopic":"Archeology","bbox":{"maxLat":40.630257904721645,"maxLong":8.621178639172953,"minLat":40.62975046683799,"minLong":8.62091913167495},"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"valutazioneQualita":"Secondo me si","metodoRaccoltaDati":"Fattobbene","scalaAcquisizione":"1:10000","authors":["Some one","Some, oneelse"],"responsabile":"Someone"},"pianteFineScavo":[{"mongo_id":"6130a2d48b7a9eef830a4416","id":0,"policy":"RESTRICTED","licenseID":"CC-BY-4.0","titolo":"Concessione : publish test pianta fine scavo","creationTime":"2021-09-02T12:08:00.057","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"715e3380-4d13-453c-adef-66ba17e019be","link":"https://data.dev.d4science.org/shub/E_ZjQ0N2UvZmFHMFQ2VzkxMjUrcDNBNEdtVDRVdG9abnhFR0YrYmR0WWlBbzkrM2V2QWs5MnR0QjNDSFRnUUFQNg=="},{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"88532c9e-7e24-4424-b8f7-ca0f79e7683d","link":"https://data.dev.d4science.org/shub/E_dGUxWmw3d1dNaURxSnRaYzZqWkJMS255ZkdYb1FnbjVXc0srT1pyUkRWOWdob1c5MlJzTjMrMFI3aDBmaDVjNA=="},{"type":"GeoServerContent","id":0,"geoserverHostName":"geoserver-218.dev.d4science.org","geoserverPath":"/srv/geoserver_data/GNA/6130a2808b7a9eef830a4401/6130a2d48b7a9eef830a4416/pianta","fileNames":["pianta.shp","pianta.shx"],"workspace":"gna_conc_6130a2808b7a9eef830a4401","store":"pianta_store","featureType":"pianta"}],"layerUUID":null,"layerID":null,"layerName":"pianta","wmsLink":"https://geoserver-218.dev.d4science.org/geoserver/gna_conc_6130a2808b7a9eef830a4401/wms?service=WMS&version=1.1.0&request=GetMap&layers=gna_conc_6130a2808b7a9eef830a4401:pianta&styles=&bbox=647502.891667,4470387.347517,647527.486073,4470417.525434&srs=EPSG:4326&format=application/openlayers&width=400&height=400","workspace":"gna_conc_6130a2808b7a9eef830a4401","abstractSection":"Planimetria georeferenziata dell'area indagata al termine delle attività","topicCategory":"Society","subTopic":"Archeology","bbox":{"maxLat":4470417.525433567,"maxLong":647527.4860734959,"minLat":4470387.347516773,"minLong":647502.8916670183},"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"valutazioneQualita":"Secondo me si","metodoRaccoltaDati":"Fattobbene","scalaAcquisizione":"1:10000","authors":["Some one","Some, oneelse"],"responsabile":"Someone"}],"genericContent":[]},{"mongo_id":"6130a3198b7a9eef830a4423","id":0,"recordType":"CONCESSIONE","version":"1.0.0","licenzaID":"CC-BY","policy":"OPEN","nome":"Concessione : publish test","folderId":"19286a89-b678-40fd-98f0-93f266a543cb","lastUpdateTime":"2021-09-02T12:10:33.629","lastUpdateUser":null,"creationTime":"2021-09-02T12:10:33.629","creationUser":null,"report":{"objectName":"Publish report","errorMessages":[],"warningMessages":[],"children":[],"status":"PASSED"},"introduzione":"This is my MONGO project","descrizioneContenuto":"It contains this and that","authors":["Some one","Some, oneelse"],"contributore":"Contrib 1","titolari":["Some one","Some, oneelse"],"responsabile":"Someone","editore":"Editore","fontiFinanziamento":["Big pharma","Pentagon"],"soggetto":["Research Excavation","Archeology"],"risorseCorrelate":null,"dataInizioProgetto":"2021-09-02T12:10:28.119","dataFineProgetto":"2021-09-02T12:10:28.119","titolareLicenza":["Qualcun altro"],"titolareCopyright":["Chiedilo in giro"],"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"centroidLat":43.0,"centroidLong":9.0,"relazioneScavo":{"mongo_id":"6130a32f8b7a9eef830a4428","id":0,"policy":"OPEN","licenseID":"CC-BY","titolo":"Concessione : publish test relazione di scavo","creationTime":"2021-09-02T12:10:33.629","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/pdf","storageID":"0af0d4af-1134-4b3c-bf18-bdf4d37b0366","link":"https://data.dev.d4science.org/shub/E_UWVHenRLelp2SWJtRFFoSU1PaHZPRHFZaExMM0kyQWtJYXZWaXR5NDIxdHIyWWFNb3dOaG04R0cwaGFJL3lOVA=="}],"abstractIta":"simple abstract section","abstractEng":null,"responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]},"immaginiRappresentative":[{"mongo_id":"6130a37f8b7a9eef830a443d","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"My image number 0","creationTime":"2021-09-02T12:10:28.119","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"image/png","storageID":"7c544d13-e226-4202-9c06-a850755ca625","link":"https://data.dev.d4science.org/shub/E_VXBBWU9RN2Vpc0NHVGxaenhrRVQzcFRkYnlScFFKY1RiekhQRTVraE92dHU1RVpTTlc4bHFxREVvaGppS1RHeg=="}],"didascalia":"You can see my image number 0","format":"TIFF","responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]},{"mongo_id":"6130a3948b7a9eef830a4442","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"My image number 1","creationTime":"2021-09-02T12:10:28.119","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"image/png","storageID":"8c4b30af-7dcd-4cfd-85d2-8560316715d9","link":"https://data.dev.d4science.org/shub/E_YkFIdERidys5aDBRbkJmMGpmWVdCM0FVdEo2WGNXS010aTE3bklodGFMTmJucDhwckU3L0g3Um5VTEh5NS9qQg=="}],"didascalia":"You can see my image number 1","format":"TIFF","responsabili":["Some one","Some, oneelse"],"soggetto":["Research Excavation","Archeology"]}],"posizionamentoScavo":{"mongo_id":"6130a34c8b7a9eef830a4430","id":0,"policy":"OPEN","licenseID":"CC-BY-4.0","titolo":"Concessione : publish test posizionamento scavo","creationTime":"2021-09-02T12:10:33.629","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"a1da6f0e-3670-43bf-84d9-1a61dac8f912","link":"https://data.dev.d4science.org/shub/E_Skw5MXJTVkZnS2ZRNWdQUWxQR2VLWVNqNUg0L3QzeitFdWdlOFdtazlkZ1ZOR0ZqcW5WYmJtSkpsN2Z3M2x1dw=="},{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"64c4733d-3a94-48b6-aa04-5115573b9d9e","link":"https://data.dev.d4science.org/shub/E_ZTdzTG4zRUlpbFRMSFlIR1lNdUExcVVzaWQ4VmkzbkxoempINnk3MzZtcE9lZlhKVGErcC9PMDVGWU1vK003cg=="},{"type":"GeoServerContent","id":0,"geoserverHostName":"geoserver-218.dev.d4science.org","geoserverPath":"/srv/geoserver_data/GNA/6130a3198b7a9eef830a4423/6130a34c8b7a9eef830a4430/pos","fileNames":["pos.shp","pos.shx"],"workspace":"gna_conc_6130a3198b7a9eef830a4423","store":"pos_store","featureType":"pos"}],"layerUUID":null,"layerID":null,"layerName":"pos","wmsLink":"https://geoserver-218.dev.d4science.org/geoserver/gna_conc_6130a3198b7a9eef830a4423/wms?service=WMS&version=1.1.0&request=GetMap&layers=gna_conc_6130a3198b7a9eef830a4423:pos&styles=&bbox=8.620919,40.629750,8.621179,40.630258&srs=EPSG:4326&format=application/openlayers&width=400&height=400","workspace":"gna_conc_6130a3198b7a9eef830a4423","abstractSection":"Posizionamento topografico georeferenziato dell’area interessata dalle indagini","topicCategory":"Society","subTopic":"Archeology","bbox":{"maxLat":40.630257904721645,"maxLong":8.621178639172953,"minLat":40.62975046683799,"minLong":8.62091913167495},"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"valutazioneQualita":"Secondo me si","metodoRaccoltaDati":"Fattobbene","scalaAcquisizione":"1:10000","authors":["Some one","Some, oneelse"],"responsabile":"Someone"},"pianteFineScavo":[{"mongo_id":"6130a3708b7a9eef830a4438","id":0,"policy":"RESTRICTED","licenseID":"CC-BY-4.0","titolo":"Concessione : publish test pianta fine scavo","creationTime":"2021-09-02T12:10:33.629","actualContent":[{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"27830c55-d762-4cfc-911b-99b254fba366","link":"https://data.dev.d4science.org/shub/E_U2ZqSExFRno4aEhXdC93cEo2elU2ZjRWVWU2TGRsb3RYMS8rYUNyMDVnUU1ZOSt6UUJxRTF0K0pKeGNjZ3RwZA=="},{"type":"WorkspaceContent","id":0,"mimetype":"application/x-shapefile","storageID":"689cd4a9-535d-4d8a-b473-175f7f772d0e","link":"https://data.dev.d4science.org/shub/E_Y2JTbjFHT3pmZzhzSW9Fa2NCN0RmeVBpU04xY2tWdzA1eUdyQVVNN2l6c1M5M3dManBzY3NVZWRsQ0w5b3VBeA=="},{"type":"GeoServerContent","id":0,"geoserverHostName":"geoserver-218.dev.d4science.org","geoserverPath":"/srv/geoserver_data/GNA/6130a3198b7a9eef830a4423/6130a3708b7a9eef830a4438/pianta","fileNames":["pianta.shp","pianta.shx"],"workspace":"gna_conc_6130a3198b7a9eef830a4423","store":"pianta_store","featureType":"pianta"}],"layerUUID":null,"layerID":null,"layerName":"pianta","wmsLink":"https://geoserver-218.dev.d4science.org/geoserver/gna_conc_6130a3198b7a9eef830a4423/wms?service=WMS&version=1.1.0&request=GetMap&layers=gna_conc_6130a3198b7a9eef830a4423:pianta&styles=&bbox=647502.891667,4470387.347517,647527.486073,4470417.525434&srs=EPSG:4326&format=application/openlayers&width=400&height=400","workspace":"gna_conc_6130a3198b7a9eef830a4423","abstractSection":"Planimetria georeferenziata dell'area indagata al termine delle attività","topicCategory":"Society","subTopic":"Archeology","bbox":{"maxLat":4470417.525433567,"maxLong":647527.4860734959,"minLat":4470387.347516773,"minLong":647502.8916670183},"paroleChiaveLibere":["Robba","Stuff"],"paroleChiaveICCD":["vattelapesca","somthing something"],"valutazioneQualita":"Secondo me si","metodoRaccoltaDati":"Fattobbene","scalaAcquisizione":"1:10000","authors":["Some one","Some, oneelse"],"responsabile":"Someone"}],"genericContent":[]}]
diff --git a/geoportal-client/src/test/resources/concessioni/DATASET_GNA_01.csv b/geoportal-client/src/test/resources/concessioni/DATASET_GNA_01.csv
new file mode 100644
index 0000000..6ab4b49
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/DATASET_GNA_01.csv
@@ -0,0 +1,6 @@
+"GNA_Aquileia Casa Bestie Ferite_2019_rev_CdL","GNA_Aquileia Casa Bestie Ferite_2019_rev_CdL/GNA_topografia_Aquileia Casa Bestie Ferite","GNA_Aquileia Casa Bestie Ferite_2019_rev_CdL/GNA_topografia_Aquileia Casa Bestie Ferite"
+"GNA_Castelseprio castrum-borgo_2019_rev_CdL","GNA_Castelseprio castrum-borgo_2019_rev_CdL/GNA_topografia_Castelseprio castrum-borgo","GNA_Castelseprio castrum-borgo_2019_rev_CdL/GNA_topografia_Castelseprio castrum-borgo"
+"GNA_Monte Postale_2019_rev_CdL_FPDC","GNA_Monte Postale_2019_rev_CdL_FPDC/GNA_topografia_Monte Postale","GNA_Monte Postale_2019_rev_CdL_FPDC/GNA_topografia_Monte Postale"
+"GNA_Castelseprio castrum-borgo_2019_rev_CdL","GNA_Castelseprio castrum-borgo_2019_rev_CdL/GNA_topografia_Castelseprio castrum-borgo","GNA_Castelseprio castrum-borgo_2019_rev_CdL/GNA_topografia_Castelseprio castrum-borgo"
+"GNA_Aquileia Casa Bestie Ferite_2019_rev_CdL","GNA_Aquileia Casa Bestie Ferite_2019_rev_CdL/GNA_topografia_Aquileia Casa Bestie Ferite","GNA_Aquileia Casa Bestie Ferite_2019_rev_CdL/GNA_topografia_Aquileia Casa Bestie Ferite"
+"GNA_Appia Antica V miglio_2019_rev_CdL","GNA_Appia Antica V miglio_2019_rev_CdL/GNA_topografia_Appia Antica V miglio","GNA_Appia Antica V miglio_2019_rev_CdL/GNA_topografia_Appia Antica V miglio"
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/DATASET_GNA_02.csv b/geoportal-client/src/test/resources/concessioni/DATASET_GNA_02.csv
new file mode 100644
index 0000000..33fec22
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/DATASET_GNA_02.csv
@@ -0,0 +1,5 @@
+"GNA_Bostel di Rotzo_Rev_FPDC","GNA_Bostel di Rotzo_Rev_FPDC/GNA_topografia_Bostel di Rotzo","GNA_Bostel di Rotzo_Rev_FPDC/GNA_topografia_Bostel di Rotzo"
+"GNA_Braida Murada_Rev_FPDC","GNA_Braida Murada_Rev_FPDC/GNA_topografia_Braida Murada","GNA_Braida Murada_Rev_FPDC/GNA_topografia_Braida Murada"
+"GNA_Egnazia_Rev_FPDC","GNA_Bostel di Rotzo_Rev_FPDC/GNA_topografia_Bostel di Rotzo","GNA_Bostel di Rotzo_Rev_FPDC/GNA_topografia_Bostel di Rotzo"
+"GNA_Ferrandina_Rev_FPDC","GNA_Ferrandina_Rev_FPDC/GNA_topografia_Ferrandina","GNA_Ferrandina_Rev_FPDC/GNA_topografia_Ferrandina"
+"GNA_Timpone della Motta_Rev_FPDC","GNA_Timpone della Motta_Rev_FPDC/GNA_topografia_Timpone della Motta","GNA_Timpone della Motta_Rev_FPDC/GNA_topografia_Timpone della Motta"
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/concessioni04-03.csv b/geoportal-client/src/test/resources/concessioni/concessioni04-03.csv
new file mode 100644
index 0000000..0b58aa6
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/concessioni04-03.csv
@@ -0,0 +1,18 @@
+"Acquacadda_Nuxis_2019_def","Acquacadda_Nuxis_2019_def/D_posizionamento saggi_NUXIS 2019","Acquacadda_Nuxis_2019_def/E_piante fine scavo vettoriali_NUXIS 2019"
+"Ariano nel Polisine (Ro) - Loc. San Basilio ( Unvi. di Padova)","Ariano nel Polisine (Ro) - Loc. San Basilio ( Unvi. di Padova)/GNA_SAN BASILIO_2019/GNA_topografia_San Basilio/POSIZIONAMENTO SAGGI E AREE DELLE INDAGINI","Ariano nel Polisine (Ro) - Loc. San Basilio ( Unvi. di Padova)/GNA_SAN BASILIO_2019/GNA_topografia_San Basilio/PLANIMETRIE SAGGI AREE DELLE INDAGINI"
+"Ariano Polesine (Ro) - Loc. San Basilio (Uni. di Venezia)","Ariano Polesine (Ro) - Loc. San Basilio (Uni. di Venezia)/S.Basilio-UniVe_GNA/D.GNA_Posizionamento_San Basilio","Ariano Polesine (Ro) - Loc. San Basilio (Uni. di Venezia)/S.Basilio-UniVe_GNA/E-F.GNA_Pianta fine scavo_San Basilio/GNA_Pianta di fine scavo_San Basilio"
+"C_F_GNA_Oscurusciuto_2020","C_F_GNA_Oscurusciuto_2020/D-E-F_GNA_topografia_Oscurusciuto/Posizionamento_limiti_saggi_indagati_Oscurusciuto_vettoriale","C_F_GNA_Oscurusciuto_2020/D-E-F_GNA_topografia_Oscurusciuto/Pianta_fine_scavo_Oscurusciuto_2019_vettoriale"
+"Cerchiara-Damale_rev","Cerchiara-Damale_rev/D. Posizionamento saggio","Cerchiara-Damale_rev/D. Posizionamento saggio/E. Pianta fine scavo_vettoriale"
+"Cerveteri (RM)_loc. Monte Abatone_documentazione fine scavo 2019 (paragr. IVa)","Cerveteri (RM)_loc. Monte Abatone_documentazione fine scavo 2019 (paragr. IVa)/IVa_E_Tav.1_Shape Posizionamento area scavo","Cerveteri (RM)_loc. Monte Abatone_documentazione fine scavo 2019 (paragr. IVa)/IVa_E_Tav.1_Shape Posizionamento area scavo"
+"Cervia Vecchia_rev","Cervia Vecchia_rev/D_GNA_topografia_Cervia","Cervia Vecchia_rev/D_GNA_topografia_Cervia"
+"Civitavecchia (RM)_loc. Ficoncella_Aquae Tauri_docum. IVa_2019","Civitavecchia (RM)_loc. Ficoncella_Aquae Tauri_docum. IVa_2019/Civitavecchia (RM)_Ficoncella_documentazione fine scavo 2019_IVa/IVa_D_E_F_topografia_Aquae_Tauri/Posizionamento saggi 2019","Civitavecchia (RM)_loc. Ficoncella_Aquae Tauri_docum. IVa_2019/Civitavecchia (RM)_Ficoncella_documentazione fine scavo 2019_IVa/IVa_D_E_F_topografia_Aquae_Tauri/Pianta di fine scavo 2019"
+"Frascineto Timpone delle Fave_rev","Frascineto Timpone delle Fave_rev/D. Posizionamento dell'area","Frascineto Timpone delle Fave_rev/D. Posizionamento dell'area"
+"GNA_AQUILEIAcomellimoro_2019_rev","GNA_AQUILEIAcomellimoro_2019_rev/GNA_topografia_AQUILEIAcomellimoro_2019/D.Posizionamento_AQU19COM","GNA_AQUILEIAcomellimoro_2019_rev/GNA_topografia_AQUILEIAcomellimoro_2019/E.Planimetria generale_AQU19COM"
+"GNA_Poggio Pimperiale_Poggibonsi","GNA_Poggio Pimperiale_Poggibonsi/5591449/GNA_topografia_PoggioImperiale/POSIZIONAMENTO","GNA_Poggio Pimperiale_Poggibonsi/5591449/GNA_topografia_PoggioImperiale/PLANIMETRIE SAGGI/SHAPE A22"
+"Jesolo (Ve) - Loc. San Mauro e Torre del Caligo","Jesolo (Ve) - Loc. San Mauro e Torre del Caligo/GNA_topografia_Jesolo/GIS_shp","Jesolo (Ve) - Loc. San Mauro e Torre del Caligo/GNA_topografia_Jesolo/GIS_shp"
+"Monterotondo (RM)_loc. Tor Mancina_documentazione fine scavo 2019 (paragr. IVa)","Monterotondo (RM)_loc. Tor Mancina_documentazione fine scavo 2019 (paragr. IVa)/IVa_D_E_F_GNA_topografia_Via Nomentum-Eretum","Monterotondo (RM)_loc. Tor Mancina_documentazione fine scavo 2019 (paragr. IVa)/IVa_D_E_F_GNA_topografia_Via Nomentum-Eretum"
+"Quarto d'Altino -Loc. Fornace","Quarto d'Altino -Loc. Fornace/Cupitò/GNA_Altino_posizionamento_shp","Quarto d'Altino -Loc. Fornace/Cupitò/GNA_Altino_posizionamento_shp"
+"Tolfa (RM)_Bufalareccia_documentazione IVa 2019","Tolfa (RM)_Bufalareccia_documentazione IVa 2019/IVa_D_GNA_posizionamento dei limiti in formato vectoriale_Bufalareccia 2019","Tolfa (RM)_Bufalareccia_documentazione IVa 2019/IVa_E_GNA_pianta di fine scavo multipolygon_Bufalareccia 2019"
+"UNIME_ LAINO_REV","UNIME_ LAINO_REV/D. Limiti saggi/laino 2019 limiti saggi","UNIME_ LAINO_REV/D. Limiti saggi/laino 2019 limiti saggi"
+"UNIME_TORTORA_rev","UNIME_TORTORA_rev/tortora 2019 limiti saggi","UNIME_TORTORA_rev/tortora 2019 pianta fine scavo"
+"UsiniTomestighes","UsiniTomestighes/GNA_TOMESTIGHES_2019/GNA_Topografia_Tomestighes/D_GNA_Posizionamento_limiti_aree_indagate","UsiniTomestighes/GNA_TOMESTIGHES_2019/GNA_Topografia_Tomestighes/E_GNA_Piante_fine_scavo_Tomestighes/Area A_est"
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/concessioni04-03_filtered.csv b/geoportal-client/src/test/resources/concessioni/concessioni04-03_filtered.csv
new file mode 100644
index 0000000..0b58aa6
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/concessioni04-03_filtered.csv
@@ -0,0 +1,18 @@
+"Acquacadda_Nuxis_2019_def","Acquacadda_Nuxis_2019_def/D_posizionamento saggi_NUXIS 2019","Acquacadda_Nuxis_2019_def/E_piante fine scavo vettoriali_NUXIS 2019"
+"Ariano nel Polisine (Ro) - Loc. San Basilio ( Unvi. di Padova)","Ariano nel Polisine (Ro) - Loc. San Basilio ( Unvi. di Padova)/GNA_SAN BASILIO_2019/GNA_topografia_San Basilio/POSIZIONAMENTO SAGGI E AREE DELLE INDAGINI","Ariano nel Polisine (Ro) - Loc. San Basilio ( Unvi. di Padova)/GNA_SAN BASILIO_2019/GNA_topografia_San Basilio/PLANIMETRIE SAGGI AREE DELLE INDAGINI"
+"Ariano Polesine (Ro) - Loc. San Basilio (Uni. di Venezia)","Ariano Polesine (Ro) - Loc. San Basilio (Uni. di Venezia)/S.Basilio-UniVe_GNA/D.GNA_Posizionamento_San Basilio","Ariano Polesine (Ro) - Loc. San Basilio (Uni. di Venezia)/S.Basilio-UniVe_GNA/E-F.GNA_Pianta fine scavo_San Basilio/GNA_Pianta di fine scavo_San Basilio"
+"C_F_GNA_Oscurusciuto_2020","C_F_GNA_Oscurusciuto_2020/D-E-F_GNA_topografia_Oscurusciuto/Posizionamento_limiti_saggi_indagati_Oscurusciuto_vettoriale","C_F_GNA_Oscurusciuto_2020/D-E-F_GNA_topografia_Oscurusciuto/Pianta_fine_scavo_Oscurusciuto_2019_vettoriale"
+"Cerchiara-Damale_rev","Cerchiara-Damale_rev/D. Posizionamento saggio","Cerchiara-Damale_rev/D. Posizionamento saggio/E. Pianta fine scavo_vettoriale"
+"Cerveteri (RM)_loc. Monte Abatone_documentazione fine scavo 2019 (paragr. IVa)","Cerveteri (RM)_loc. Monte Abatone_documentazione fine scavo 2019 (paragr. IVa)/IVa_E_Tav.1_Shape Posizionamento area scavo","Cerveteri (RM)_loc. Monte Abatone_documentazione fine scavo 2019 (paragr. IVa)/IVa_E_Tav.1_Shape Posizionamento area scavo"
+"Cervia Vecchia_rev","Cervia Vecchia_rev/D_GNA_topografia_Cervia","Cervia Vecchia_rev/D_GNA_topografia_Cervia"
+"Civitavecchia (RM)_loc. Ficoncella_Aquae Tauri_docum. IVa_2019","Civitavecchia (RM)_loc. Ficoncella_Aquae Tauri_docum. IVa_2019/Civitavecchia (RM)_Ficoncella_documentazione fine scavo 2019_IVa/IVa_D_E_F_topografia_Aquae_Tauri/Posizionamento saggi 2019","Civitavecchia (RM)_loc. Ficoncella_Aquae Tauri_docum. IVa_2019/Civitavecchia (RM)_Ficoncella_documentazione fine scavo 2019_IVa/IVa_D_E_F_topografia_Aquae_Tauri/Pianta di fine scavo 2019"
+"Frascineto Timpone delle Fave_rev","Frascineto Timpone delle Fave_rev/D. Posizionamento dell'area","Frascineto Timpone delle Fave_rev/D. Posizionamento dell'area"
+"GNA_AQUILEIAcomellimoro_2019_rev","GNA_AQUILEIAcomellimoro_2019_rev/GNA_topografia_AQUILEIAcomellimoro_2019/D.Posizionamento_AQU19COM","GNA_AQUILEIAcomellimoro_2019_rev/GNA_topografia_AQUILEIAcomellimoro_2019/E.Planimetria generale_AQU19COM"
+"GNA_Poggio Pimperiale_Poggibonsi","GNA_Poggio Pimperiale_Poggibonsi/5591449/GNA_topografia_PoggioImperiale/POSIZIONAMENTO","GNA_Poggio Pimperiale_Poggibonsi/5591449/GNA_topografia_PoggioImperiale/PLANIMETRIE SAGGI/SHAPE A22"
+"Jesolo (Ve) - Loc. San Mauro e Torre del Caligo","Jesolo (Ve) - Loc. San Mauro e Torre del Caligo/GNA_topografia_Jesolo/GIS_shp","Jesolo (Ve) - Loc. San Mauro e Torre del Caligo/GNA_topografia_Jesolo/GIS_shp"
+"Monterotondo (RM)_loc. Tor Mancina_documentazione fine scavo 2019 (paragr. IVa)","Monterotondo (RM)_loc. Tor Mancina_documentazione fine scavo 2019 (paragr. IVa)/IVa_D_E_F_GNA_topografia_Via Nomentum-Eretum","Monterotondo (RM)_loc. Tor Mancina_documentazione fine scavo 2019 (paragr. IVa)/IVa_D_E_F_GNA_topografia_Via Nomentum-Eretum"
+"Quarto d'Altino -Loc. Fornace","Quarto d'Altino -Loc. Fornace/Cupitò/GNA_Altino_posizionamento_shp","Quarto d'Altino -Loc. Fornace/Cupitò/GNA_Altino_posizionamento_shp"
+"Tolfa (RM)_Bufalareccia_documentazione IVa 2019","Tolfa (RM)_Bufalareccia_documentazione IVa 2019/IVa_D_GNA_posizionamento dei limiti in formato vectoriale_Bufalareccia 2019","Tolfa (RM)_Bufalareccia_documentazione IVa 2019/IVa_E_GNA_pianta di fine scavo multipolygon_Bufalareccia 2019"
+"UNIME_ LAINO_REV","UNIME_ LAINO_REV/D. Limiti saggi/laino 2019 limiti saggi","UNIME_ LAINO_REV/D. Limiti saggi/laino 2019 limiti saggi"
+"UNIME_TORTORA_rev","UNIME_TORTORA_rev/tortora 2019 limiti saggi","UNIME_TORTORA_rev/tortora 2019 pianta fine scavo"
+"UsiniTomestighes","UsiniTomestighes/GNA_TOMESTIGHES_2019/GNA_Topografia_Tomestighes/D_GNA_Posizionamento_limiti_aree_indagate","UsiniTomestighes/GNA_TOMESTIGHES_2019/GNA_Topografia_Tomestighes/E_GNA_Piante_fine_scavo_Tomestighes/Area A_est"
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/concessioni_23_04.csv b/geoportal-client/src/test/resources/concessioni/concessioni_23_04.csv
new file mode 100644
index 0000000..00af136
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/concessioni_23_04.csv
@@ -0,0 +1,4 @@
+"GNA_Incoronata_2019_Rennes","/GNA_Incoronata_2019_Rennes/GNA_topografia_Incoronata/D","/GNA_Incoronata_2019_Rennes/GNA_topografia_Incoronata/E/SHP"
+"MONTE MANNU_2019","/MONTE MANNU_2019/GNA_topografia_Monte_Mannu/D_Limiti dei saggi","/MONTE MANNU_2019/GNA_topografia_Monte_Mannu/E_Pianta di fine scavo"
+"Santa Rosa Poviglio_2019","/Santa Rosa Poviglio_2019/GNA_Topografia_Poviglio/Posizionamento","/Santa Rosa Poviglio_2019/GNA_Topografia_Poviglio/Planimetrie"
+"Usini Tomestighes_integrata","/Usini Tomestighes_integrata/GNA_TOMESTIGHES_2019/GNA_Topografia_Tomestighes/GNA_Tomestighes_2019/D_GNA_Posizionamento_limiti_aree_indagate","/Usini Tomestighes_integrata/GNA_TOMESTIGHES_2019/GNA_Topografia_Tomestighes/GNA_Tomestighes_2019/E_GNA_Piante_fine_scavo_Tomestighes/Area A est"
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/filters/all.json b/geoportal-client/src/test/resources/concessioni/filters/all.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/filters/all.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/filters/legacyid.json b/geoportal-client/src/test/resources/concessioni/filters/legacyid.json
new file mode 100644
index 0000000..610e687
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/filters/legacyid.json
@@ -0,0 +1,3 @@
+{
+ "id" : {$gt : 0}
+}
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/filters/missingCentroid.json b/geoportal-client/src/test/resources/concessioni/filters/missingCentroid.json
new file mode 100644
index 0000000..ab28660
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/filters/missingCentroid.json
@@ -0,0 +1,4 @@
+{
+ "centroidLat" : 0
+
+}
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/filters/nonFabio.json b/geoportal-client/src/test/resources/concessioni/filters/nonFabio.json
new file mode 100644
index 0000000..b40d2fe
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/filters/nonFabio.json
@@ -0,0 +1,3 @@
+{
+ "creationUser" : {$ne : "fabio.sinibaldi"}
+}
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/filters/validated.json b/geoportal-client/src/test/resources/concessioni/filters/validated.json
new file mode 100644
index 0000000..f05a79f
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/filters/validated.json
@@ -0,0 +1,3 @@
+{
+ "report.status": {$eq : "PASSED"}
+}
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/immagine.png b/geoportal-client/src/test/resources/concessioni/immagine.png
new file mode 100644
index 0000000..e777369
Binary files /dev/null and b/geoportal-client/src/test/resources/concessioni/immagine.png differ
diff --git a/geoportal-client/src/test/resources/concessioni/immagine2.png b/geoportal-client/src/test/resources/concessioni/immagine2.png
new file mode 100644
index 0000000..e777369
Binary files /dev/null and b/geoportal-client/src/test/resources/concessioni/immagine2.png differ
diff --git a/geoportal-client/src/test/resources/concessioni/invio_08_05.csv b/geoportal-client/src/test/resources/concessioni/invio_08_05.csv
new file mode 100644
index 0000000..8dc9e6a
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/invio_08_05.csv
@@ -0,0 +1,7 @@
+"Farnese (VT)_Sorgenti della Nova_documentazione fine scavo 2019","Farnese (VT)_Sorgenti della Nova_documentazione fine scavo 2019/Gis Sorgenti della Nova","Farnese (VT)_Sorgenti della Nova_documentazione fine scavo 2019/Gis Sorgenti della Nova/Piante di fase"
+"GNA_Aquileia_ExPasqualis_ok","GNA_Aquileia_ExPasqualis_ok/GNA_topografia_Aquileia ex Pasqualis_2019","GNA_Aquileia_ExPasqualis_ok/GNA_topografia_Aquileia ex Pasqualis_2019"
+"Jesolo (Ve) - Loc. San Mauro e Torre del Caligo","Jesolo (Ve) - Loc. San Mauro e Torre del Caligo/topografia_modificata","Jesolo (Ve) - Loc. San Mauro e Torre del Caligo/topografia_modificata"
+"Montalto di Castro (VT)_Vulci_Indagini non invasive_Doc. paragr._Va","Montalto di Castro (VT)_Vulci_Indagini non invasive_Doc. paragr._Va/CONSEGNA_WGS84","Montalto di Castro (VT)_Vulci_Indagini non invasive_Doc. paragr._Va/CONSEGNA_WGS84"
+"Montecompatri_Tenuta_Castiglione_doc_IVa_2019","Montecompatri_Tenuta_Castiglione_doc_IVa_2019/GNA_topografia_Gabii_Louvre/POSIZIONAMENTO","Montecompatri_Tenuta_Castiglione_doc_IVa_2019/GNA_topografia_Gabii_Louvre/PIANTA FINE SCAVO"
+"SAN_CASCIANO_BAGNI","SAN_CASCIANO_BAGNI/POSIZIONAMENTO_EPSG_4326","SAN_CASCIANO_BAGNI"
+"Tarquinia_Civita_GNA_2019","Tarquinia_Civita_GNA_2019/Va_D__Topografia_Tarquinia/Posizionamento","Tarquinia_Civita_GNA_2019/Va_D__Topografia_Tarquinia/Posizionamento"
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/pianta.shp b/geoportal-client/src/test/resources/concessioni/pianta.shp
new file mode 100644
index 0000000..24ed2bd
Binary files /dev/null and b/geoportal-client/src/test/resources/concessioni/pianta.shp differ
diff --git a/geoportal-client/src/test/resources/concessioni/pianta.shx b/geoportal-client/src/test/resources/concessioni/pianta.shx
new file mode 100644
index 0000000..b6a49a0
Binary files /dev/null and b/geoportal-client/src/test/resources/concessioni/pianta.shx differ
diff --git a/geoportal-client/src/test/resources/concessioni/pos.dbf b/geoportal-client/src/test/resources/concessioni/pos.dbf
new file mode 100644
index 0000000..eff02b7
Binary files /dev/null and b/geoportal-client/src/test/resources/concessioni/pos.dbf differ
diff --git a/geoportal-client/src/test/resources/concessioni/pos.prj b/geoportal-client/src/test/resources/concessioni/pos.prj
new file mode 100644
index 0000000..a30c00a
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/pos.prj
@@ -0,0 +1 @@
+GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/pos.qpj b/geoportal-client/src/test/resources/concessioni/pos.qpj
new file mode 100644
index 0000000..5fbc831
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/pos.qpj
@@ -0,0 +1 @@
+GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]
diff --git a/geoportal-client/src/test/resources/concessioni/pos.shp b/geoportal-client/src/test/resources/concessioni/pos.shp
new file mode 100644
index 0000000..ba95a92
Binary files /dev/null and b/geoportal-client/src/test/resources/concessioni/pos.shp differ
diff --git a/geoportal-client/src/test/resources/concessioni/pos.shx b/geoportal-client/src/test/resources/concessioni/pos.shx
new file mode 100644
index 0000000..21821b5
Binary files /dev/null and b/geoportal-client/src/test/resources/concessioni/pos.shx differ
diff --git a/geoportal-client/src/test/resources/concessioni/queries/firstRegistered.json b/geoportal-client/src/test/resources/concessioni/queries/firstRegistered.json
new file mode 100644
index 0000000..f70d918
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/queries/firstRegistered.json
@@ -0,0 +1,10 @@
+{
+ "paging" : {
+ "offset" : 0,
+ "limit" : 1
+ },
+ "ordering" : {
+ "direction" : "ASCENDING",
+ "fields" : ["creationTime","nome"]
+ }
+}
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/queries/lastNameRegisteredByFabio.json b/geoportal-client/src/test/resources/concessioni/queries/lastNameRegisteredByFabio.json
new file mode 100644
index 0000000..668175a
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/queries/lastNameRegisteredByFabio.json
@@ -0,0 +1,18 @@
+{
+ "paging" : {
+ "offset" : 0,
+ "limit" : 1
+ },
+ "ordering" : {
+ "direction" : "DESCENDING",
+ "fields" : ["creationTime","nome"]
+ },
+ "filter" : {
+ "creationUser" : {$eq : "fabio.sinibaldi"}
+ },
+ "projection" : {
+ "nome" : 1
+ }
+
+
+}
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/queries/lastRegistered.json b/geoportal-client/src/test/resources/concessioni/queries/lastRegistered.json
new file mode 100644
index 0000000..3324a3a
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/queries/lastRegistered.json
@@ -0,0 +1,11 @@
+{
+ "paging" : {
+ "offset" : 0,
+ "limit" : 1
+ },
+ "ordering" : {
+ "direction" : "DESCENDING",
+ "fields" : ["creationTime","nome"]
+ }
+
+}
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/queries/publicationWarningMessages.json b/geoportal-client/src/test/resources/concessioni/queries/publicationWarningMessages.json
new file mode 100644
index 0000000..514bb64
--- /dev/null
+++ b/geoportal-client/src/test/resources/concessioni/queries/publicationWarningMessages.json
@@ -0,0 +1,10 @@
+{
+ "ordering" : {
+ "direction" : "DESCENDING",
+ "fields" : ["nome"]
+ },
+
+ "filter" : {"report.status" : {"$eq" : "WARNING"}},
+ "projection" : {"report.warningMessages" : 1}
+
+}
\ No newline at end of file
diff --git a/geoportal-client/src/test/resources/concessioni/relazione.pdf b/geoportal-client/src/test/resources/concessioni/relazione.pdf
new file mode 100644
index 0000000..65c914c
Binary files /dev/null and b/geoportal-client/src/test/resources/concessioni/relazione.pdf differ
diff --git a/geoportal-common/CHANGELOG.md b/geoportal-common/CHANGELOG.md
new file mode 100644
index 0000000..78a2f46
--- /dev/null
+++ b/geoportal-common/CHANGELOG.md
@@ -0,0 +1,41 @@
+This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+# Changelog for org.gcube.application.geoportal-common
+
+# [v1.0.7-SNAPSHOT] - 2021-09-20
+Refactored repositories
+
+# [v1.0.6-SNAPSHOT] - 2021-08-3
+Forced Deletion
+Search & query
+Clean Fileset
+Interfaces return iterator instead of iterable
+Name in WorkspaceContent (https://support.d4science.org/issues/22032)
+Section AbstractRelazione (https://support.d4science.org/issues/22031)
+
+# [v1.0.5] - 2020-12-9
+Mongo Id in record
+Mongo Concessioni interface
+Added Files.fixFileNAme
+ValidationReport as field
+Updated Model (#20357)
+
+
+# [v1.0.4-SNAPSHOT] - 2020-12-9
+Projects Rest Interface
+TempFile support
+
+# [v1.0.3] - 2020-12-4
+Project model update
+
+
+# [v1.0.2-SNAPSHOT] - 2020-12-4
+Model update
+
+## [v1.0.1] - 2020-11-11
+
+Model update
+
+## [v1.0.0] - 2020-11-11
+
+First release
\ No newline at end of file
diff --git a/geoportal-common/FUNDING.md b/geoportal-common/FUNDING.md
new file mode 100644
index 0000000..9e48b94
--- /dev/null
+++ b/geoportal-common/FUNDING.md
@@ -0,0 +1,26 @@
+# Acknowledgments
+
+The projects leading to this software have received funding from a series of European Union programmes including:
+
+- the Sixth Framework Programme for Research and Technological Development
+ - [DILIGENT](https://cordis.europa.eu/project/id/004260) (grant no. 004260).
+- the Seventh Framework Programme for research, technological development and demonstration
+ - [D4Science](https://cordis.europa.eu/project/id/212488) (grant no. 212488);
+ - [D4Science-II](https://cordis.europa.eu/project/id/239019) (grant no.239019);
+ - [ENVRI](https://cordis.europa.eu/project/id/283465) (grant no. 283465);
+ - [iMarine](https://cordis.europa.eu/project/id/283644) (grant no. 283644);
+ - [EUBrazilOpenBio](https://cordis.europa.eu/project/id/288754) (grant no. 288754).
+- the H2020 research and innovation programme
+ - [SoBigData](https://cordis.europa.eu/project/id/654024) (grant no. 654024);
+ - [PARTHENOS](https://cordis.europa.eu/project/id/654119) (grant no. 654119);
+ - [EGI-Engage](https://cordis.europa.eu/project/id/654142) (grant no. 654142);
+ - [ENVRI PLUS](https://cordis.europa.eu/project/id/654182) (grant no. 654182);
+ - [BlueBRIDGE](https://cordis.europa.eu/project/id/675680) (grant no. 675680);
+ - [PerformFISH](https://cordis.europa.eu/project/id/727610) (grant no. 727610);
+ - [AGINFRA PLUS](https://cordis.europa.eu/project/id/731001) (grant no. 731001);
+ - [DESIRA](https://cordis.europa.eu/project/id/818194) (grant no. 818194);
+ - [ARIADNEplus](https://cordis.europa.eu/project/id/823914) (grant no. 823914);
+ - [RISIS 2](https://cordis.europa.eu/project/id/824091) (grant no. 824091);
+ - [EOSC-Pillar](https://cordis.europa.eu/project/id/857650) (grant no. 857650);
+ - [Blue Cloud](https://cordis.europa.eu/project/id/862409) (grant no. 862409);
+ - [SoBigData-PlusPlus](https://cordis.europa.eu/project/id/871042) (grant no. 871042);
diff --git a/geoportal-common/LICENSE.md b/geoportal-common/LICENSE.md
new file mode 100644
index 0000000..3af0507
--- /dev/null
+++ b/geoportal-common/LICENSE.md
@@ -0,0 +1,312 @@
+# European Union Public Licence V. 1.1
+
+
+EUPL © the European Community 2007
+
+
+This European Union Public Licence (the “EUPL”) applies to the Work or Software
+(as defined below) which is provided under the terms of this Licence. Any use of
+the Work, other than as authorised under this Licence is prohibited (to the
+extent such use is covered by a right of the copyright holder of the Work).
+
+The Original Work is provided under the terms of this Licence when the Licensor
+(as defined below) has placed the following notice immediately following the
+copyright notice for the Original Work:
+
+Licensed under the EUPL V.1.1
+
+or has expressed by any other mean his willingness to license under the EUPL.
+
+
+
+## 1. Definitions
+
+In this Licence, the following terms have the following meaning:
+
+- The Licence: this Licence.
+
+- The Original Work or the Software: the software distributed and/or
+ communicated by the Licensor under this Licence, available as Source Code and
+ also as Executable Code as the case may be.
+
+- Derivative Works: the works or software that could be created by the Licensee,
+ based upon the Original Work or modifications thereof. This Licence does not
+ define the extent of modification or dependence on the Original Work required
+ in order to classify a work as a Derivative Work; this extent is determined by
+ copyright law applicable in the country mentioned in Article 15.
+
+- The Work: the Original Work and/or its Derivative Works.
+
+- The Source Code: the human-readable form of the Work which is the most
+ convenient for people to study and modify.
+
+- The Executable Code: any code which has generally been compiled and which is
+ meant to be interpreted by a computer as a program.
+
+- The Licensor: the natural or legal person that distributes and/or communicates
+ the Work under the Licence.
+
+- Contributor(s): any natural or legal person who modifies the Work under the
+ Licence, or otherwise contributes to the creation of a Derivative Work.
+
+- The Licensee or “You”: any natural or legal person who makes any usage of the
+ Software under the terms of the Licence.
+
+- Distribution and/or Communication: any act of selling, giving, lending,
+ renting, distributing, communicating, transmitting, or otherwise making
+ available, on-line or off-line, copies of the Work or providing access to its
+ essential functionalities at the disposal of any other natural or legal
+ person.
+
+
+
+## 2. Scope of the rights granted by the Licence
+
+The Licensor hereby grants You a world-wide, royalty-free, non-exclusive,
+sub-licensable licence to do the following, for the duration of copyright vested
+in the Original Work:
+
+- use the Work in any circumstance and for all usage, reproduce the Work, modify
+- the Original Work, and make Derivative Works based upon the Work, communicate
+- to the public, including the right to make available or display the Work or
+- copies thereof to the public and perform publicly, as the case may be, the
+- Work, distribute the Work or copies thereof, lend and rent the Work or copies
+- thereof, sub-license rights in the Work or copies thereof.
+
+Those rights can be exercised on any media, supports and formats, whether now
+known or later invented, as far as the applicable law permits so.
+
+In the countries where moral rights apply, the Licensor waives his right to
+exercise his moral right to the extent allowed by law in order to make effective
+the licence of the economic rights here above listed.
+
+The Licensor grants to the Licensee royalty-free, non exclusive usage rights to
+any patents held by the Licensor, to the extent necessary to make use of the
+rights granted on the Work under this Licence.
+
+
+
+## 3. Communication of the Source Code
+
+The Licensor may provide the Work either in its Source Code form, or as
+Executable Code. If the Work is provided as Executable Code, the Licensor
+provides in addition a machine-readable copy of the Source Code of the Work
+along with each copy of the Work that the Licensor distributes or indicates, in
+a notice following the copyright notice attached to the Work, a repository where
+the Source Code is easily and freely accessible for as long as the Licensor
+continues to distribute and/or communicate the Work.
+
+
+
+## 4. Limitations on copyright
+
+Nothing in this Licence is intended to deprive the Licensee of the benefits from
+any exception or limitation to the exclusive rights of the rights owners in the
+Original Work or Software, of the exhaustion of those rights or of other
+applicable limitations thereto.
+
+
+
+## 5. Obligations of the Licensee
+
+The grant of the rights mentioned above is subject to some restrictions and
+obligations imposed on the Licensee. Those obligations are the following:
+
+Attribution right: the Licensee shall keep intact all copyright, patent or
+trademarks notices and all notices that refer to the Licence and to the
+disclaimer of warranties. The Licensee must include a copy of such notices and a
+copy of the Licence with every copy of the Work he/she distributes and/or
+communicates. The Licensee must cause any Derivative Work to carry prominent
+notices stating that the Work has been modified and the date of modification.
+
+Copyleft clause: If the Licensee distributes and/or communicates copies of the
+Original Works or Derivative Works based upon the Original Work, this
+Distribution and/or Communication will be done under the terms of this Licence
+or of a later version of this Licence unless the Original Work is expressly
+distributed only under this version of the Licence. The Licensee (becoming
+Licensor) cannot offer or impose any additional terms or conditions on the Work
+or Derivative Work that alter or restrict the terms of the Licence.
+
+Compatibility clause: If the Licensee Distributes and/or Communicates Derivative
+Works or copies thereof based upon both the Original Work and another work
+licensed under a Compatible Licence, this Distribution and/or Communication can
+be done under the terms of this Compatible Licence. For the sake of this clause,
+“Compatible Licence” refers to the licences listed in the appendix attached to
+this Licence. Should the Licensee’s obligations under the Compatible Licence
+conflict with his/her obligations under this Licence, the obligations of the
+Compatible Licence shall prevail.
+
+Provision of Source Code: When distributing and/or communicating copies of the
+Work, the Licensee will provide a machine-readable copy of the Source Code or
+indicate a repository where this Source will be easily and freely available for
+as long as the Licensee continues to distribute and/or communicate the Work.
+
+Legal Protection: This Licence does not grant permission to use the trade names,
+trademarks, service marks, or names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the copyright notice.
+
+
+
+## 6. Chain of Authorship
+
+The original Licensor warrants that the copyright in the Original Work granted
+hereunder is owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each Contributor warrants that the copyright in the modifications he/she brings
+to the Work are owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each time You accept the Licence, the original Licensor and subsequent
+Contributors grant You a licence to their contributions to the Work, under the
+terms of this Licence.
+
+
+
+## 7. Disclaimer of Warranty
+
+The Work is a work in progress, which is continuously improved by numerous
+contributors. It is not a finished work and may therefore contain defects or
+“bugs” inherent to this type of software development.
+
+For the above reason, the Work is provided under the Licence on an “as is” basis
+and without warranties of any kind concerning the Work, including without
+limitation merchantability, fitness for a particular purpose, absence of defects
+or errors, accuracy, non-infringement of intellectual property rights other than
+copyright as stated in Article 6 of this Licence.
+
+This disclaimer of warranty is an essential part of the Licence and a condition
+for the grant of any rights to the Work.
+
+
+
+## 8. Disclaimer of Liability
+
+Except in the cases of wilful misconduct or damages directly caused to natural
+persons, the Licensor will in no event be liable for any direct or indirect,
+material or moral, damages of any kind, arising out of the Licence or of the use
+of the Work, including without limitation, damages for loss of goodwill, work
+stoppage, computer failure or malfunction, loss of data or any commercial
+damage, even if the Licensor has been advised of the possibility of such
+damage. However, the Licensor will be liable under statutory product liability
+laws as far such laws apply to the Work.
+
+
+
+## 9. Additional agreements
+
+While distributing the Original Work or Derivative Works, You may choose to
+conclude an additional agreement to offer, and charge a fee for, acceptance of
+support, warranty, indemnity, or other liability obligations and/or services
+consistent with this Licence. However, in accepting such obligations, You may
+act only on your own behalf and on your sole responsibility, not on behalf of
+the original Licensor or any other Contributor, and only if You agree to
+indemnify, defend, and hold each Contributor harmless for any liability incurred
+by, or claims asserted against such Contributor by the fact You have accepted
+any such warranty or additional liability.
+
+
+
+## 10. Acceptance of the Licence
+
+The provisions of this Licence can be accepted by clicking on an icon “I agree”
+placed under the bottom of a window displaying the text of this Licence or by
+affirming consent in any other similar way, in accordance with the rules of
+applicable law. Clicking on that icon indicates your clear and irrevocable
+acceptance of this Licence and all of its terms and conditions.
+
+Similarly, you irrevocably accept this Licence and all of its terms and
+conditions by exercising any rights granted to You by Article 2 of this Licence,
+such as the use of the Work, the creation by You of a Derivative Work or the
+Distribution and/or Communication by You of the Work or copies thereof.
+
+
+
+## 11. Information to the public
+
+In case of any Distribution and/or Communication of the Work by means of
+electronic communication by You (for example, by offering to download the Work
+from a remote location) the distribution channel or media (for example, a
+website) must at least provide to the public the information requested by the
+applicable law regarding the Licensor, the Licence and the way it may be
+accessible, concluded, stored and reproduced by the Licensee.
+
+
+
+## 12. Termination of the Licence
+
+The Licence and the rights granted hereunder will terminate automatically upon
+any breach by the Licensee of the terms of the Licence.
+
+Such a termination will not terminate the licences of any person who has
+received the Work from the Licensee under the Licence, provided such persons
+remain in full compliance with the Licence.
+
+
+
+## 13. Miscellaneous
+
+Without prejudice of Article 9 above, the Licence represents the complete
+agreement between the Parties as to the Work licensed hereunder.
+
+If any provision of the Licence is invalid or unenforceable under applicable
+law, this will not affect the validity or enforceability of the Licence as a
+whole. Such provision will be construed and/or reformed so as necessary to make
+it valid and enforceable.
+
+The European Commission may publish other linguistic versions and/or new
+versions of this Licence, so far this is required and reasonable, without
+reducing the scope of the rights granted by the Licence. New versions of the
+Licence will be published with a unique version number.
+
+All linguistic versions of this Licence, approved by the European Commission,
+have identical value. Parties can take advantage of the linguistic version of
+their choice.
+
+
+
+## 14. Jurisdiction
+
+Any litigation resulting from the interpretation of this License, arising
+between the European Commission, as a Licensor, and any Licensee, will be
+subject to the jurisdiction of the Court of Justice of the European Communities,
+as laid down in article 238 of the Treaty establishing the European Community.
+
+Any litigation arising between Parties, other than the European Commission, and
+resulting from the interpretation of this License, will be subject to the
+exclusive jurisdiction of the competent court where the Licensor resides or
+conducts its primary business.
+
+
+
+## 15. Applicable Law
+
+This Licence shall be governed by the law of the European Union country where
+the Licensor resides or has his registered office.
+
+This licence shall be governed by the Belgian law if:
+
+- a litigation arises between the European Commission, as a Licensor, and any
+- Licensee; the Licensor, other than the European Commission, has no residence
+- or registered office inside a European Union country.
+
+
+
+## Appendix
+
+
+
+“Compatible Licences” according to article 5 EUPL are:
+
+
+- GNU General Public License (GNU GPL) v. 2
+
+- Open Software License (OSL) v. 2.1, v. 3.0
+
+- Common Public License v. 1.0
+
+- Eclipse Public License v. 1.0
+
+- Cecill v. 2.0
+
diff --git a/geoportal-common/README.md b/geoportal-common/README.md
new file mode 100644
index 0000000..95025f7
--- /dev/null
+++ b/geoportal-common/README.md
@@ -0,0 +1,50 @@
+GeoPortal - Common
+--------------------------------------------------
+
+GeoPortal - Common is the java library containing basic classes (e.g. models) of gCube GeoPortal.
+
+## Built with
+* [Maven](https://maven.apache.org/) - Dependency Management
+
+## Documentation
+
+Documentation can be found [here](https://gcube.wiki.gcube-system.org/gcube/GeoPortal).
+
+## Change log
+
+See [CHANGELOG.md](CHANGELOG.md).
+
+## License
+
+This project is licensed under the EUPL V.1.1 License - see the [LICENSE.md](LICENSE.md) file for details.
+
+## About the gCube Framework
+This software is part of the [gCubeFramework](https://www.gcube-system.org/ "gCubeFramework"): an
+open-source software toolkit used for building and operating Hybrid Data
+Infrastructures enabling the dynamic deployment of Virtual Research Environments
+by favouring the realisation of reuse oriented policies.
+
+The projects leading to this software have received funding from a series of European Union programmes including:
+
+- the Sixth Framework Programme for Research and Technological Development
+ - DILIGENT (grant no. 004260).
+- the Seventh Framework Programme for research, technological development and demonstration
+ - D4Science (grant no. 212488);
+ - D4Science-II (grant no.239019);
+ - ENVRI (grant no. 283465);
+ - iMarine(grant no. 283644);
+ - EUBrazilOpenBio (grant no. 288754).
+- the H2020 research and innovation programme
+ - SoBigData (grant no. 654024);
+ - PARTHENOS (grant no. 654119);
+ - EGIEngage (grant no. 654142);
+ - ENVRIplus (grant no. 654182);
+ - BlueBRIDGE (grant no. 675680);
+ - PerformFish (grant no. 727610);
+ - AGINFRAplus (grant no. 731001);
+ - DESIRA (grant no. 818194);
+ - ARIADNEplus (grant no. 823914);
+ - RISIS2 (grant no. 824091);
+
+
+
diff --git a/geoportal-common/pom.xml b/geoportal-common/pom.xml
new file mode 100644
index 0000000..7236f7e
--- /dev/null
+++ b/geoportal-common/pom.xml
@@ -0,0 +1,103 @@
+
+ 4.0.0
+ org.gcube.application
+ geoportal-common
+ 1.0.7-SNAPSHOT
+ Geoportal Common
+
+
+
+ org.gcube.application.cms
+ gcube-cms-suite
+ 1.0.0-SNAPSHOT
+
+
+
+ https://code-repo.d4science.org/gCubeSystem
+ 1.0
+
+
+
+
+
+
+ org.gcube.distribution
+ gcube-bom
+ 2.0.1
+ pom
+ import
+
+
+
+
+
+ scm:git:${gitBaseUrl}/${project.artifactId}.git
+ scm:git:${gitBaseUrl}/${project.artifactId}.git
+ ${gitBaseUrl}/${project.artifactId}.git
+
+
+
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.14.8
+
+
+
+
+ org.gcube.common
+ authorization-client
+
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+
+
+
+ org.glassfish.jersey.media
+ jersey-media-json-jackson
+
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ 2.8.8
+
+
+
+
+ org.gcube.contentmanagement
+ storage-manager-core
+ [2.0.0, 3.0.0-SNAPSHOT)
+
+
+ org.gcube.contentmanagement
+ storage-manager-wrapper
+ [2.0.0, 3.0.0-SNAPSHOT)
+
+
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+
+
+
+
\ No newline at end of file
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/faults/JsonParseException.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/faults/JsonParseException.java
new file mode 100644
index 0000000..f45f8a1
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/faults/JsonParseException.java
@@ -0,0 +1,37 @@
+package org.gcube.application.geoportal.common.faults;
+
+public class JsonParseException extends Exception{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public JsonParseException() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public JsonParseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ // TODO Auto-generated constructor stub
+ }
+
+ public JsonParseException(String message, Throwable cause) {
+ super(message, cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ public JsonParseException(String message) {
+ super(message);
+ // TODO Auto-generated constructor stub
+ }
+
+ public JsonParseException(Throwable cause) {
+ super(cause);
+ // TODO Auto-generated constructor stub
+ }
+
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/BasicJSONObject.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/BasicJSONObject.java
new file mode 100644
index 0000000..3ba4e81
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/BasicJSONObject.java
@@ -0,0 +1,7 @@
+package org.gcube.application.geoportal.common.model;
+
+public class BasicJSONObject {
+
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/AbstractRelazione.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/AbstractRelazione.java
new file mode 100644
index 0000000..d5cab38
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/AbstractRelazione.java
@@ -0,0 +1,16 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@ToString(callSuper=true)
+public class AbstractRelazione extends AssociatedContent{
+
+ private String abstractIta;
+ private String abstractEng;
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/AccessPolicy.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/AccessPolicy.java
new file mode 100644
index 0000000..f17f659
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/AccessPolicy.java
@@ -0,0 +1,7 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+public enum AccessPolicy {
+
+ OPEN,RESTRICTED,EMBARGOED;
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/AssociatedContent.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/AssociatedContent.java
new file mode 100644
index 0000000..627d244
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/AssociatedContent.java
@@ -0,0 +1,132 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport;
+import org.gcube.application.geoportal.common.utils.CollectionsUtils;
+
+import lombok.Getter;
+import lombok.Setter;
+
+
+@Getter
+@Setter
+
+public abstract class AssociatedContent {
+
+ private String mongo_id;
+ private long id;
+
+ private AccessPolicy policy;
+ private String licenseID;
+ private String titolo;
+ private LocalDateTime creationTime;
+
+
+ public ValidationReport validateForInsertion() {
+ ValidationReport toReturn=new ValidationReport("Associated Content");
+ toReturn.checkMandatory(policy, "Politica di accesso");
+ toReturn.checkMandatory(licenseID, "Licenza");
+ toReturn.checkMandatory(titolo,"Titolo");
+ toReturn.checkMandatory(creationTime, "Creation time");
+ return toReturn;
+ }
+
+
+
+ @XmlElements({
+ @XmlElement(type=GeoServerContent.class),
+ @XmlElement(type=WorkspaceContent.class),
+ })
+
+ private List actualContent=new ArrayList<>();
+
+
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+// result = prime * result + ((actualContent == null) ? 0 : actualContent.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(actualContent);
+
+ result = prime * result + ((creationTime == null) ? 0 : creationTime.hashCode());
+ result = prime * result + (int) (id ^ (id >>> 32));
+ result = prime * result + ((licenseID == null) ? 0 : licenseID.hashCode());
+ result = prime * result + ((policy == null) ? 0 : policy.hashCode());
+ result = prime * result + ((titolo == null) ? 0 : titolo.hashCode());
+ return result;
+ }
+
+
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ AssociatedContent other = (AssociatedContent) obj;
+// if (actualContent == null) {
+// if (other.actualContent != null)
+// return false;
+// } else if (!actualContent.equals(other.actualContent))
+// return false;
+ if(!CollectionsUtils.equalsCollections(actualContent, other.actualContent)) return false;
+
+ if (creationTime == null) {
+ if (other.creationTime != null)
+ return false;
+ } else if (!creationTime.equals(other.creationTime))
+ return false;
+ if (id != other.id)
+ return false;
+ if (licenseID == null) {
+ if (other.licenseID != null)
+ return false;
+ } else if (!licenseID.equals(other.licenseID))
+ return false;
+ if (policy != other.policy)
+ return false;
+ if (titolo == null) {
+ if (other.titolo != null)
+ return false;
+ } else if (!titolo.equals(other.titolo))
+ return false;
+ return true;
+ }
+
+
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("AssociatedContent [id=");
+ builder.append(id);
+ builder.append(", policy=");
+ builder.append(policy);
+ builder.append(", licenseID=");
+ builder.append(licenseID);
+ builder.append(", titolo=");
+ builder.append(titolo);
+ builder.append(", creationTime=");
+ builder.append(creationTime);
+
+ builder.append(", actualContent=");
+ builder.append(actualContent);
+ builder.append("]");
+ return builder.toString();
+ }
+
+
+
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/BBOX.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/BBOX.java
new file mode 100644
index 0000000..aa88773
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/BBOX.java
@@ -0,0 +1,36 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import java.io.Serializable;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+
+@RequiredArgsConstructor
+@Getter
+@NoArgsConstructor
+@EqualsAndHashCode
+@ToString
+public class BBOX implements Serializable{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -159414992596542946L;
+
+ public static BBOX WORLD_EXTENT=new BBOX(90d,180d,-90d,-180d);
+
+ @NonNull
+ private Double maxLat;
+ @NonNull
+ private Double maxLong;
+ @NonNull
+ private Double minLat;
+ @NonNull
+ private Double minLong;
+
+
+}
\ No newline at end of file
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/Concessione.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/Concessione.java
new file mode 100644
index 0000000..f664862
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/Concessione.java
@@ -0,0 +1,512 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.gcube.application.geoportal.common.model.legacy.report.Check;
+import org.gcube.application.geoportal.common.model.legacy.report.ConstraintCheck;
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport;
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport.ValidationStatus;
+import org.gcube.application.geoportal.common.utils.CollectionsUtils;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@ToString(callSuper=true)
+@XmlRootElement
+public class Concessione extends Record{
+
+
+ //Introduzione (descrizione del progetto)
+ private String introduzione;
+
+ //Descrizione del contenuto
+ private String descrizioneContenuto;
+
+ //Autori
+ private List authors;
+
+ //Soggetto che materialmente invia i dati.
+ private String contributore;
+
+ //Indicare il nome del titolare/i dei dati contenuti nel dataset e/o per sue specifiche parti.
+ private List titolari;
+
+ private String responsabile;
+ private String editore;
+
+
+ private List fontiFinanziamento;
+
+ //Research Excavation; Archaeology (valori di default)
+
+ private List soggetto;
+
+
+ //Referenze bibliografiche, DOI (se esistenti) di risorse correlate all’indagine in oggetto
+ private List risorseCorrelate;
+
+
+ private LocalDateTime dataInizioProgetto;
+ private LocalDateTime dataFineProgetto;
+
+ private List titolareLicenza;
+ private List titolareCopyright;
+
+
+
+ private List paroleChiaveLibere;
+
+ private List paroleChiaveICCD;
+
+
+ private Double centroidLat;
+ private Double centroidLong;
+
+ private RelazioneScavo relazioneScavo;
+ private AssociatedContent abstractRelazione;
+
+ private List immaginiRappresentative=new ArrayList();
+
+ private LayerConcessione posizionamentoScavo;
+
+ private List pianteFineScavo=new ArrayList<>();
+
+ private List genericContent=new ArrayList<>();
+
+
+ public Concessione() {
+ super();
+ setRecordType(RecordType.CONCESSIONE);
+ }
+
+
+ public static class Paths{
+ public final static String RELAZIONE="relazione";
+ public final static String POSIZIONAMENTO="posizionamentoScavo";
+ public final static String PIANTE="piante";
+ public final static String IMMAGINI="immagini";
+ public final static String ABSTRACT_RELAZIONE="abstract_relazione";
+ public static final String MONGO_ID="mongo_id";
+
+ public final static String piantaByIndex(int index) {return makeByIndex(PIANTE,index);};
+ public final static String imgByIndex(int index) {return makeByIndex(IMMAGINI,index);};
+
+ public final static String piantaById(String id) {return makeByStringField(PIANTE, MONGO_ID, id);};
+ public final static String imgById(String id) {return makeByStringField(IMMAGINI, MONGO_ID, id);};
+
+
+
+ private static String makeByIndex(String base,int value) {return String.format("%1$s[%2$d]",base,value);}
+ private static String makeByStringField(String base,String field,String value)
+ {return String.format("%1$s.%2$s:\"%3$s\"",base,field,value);}
+ }
+
+ @Override
+ public AssociatedContent getContentByPath(String path) {
+ switch(path) {
+ case Paths.RELAZIONE : return getRelazioneScavo();
+ case Paths.POSIZIONAMENTO : return getPosizionamentoScavo();
+ case Paths.ABSTRACT_RELAZIONE: return getAbstractRelazione();
+ }
+ if(path.matches("\\w+\\[\\d+\\]")) {
+ // Array section
+ String field=path.substring(0,path.lastIndexOf("["));
+ Integer index=Integer.parseInt(path.substring(path.lastIndexOf("[")+1,path.lastIndexOf("]")));
+ List extends AssociatedContent> list=null;
+ switch (field) {
+ case Paths.IMMAGINI : list = immaginiRappresentative; break;
+ case Paths.PIANTE : list = pianteFineScavo; break;
+ }
+ return getByIndex(list,index);
+
+ }
+ if(path.matches("\\w+\\.\\w+\\s*\\:\\s*\\\"\\w+\\\"")) {
+ // Map section
+ String field=path.substring(0,path.lastIndexOf("."));
+ String subField=path.substring(path.indexOf(".")+1,path.lastIndexOf(":")).trim();
+ String value=path.substring(path.indexOf("\"")+1,path.lastIndexOf("\""));
+ List extends AssociatedContent> list=null;
+ switch (field) {
+ case Paths.IMMAGINI : list = immaginiRappresentative; break;
+ case Paths.PIANTE : list = pianteFineScavo; break;
+ }
+ return getByFieldValue(list, subField, value);
+ }
+ return null;
+ }
+
+ private static AssociatedContent getByIndex(List extends AssociatedContent> list, int index) {
+ if(list == null )return null;
+ return list.get(index);
+ }
+
+// NB only mongo_id is supported in this impl.
+ private static AssociatedContent getByFieldValue(List extends AssociatedContent> list, String field, Object value) {
+ for(AssociatedContent c: list) {
+ switch(field) {
+ case Paths.MONGO_ID : {
+ if(c.getMongo_id()!=null&&c.getMongo_id().equals(value))
+ return c;
+ }
+ }
+ }
+ return null;
+ }
+
+
+ @Override
+ public void setAtPath(AssociatedContent toSet, String path) {
+ switch(path) {
+ case Paths.RELAZIONE : {
+ setRelazioneScavo((RelazioneScavo) toSet);
+ break;
+ }
+ case Paths.POSIZIONAMENTO : {
+ setPosizionamentoScavo((LayerConcessione) toSet);
+ break;
+ }
+ case Paths.ABSTRACT_RELAZIONE:{
+ setAbstractRelazione((AbstractRelazione)toSet);
+ break;
+ }
+ case Paths.PIANTE : {
+ if(pianteFineScavo==null)pianteFineScavo=new ArrayList();
+ pianteFineScavo.add((LayerConcessione) toSet);
+ break;
+ }
+ case Paths.IMMAGINI: {
+ if(immaginiRappresentative==null)immaginiRappresentative=new ArrayList();
+ pianteFineScavo.add((LayerConcessione) toSet);
+ break;
+ }
+
+ //TODO MATCH if()case Paths.PIANTa : return
+ //TODO MATCH if()case Paths.Img : return
+ }
+
+ }
+
+ @Override
+ public ValidationReport validate() {
+ ValidationReport validator= super.validate();
+
+ validator.setObjectName("Concessione");
+
+ setPolicy(AccessPolicy.OPEN);
+
+
+
+ validator.checkMandatory(authors, "Lista Autori");
+ if(validator.checkMandatory(centroidLat, "Latitudine"))
+ if(centroidLat>90||centroidLat<-90) validator.addMessage(ValidationStatus.ERROR, "Latitudine non valida : "+centroidLat);
+
+ if(validator.checkMandatory(centroidLong, "Longitudine"))
+ if(centroidLong>180||centroidLong<-180) validator.addMessage(ValidationStatus.ERROR, "Longitudine non valida : "+centroidLong);
+
+ validator.checkMandatory(contributore, "Contributore");
+ if(validator.checkMandatory(dataFineProgetto, "Data Fine Progetto") &&
+ validator.checkMandatory(dataInizioProgetto, "Data Inizio Progetto"))
+ if(dataFineProgetto.isBefore(dataInizioProgetto)) validator.addMessage(ValidationStatus.ERROR, "Data Fine Progetto non può esser prima di Data Inizio Progetto.");
+
+ validator.checkMandatory(descrizioneContenuto, "Descrizione contenuto");
+ validator.checkMandatory(editore, "Editore");
+ validator.checkMandatory(fontiFinanziamento, "Fonti Finanaziamento");
+ validator.checkMandatory(introduzione, "Introduzione");
+ validator.checkMandatory(paroleChiaveICCD, "Parole chiave ICCD");
+ validator.checkMandatory(paroleChiaveLibere, "Parole chiave libere");
+
+ validator.checkMandatory(responsabile,"Responsabile");
+
+
+ validator.checkMandatory(titolareCopyright, "Titolare Copyright");
+ validator.checkMandatory(titolareLicenza,"Titolare licenza");
+ validator.checkMandatory(titolari, "Titolari");
+
+
+
+ if(validator.checkMandatory(relazioneScavo, "Relazione scavo")) {
+ validator.addChild(relazioneScavo.validateForInsertion());
+ }
+
+ if(validator.checkMandatory(abstractRelazione,"Abstract Relazione")){
+ validator.addChild(abstractRelazione.validateForInsertion());
+ }
+
+// if(immaginiRappresentative!=null)
+//
+// for(UploadedImage img : immaginiRappresentative) {
+// validator.setDefault(img.getSoggetto(),getSoggetto());
+// validator.setDefault(img.getCreationTime(),getCreationTime());
+// validator.setDefault(img.getPolicy(), getPolicy());
+// validator.setDefault(img.getLicenzaID(), getLicenzaID());
+//
+// validator.addChild(img.validateForInsertion());
+// }
+//
+
+ if(validator.checkMandatory(posizionamentoScavo, "Posizionamento scavo")) {
+
+ ValidationReport posReport=posizionamentoScavo.validateForInsertion();
+ posReport.setObjectName("Posizionamento scavo");
+ validator.addChild(posReport);
+ }
+
+
+ if(genericContent!=null)
+ for(OtherContent content:genericContent)
+ validator.addChild(content.validateForInsertion());
+
+ if(validator.checkMandatory(pianteFineScavo,"Piante fine scavo"))
+ for(LayerConcessione l:pianteFineScavo) {
+ validator.addChild(l.validateForInsertion());
+ }
+
+
+
+
+
+ return validator;
+ }
+
+
+ @Override
+ public void setDefaults() {
+ super.setDefaults();
+ setSoggetto(ConstraintCheck.defaultFor(soggetto, Arrays.asList(new String[] {"Research Excavation","Archaeology"}))
+ .addChecks(Check.collectionSizeMin(2)).evaluate());
+
+ setDescrizioneContenuto(ConstraintCheck.defaultFor(getDescrizioneContenuto(),
+ "Relazione di fine scavo e relativo abstract; selezione di immagini rappresentative;"
+ + " posizionamento topografico dell'area indagata, pianta di fine scavo.").evaluate());
+
+
+ setSoggetto(ConstraintCheck.defaultFor(soggetto, Arrays.asList(new String[] {"Research Excavation","Archaeology"}))
+ .addChecks(Check.collectionSizeMin(2)).evaluate());
+
+ setLicenzaID(ConstraintCheck.defaultFor(getLicenzaID(), "CC0-1.0").evaluate());
+
+
+
+ if(relazioneScavo!=null) {
+ relazioneScavo.setTitolo(ConstraintCheck.defaultFor(relazioneScavo.getTitolo(),getNome()+" relazione di scavo").evaluate());
+ relazioneScavo.setSoggetto(ConstraintCheck.defaultFor(relazioneScavo.getSoggetto(),getSoggetto()).evaluate());
+ relazioneScavo.setCreationTime(ConstraintCheck.defaultFor(relazioneScavo.getCreationTime(),getCreationTime()).evaluate());
+ relazioneScavo.setLicenseID(ConstraintCheck.defaultFor(getLicenzaID(), "CC-BY-4.0").evaluate());
+ relazioneScavo.setPolicy(getPolicy());
+ }
+
+ if(abstractRelazione!=null) {
+ abstractRelazione.setTitolo(ConstraintCheck.defaultFor(abstractRelazione.getTitolo(),getNome()+" abstract relazione di scavo").evaluate());
+ abstractRelazione.setCreationTime(ConstraintCheck.defaultFor(abstractRelazione.getCreationTime(),getCreationTime()).evaluate());
+ abstractRelazione.setLicenseID(ConstraintCheck.defaultFor(getLicenzaID(), "CC-BY-4.0").evaluate());
+ abstractRelazione.setPolicy(getPolicy());
+ }
+
+
+ if(immaginiRappresentative!=null)
+ for(UploadedImage img : immaginiRappresentative) {
+ img.setSoggetto(ConstraintCheck.defaultFor(img.getSoggetto(),getSoggetto()).evaluate());
+ img.setCreationTime(ConstraintCheck.defaultFor(img.getCreationTime(),getCreationTime()).evaluate());
+ img.setPolicy(ConstraintCheck.defaultFor(img.getPolicy(),getPolicy()).evaluate());
+ img.setLicenseID(ConstraintCheck.defaultFor(img.getLicenseID(),"CC-BY-4.0").evaluate());
+ }
+
+
+ if(posizionamentoScavo!=null) {
+ posizionamentoScavo.setTitolo(ConstraintCheck.defaultFor(posizionamentoScavo.getTitolo(), getNome()+" posizionamento scavo").evaluate());
+ posizionamentoScavo.setAbstractSection(
+ ConstraintCheck.defaultFor(posizionamentoScavo.getAbstractSection(),"Posizionamento topografico georeferenziato dell’area interessata dalle indagini").evaluate());
+
+ posizionamentoScavo.setTopicCategory(ConstraintCheck.defaultFor(posizionamentoScavo.getTopicCategory(), "Society").evaluate());
+ posizionamentoScavo.setSubTopic(ConstraintCheck.defaultFor(posizionamentoScavo.getSubTopic(), "Archeology").evaluate());
+
+ posizionamentoScavo.setParoleChiaveLibere(ConstraintCheck.defaultFor(posizionamentoScavo.getParoleChiaveLibere(),getParoleChiaveLibere()).evaluate());
+ posizionamentoScavo.setParoleChiaveICCD(ConstraintCheck.defaultFor(posizionamentoScavo.getParoleChiaveICCD(),getParoleChiaveICCD()).evaluate());
+
+ //TODO Evaluate
+ posizionamentoScavo.setBbox(ConstraintCheck.defaultFor(posizionamentoScavo.getBbox(), BBOX.WORLD_EXTENT).evaluate());
+
+ posizionamentoScavo.setPolicy(ConstraintCheck.defaultFor(posizionamentoScavo.getPolicy(),getPolicy()).evaluate());;
+ posizionamentoScavo.setLicenseID(ConstraintCheck.defaultFor(posizionamentoScavo.getLicenseID(), "CC-BY-4.0").evaluate());
+ posizionamentoScavo.setResponsabile(getResponsabile());
+ posizionamentoScavo.setCreationTime(ConstraintCheck.defaultFor(posizionamentoScavo.getCreationTime(), getCreationTime()).evaluate());
+
+
+ }
+
+
+
+ if(pianteFineScavo!=null)
+ for(LayerConcessione l:pianteFineScavo) {
+
+ l.setTitolo(ConstraintCheck.defaultFor(l.getTitolo(), getNome()+" pianta fine scavo").evaluate());
+ l.setAbstractSection(
+ ConstraintCheck.defaultFor(l.getAbstractSection(),"Planimetria georeferenziata dell'area indagata al termine delle attività").evaluate());
+
+ l.setTopicCategory(ConstraintCheck.defaultFor(l.getTopicCategory(), "Society").evaluate());
+ l.setSubTopic(ConstraintCheck.defaultFor(l.getSubTopic(), "Archeology").evaluate());
+
+ l.setParoleChiaveLibere(ConstraintCheck.defaultFor(l.getParoleChiaveLibere(),getParoleChiaveLibere()).evaluate());
+ l.setParoleChiaveICCD(ConstraintCheck.defaultFor(l.getParoleChiaveICCD(),getParoleChiaveICCD()).evaluate());
+
+
+ l.setBbox(ConstraintCheck.defaultFor(l.getBbox(), BBOX.WORLD_EXTENT).evaluate());
+
+ l.setPolicy(ConstraintCheck.defaultFor(l.getPolicy(),getPolicy()).evaluate());;
+ l.setLicenseID(ConstraintCheck.defaultFor(l.getLicenseID(), "CC-BY-4.0").evaluate());
+ l.setResponsabile(getResponsabile());
+ l.setCreationTime(ConstraintCheck.defaultFor(l.getCreationTime(), getCreationTime()).evaluate());
+ }
+
+
+
+
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+// result = prime * result + ((authors == null) ? 0 : authors.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(authors);
+// result = prime * result + ((fontiFinanaziamento == null) ? 0 : fontiFinanaziamento.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(fontiFinanziamento);
+// result = prime * result + ((immaginiRappresentative == null) ? 0 : immaginiRappresentative.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(immaginiRappresentative);
+// result = prime * result + ((paroleChiaveICCD == null) ? 0 : paroleChiaveICCD.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(paroleChiaveICCD);
+// result = prime * result + ((paroleChiaveLibere == null) ? 0 : paroleChiaveLibere.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(paroleChiaveLibere);
+// result = prime * result + ((pianteFineScavo == null) ? 0 : pianteFineScavo.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(pianteFineScavo);
+// result = prime * result + ((risorseCorrelate == null) ? 0 : risorseCorrelate.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(risorseCorrelate);
+// result = prime * result + ((soggetto == null) ? 0 : soggetto.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(soggetto);
+// result = prime * result + ((titolari == null) ? 0 : titolari.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(titolari);
+
+ result = prime * result + ((centroidLat == null) ? 0 : centroidLat.hashCode());
+ result = prime * result + ((centroidLong == null) ? 0 : centroidLong.hashCode());
+ result = prime * result + ((contributore == null) ? 0 : contributore.hashCode());
+ result = prime * result + ((dataFineProgetto == null) ? 0 : dataFineProgetto.hashCode());
+ result = prime * result + ((dataInizioProgetto == null) ? 0 : dataInizioProgetto.hashCode());
+ result = prime * result + ((descrizioneContenuto == null) ? 0 : descrizioneContenuto.hashCode());
+ result = prime * result + ((editore == null) ? 0 : editore.hashCode());
+ result = prime * result + ((genericContent == null) ? 0 : genericContent.hashCode());
+ result = prime * result + ((introduzione == null) ? 0 : introduzione.hashCode());
+
+ result = prime * result + ((posizionamentoScavo == null) ? 0 : posizionamentoScavo.hashCode());
+ result = prime * result + ((relazioneScavo == null) ? 0 : relazioneScavo.hashCode());
+ result = prime * result + ((responsabile == null) ? 0 : responsabile.hashCode());
+ result = prime * result + ((titolareCopyright == null) ? 0 : titolareCopyright.hashCode());
+ result = prime * result + ((titolareLicenza == null) ? 0 : titolareLicenza.hashCode());
+ return result;
+ }
+
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Concessione other = (Concessione) obj;
+
+ if(!CollectionsUtils.equalsCollections(authors, other.authors)) return false;
+ if (!CollectionsUtils.equalsCollections(fontiFinanziamento, other.fontiFinanziamento)) return false;
+ if (!CollectionsUtils.equalsCollections(immaginiRappresentative, other.immaginiRappresentative)) return false;
+ if (!CollectionsUtils.equalsCollections(paroleChiaveICCD, other.paroleChiaveICCD)) return false;
+ if (!CollectionsUtils.equalsCollections(paroleChiaveLibere, other.paroleChiaveLibere)) return false;
+ if (!CollectionsUtils.equalsCollections(pianteFineScavo, other.pianteFineScavo)) return false;
+ if (!CollectionsUtils.equalsCollections(risorseCorrelate, other.risorseCorrelate)) return false;
+ if (!CollectionsUtils.equalsCollections(soggetto, other.soggetto)) return false;
+ if (!CollectionsUtils.equalsCollections(titolari, other.titolari)) return false;
+
+ if (centroidLat == null) {
+ if (other.centroidLat != null)
+ return false;
+ } else if (!centroidLat.equals(other.centroidLat))
+ return false;
+ if (centroidLong == null) {
+ if (other.centroidLong != null)
+ return false;
+ } else if (!centroidLong.equals(other.centroidLong))
+ return false;
+ if (contributore == null) {
+ if (other.contributore != null)
+ return false;
+ } else if (!contributore.equals(other.contributore))
+ return false;
+ if (dataFineProgetto == null) {
+ if (other.dataFineProgetto != null)
+ return false;
+ } else if (!dataFineProgetto.equals(other.dataFineProgetto))
+ return false;
+ if (dataInizioProgetto == null) {
+ if (other.dataInizioProgetto != null)
+ return false;
+ } else if (!dataInizioProgetto.equals(other.dataInizioProgetto))
+ return false;
+ if (descrizioneContenuto == null) {
+ if (other.descrizioneContenuto != null)
+ return false;
+ } else if (!descrizioneContenuto.equals(other.descrizioneContenuto))
+ return false;
+ if (editore == null) {
+ if (other.editore != null)
+ return false;
+ } else if (!editore.equals(other.editore))
+ return false;
+ if (genericContent == null) {
+ if (other.genericContent != null)
+ return false;
+ } else if (!genericContent.equals(other.genericContent))
+ return false;
+ if (introduzione == null) {
+ if (other.introduzione != null)
+ return false;
+ } else if (!introduzione.equals(other.introduzione))
+ return false;
+
+ if (posizionamentoScavo == null) {
+ if (other.posizionamentoScavo != null)
+ return false;
+ } else if (!posizionamentoScavo.equals(other.posizionamentoScavo))
+ return false;
+ if (relazioneScavo == null) {
+ if (other.relazioneScavo != null)
+ return false;
+ } else if (!relazioneScavo.equals(other.relazioneScavo))
+ return false;
+ if (responsabile == null) {
+ if (other.responsabile != null)
+ return false;
+ } else if (!responsabile.equals(other.responsabile))
+ return false;
+ if (titolareCopyright == null) {
+ if (other.titolareCopyright != null)
+ return false;
+ } else if (!titolareCopyright.equals(other.titolareCopyright))
+ return false;
+ if (titolareLicenza == null) {
+ if (other.titolareLicenza != null)
+ return false;
+ } else if (!titolareLicenza.equals(other.titolareLicenza))
+ return false;
+
+ return true;
+ }
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/GeoServerContent.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/GeoServerContent.java
new file mode 100644
index 0000000..88fd57a
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/GeoServerContent.java
@@ -0,0 +1,28 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@ToString(callSuper=true)
+
+@EqualsAndHashCode(callSuper=true)
+public class GeoServerContent extends PersistedContent{
+
+ //GeoServer Details
+ private String geoserverHostName;
+ private String geoserverPath;
+
+ private List fileNames=new ArrayList();
+
+
+ private String workspace;
+ private String store;
+ private String featureType;
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/InputStreamDescriptor.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/InputStreamDescriptor.java
new file mode 100644
index 0000000..2b04ec7
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/InputStreamDescriptor.java
@@ -0,0 +1,21 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import java.io.InputStream;
+
+import lombok.Data;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.Setter;
+
+@Data
+@Getter
+@Setter
+public class InputStreamDescriptor{
+
+ @NonNull
+ private InputStream stream;
+ @NonNull
+ private String filename;
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/LayerConcessione.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/LayerConcessione.java
new file mode 100644
index 0000000..fa3362a
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/LayerConcessione.java
@@ -0,0 +1,152 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import java.util.List;
+
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport;
+import org.gcube.application.geoportal.common.utils.CollectionsUtils;
+
+import lombok.Getter;
+import lombok.Setter;
+
+
+@Getter
+@Setter
+
+public class LayerConcessione extends SDILayerDescriptor{
+
+
+ //meta
+ private String layerUUID;
+ private Long layerID;
+
+ //layer
+ private String layerName;
+ private String wmsLink;
+ private String workspace;
+
+
+ //1.Identificazione
+ private String abstractSection;
+
+ //2.Classificazione
+ private String topicCategory;
+
+ //3.Keyword
+ private String subTopic;
+
+ //4. Delimitazione geographica
+ private BBOX bbox;
+
+ //5. Temporal
+
+ private List paroleChiaveLibere;
+
+ private List paroleChiaveICCD;
+
+ //6. Quality
+ private String valutazioneQualita;
+
+ private String metodoRaccoltaDati;
+
+ private String scalaAcquisizione;
+
+ //8. Responsabili
+ private List authors;
+
+ private String responsabile;
+
+
+
+
+ @Override
+ public ValidationReport validateForInsertion() {
+ ValidationReport toReturn=super.validateForInsertion();
+ toReturn.setObjectName("Layer Concessione");
+ toReturn.checkMandatory(abstractSection, "Abstract");
+ toReturn.checkMandatory(subTopic, "Categoria (Topic)");
+ //TODO
+// toReturn.checkMandatory(bbox, "Bounding Box");
+
+ toReturn.checkMandatory(valutazioneQualita, "Valutazione della qualita");
+ toReturn.checkMandatory(metodoRaccoltaDati, "Metodo raccolta dati");
+ toReturn.checkMandatory(scalaAcquisizione, "Scala acquisizione");
+ toReturn.checkMandatory(authors, "Autori");
+ return toReturn;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((abstractSection == null) ? 0 : abstractSection.hashCode());
+// result = prime * result + ((authors == null) ? 0 : authors.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(authors);
+
+
+ result = prime * result + ((bbox == null) ? 0 : bbox.hashCode());
+ result = prime * result + ((metodoRaccoltaDati == null) ? 0 : metodoRaccoltaDati.hashCode());
+ result = prime * result + ((scalaAcquisizione == null) ? 0 : scalaAcquisizione.hashCode());
+ result = prime * result + ((subTopic == null) ? 0 : subTopic.hashCode());
+ result = prime * result + ((topicCategory == null) ? 0 : topicCategory.hashCode());
+ result = prime * result + ((valutazioneQualita == null) ? 0 : valutazioneQualita.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ LayerConcessione other = (LayerConcessione) obj;
+ if (abstractSection == null) {
+ if (other.abstractSection != null)
+ return false;
+ } else if (!abstractSection.equals(other.abstractSection))
+ return false;
+// if (authors == null) {
+// if (other.authors != null)
+// return false;
+// } else if (!authors.equals(other.authors))
+// return false;
+ if(!CollectionsUtils.equalsCollections(authors, other.authors)) return false;
+
+
+ if (bbox == null) {
+ if (other.bbox != null)
+ return false;
+ } else if (!bbox.equals(other.bbox))
+ return false;
+ if (metodoRaccoltaDati == null) {
+ if (other.metodoRaccoltaDati != null)
+ return false;
+ } else if (!metodoRaccoltaDati.equals(other.metodoRaccoltaDati))
+ return false;
+ if (scalaAcquisizione == null) {
+ if (other.scalaAcquisizione != null)
+ return false;
+ } else if (!scalaAcquisizione.equals(other.scalaAcquisizione))
+ return false;
+ if (subTopic == null) {
+ if (other.subTopic != null)
+ return false;
+ } else if (!subTopic.equals(other.subTopic))
+ return false;
+ if (topicCategory == null) {
+ if (other.topicCategory != null)
+ return false;
+ } else if (!topicCategory.equals(other.topicCategory))
+ return false;
+ if (valutazioneQualita == null) {
+ if (other.valutazioneQualita != null)
+ return false;
+ } else if (!valutazioneQualita.equals(other.valutazioneQualita))
+ return false;
+ return true;
+ }
+
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/OtherContent.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/OtherContent.java
new file mode 100644
index 0000000..7aeda2f
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/OtherContent.java
@@ -0,0 +1,15 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@ToString(callSuper=true)
+
+public class OtherContent extends AssociatedContent {
+
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/PersistedContent.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/PersistedContent.java
new file mode 100644
index 0000000..9905d66
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/PersistedContent.java
@@ -0,0 +1,36 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@EqualsAndHashCode
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
+@JsonSubTypes({
+ @Type(value = GeoServerContent.class),
+ @Type(value = WorkspaceContent.class),
+ })
+public abstract class PersistedContent {
+
+ //Generic Info
+ private long id;
+
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("PersistedContent [id=");
+ builder.append(id);
+ builder.append("]");
+ return builder.toString();
+ }
+
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/Record.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/Record.java
new file mode 100644
index 0000000..4efecac
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/Record.java
@@ -0,0 +1,74 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import java.time.LocalDateTime;
+
+import org.gcube.application.geoportal.common.model.legacy.report.ConstraintCheck;
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@ToString
+@EqualsAndHashCode
+
+public abstract class Record {
+
+ private String mongo_id;
+
+ //Generic Info
+ private long id;
+
+ private RecordType recordType;
+ private String version;
+ private String licenzaID;
+
+ private AccessPolicy policy;
+ //Nome del progetto
+ private String nome;
+
+
+ //Storage Info
+ private String folderId;
+
+ //Accounting
+ private LocalDateTime lastUpdateTime;
+ private String lastUpdateUser;
+ private LocalDateTime creationTime;
+ private String creationUser;
+
+
+
+ private ValidationReport report;
+
+ public ValidationReport validate() {
+
+ setDefaults();
+ ValidationReport validator=new ValidationReport("Core metadata");
+ validator.checkMandatory(getRecordType(), "Record Type");
+
+ validator.checkMandatory(getNome(), "Nome");
+ setReport(validator);
+
+ return getReport();
+ }
+
+ public void setDefaults() {
+ LocalDateTime now=LocalDateTime.now();
+
+ setVersion(ConstraintCheck.defaultFor(getVersion(),"1.0.0").evaluate());
+ setPolicy(ConstraintCheck.defaultFor(getPolicy(), AccessPolicy.OPEN).evaluate());
+
+ setLastUpdateTime(ConstraintCheck.defaultFor(getLastUpdateTime(),now).evaluate());
+ setCreationTime(ConstraintCheck.defaultFor(getCreationTime(),now).evaluate());
+ setLicenzaID(ConstraintCheck.defaultFor(getLicenzaID(),"CC-BY").evaluate());
+ }
+
+
+ public abstract AssociatedContent getContentByPath(String path);
+ public abstract void setAtPath(AssociatedContent toSet,String path);
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/RecordType.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/RecordType.java
new file mode 100644
index 0000000..267cc3f
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/RecordType.java
@@ -0,0 +1,6 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+public enum RecordType {
+
+ CONCESSIONE,MOSI,MOPR
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/RelazioneScavo.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/RelazioneScavo.java
new file mode 100644
index 0000000..6cc5e88
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/RelazioneScavo.java
@@ -0,0 +1,60 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import java.util.List;
+
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport;
+import org.gcube.application.geoportal.common.utils.CollectionsUtils;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@ToString(callSuper=true)
+public class RelazioneScavo extends AssociatedContent {
+
+
+
+
+ private List responsabili;
+ private List soggetto;
+
+
+ @Override
+ public ValidationReport validateForInsertion() {
+
+ ValidationReport toReturn=super.validateForInsertion();
+ toReturn.setObjectName("Relazione Scavo");
+ toReturn.checkMandatory(responsabili, "Responsabili");
+ toReturn.checkMandatory(soggetto, "Soggetto");
+ return toReturn;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + CollectionsUtils.hashCode(responsabili);
+ result = prime * result + CollectionsUtils.hashCode(soggetto);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ RelazioneScavo other = (RelazioneScavo) obj;
+
+ if(!CollectionsUtils.equalsCollections(responsabili, other.responsabili)) return false;
+
+ if(!CollectionsUtils.equalsCollections(soggetto, other.soggetto)) return false;
+
+ return true;
+ }
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/SDILayerDescriptor.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/SDILayerDescriptor.java
new file mode 100644
index 0000000..c3af358
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/SDILayerDescriptor.java
@@ -0,0 +1,25 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import lombok.Getter;
+import lombok.Setter;
+
+
+@Getter
+@Setter
+public abstract class SDILayerDescriptor extends AssociatedContent{
+
+
+ public abstract Long getLayerID();
+ public abstract void setLayerID(Long layerID);
+ public abstract String getLayerUUID();
+ public abstract void setLayerUUID(String layerUUID);
+ public abstract String getLayerName();
+ public abstract void setLayerName(String layerName);
+ public abstract String getWmsLink();
+ public abstract void setWmsLink(String wmsLink);
+
+ public abstract void setWorkspace(String workspace);
+ public abstract String getWorkspace();
+ public abstract BBOX getBbox();
+ public abstract void setBbox(BBOX toSet);
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/UploadedImage.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/UploadedImage.java
new file mode 100644
index 0000000..3b5b413
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/UploadedImage.java
@@ -0,0 +1,73 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import java.util.List;
+
+import org.gcube.application.geoportal.common.utils.CollectionsUtils;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@ToString(callSuper=true)
+
+public class UploadedImage extends AssociatedContent {
+
+
+ private String didascalia;
+ private String format;
+
+ private List responsabili;
+ private List soggetto;
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((didascalia == null) ? 0 : didascalia.hashCode());
+ result = prime * result + ((format == null) ? 0 : format.hashCode());
+// result = prime * result + ((responsabili == null) ? 0 : responsabili.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(responsabili);
+// result = prime * result + ((soggetto == null) ? 0 : soggetto.hashCode());
+ result = prime * result + CollectionsUtils.hashCode(soggetto);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ UploadedImage other = (UploadedImage) obj;
+ if (didascalia == null) {
+ if (other.didascalia != null)
+ return false;
+ } else if (!didascalia.equals(other.didascalia))
+ return false;
+ if (format == null) {
+ if (other.format != null)
+ return false;
+ } else if (!format.equals(other.format))
+ return false;
+// if (responsabili == null) {
+// if (other.responsabili != null)
+// return false;
+// } else if (!responsabili.equals(other.responsabili))
+// return false;
+ if(!CollectionsUtils.equalsCollections(responsabili, other.responsabili)) return false;
+
+// if (soggetto == null) {
+// if (other.soggetto != null)
+// return false;
+// } else if (!soggetto.equals(other.soggetto))
+// return false;
+ if(!CollectionsUtils.equalsCollections(soggetto, other.soggetto)) return false;
+
+ return true;
+ }
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/WorkspaceContent.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/WorkspaceContent.java
new file mode 100644
index 0000000..5229d2b
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/WorkspaceContent.java
@@ -0,0 +1,19 @@
+package org.gcube.application.geoportal.common.model.legacy;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@Getter
+@Setter
+@ToString(callSuper=true)
+
+@EqualsAndHashCode(callSuper=true)
+public class WorkspaceContent extends PersistedContent{
+
+ private String mimetype;
+ private String storageID;
+ private String link;
+ private String name;
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/report/Check.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/report/Check.java
new file mode 100644
index 0000000..d5e2e27
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/report/Check.java
@@ -0,0 +1,56 @@
+package org.gcube.application.geoportal.common.model.legacy.report;
+
+import java.util.Collection;
+
+public interface Check{
+
+ public static Check collectionSizeMax(final int upperBound) {
+ return new Check() {
+ int size=0;
+ @Override
+ public boolean isOk(Object toCheck) {
+ int size=((Collection)toCheck).size();
+ return size<=upperBound;
+ }
+ @Override
+ public String getMessage() {
+ return "Numero elementi : "+size+" [max : "+upperBound+"]";
+ }
+ };
+ }
+
+ public static Check collectionSizeMin(final int lowerBound) {
+ return new Check() {
+ int size=0;
+ @Override
+ public boolean isOk(Object toCheck) {
+ int size=((Collection)toCheck).size();
+ return size>=lowerBound;
+ }
+ @Override
+ public String getMessage() {
+ return "Numero elementi : "+size+" [min : "+lowerBound+"]";
+ }
+ };
+ }
+
+ public static Check collectionSize(final int lowerBound, final int upperBound) {
+ return new Check() {
+ int size=0;
+
+ @Override
+ public boolean isOk(Object toCheck) {
+ size=((Collection)toCheck).size();
+ return size<=upperBound&&size>=lowerBound;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Numero elementi : "+size+" [min : "+lowerBound+" max : "+upperBound+"]";
+ }
+ };
+ }
+
+ public boolean isOk(Object toCheck);
+ public String getMessage();
+}
\ No newline at end of file
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/report/Checks.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/report/Checks.java
new file mode 100644
index 0000000..e5d57ae
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/report/Checks.java
@@ -0,0 +1,7 @@
+package org.gcube.application.geoportal.common.model.legacy.report;
+
+public class Checks {
+
+// public static final Check
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/report/ConstraintCheck.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/report/ConstraintCheck.java
new file mode 100644
index 0000000..558d108
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/legacy/report/ConstraintCheck.java
@@ -0,0 +1,103 @@
+package org.gcube.application.geoportal.common.model.legacy.report;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ConstraintCheck {
+
+ public static ConstraintCheck defaultFor(T toCheck,T defaultValue){
+ return new ConstraintCheck(toCheck).withDefault(defaultValue);
+ }
+
+
+ private T theObject;
+ private String fieldLabel;
+ private String message;
+ private boolean error=false;
+ private boolean mandatory;
+ private T theDefault;
+
+ private List additionalChecks=new ArrayList();
+
+ public ConstraintCheck(T theObject,Check...checks){
+ this.theObject=theObject;
+ for(Check c:checks)
+ additionalChecks.add(c);
+ check();
+
+ }
+ public ConstraintCheck withDefault(T theDefault){
+ this.theDefault=theDefault;
+ return this;
+ }
+ public ConstraintCheck addChecks(Check...checks){
+ for(Check c:checks)
+ additionalChecks.add(c);
+ return this;
+ }
+ public ConstraintCheck(T theObject,String fieldLabel,Check...checks){
+ this.theObject=theObject;
+ this.fieldLabel=fieldLabel;
+ for(Check c:checks)
+ additionalChecks.add(c);
+ check();
+ }
+
+ public T evaluate() {
+ check();
+ T result=theObject;
+ if(isError()) {
+ result=theDefault;
+ if(theDefault!=null && theDefault instanceof Collection) {
+ Collection defaultCollection=(Collection) theDefault;
+ ArrayList target=new ArrayList(defaultCollection);
+ result=(T) target;
+ }
+ }
+ return result;
+
+ }
+
+ private void check() {
+ if(theObject==null) {
+ this.setMessage(fieldLabel+" è un campo obbligatorio.");
+ this.setError(true);
+ }else
+ if((theObject instanceof String) && ((String) theObject).isEmpty()) {
+ this.setMessage(fieldLabel+" non può essere vuoto.");
+ this.setError(true);
+ }else
+ if((theObject instanceof Collection)) {
+ Collection toCheckCollection=(Collection) theObject;
+ if(toCheckCollection.isEmpty()) {
+ this.setMessage("La lista "+fieldLabel+" non può essere vuota.");
+ this.setError(true);
+ }
+
+
+ Boolean containsError=false;
+ Object[] array=toCheckCollection.toArray(new Object[toCheckCollection.size()]);
+ for(int i=0;i errorMessages=new ArrayList();
+ private List warningMessages=new ArrayList();
+ private List children=new ArrayList();
+
+
+ public ValidationStatus getStatus() {
+ if(!errorMessages.isEmpty()) return ValidationStatus.ERROR;
+
+ boolean isWarning=(!warningMessages.isEmpty());
+ for(ValidationReport obj : children) {
+ ValidationStatus status=obj.getStatus();
+ if(status.equals(ValidationStatus.ERROR)) return ValidationStatus.ERROR;
+ if(status.equals(ValidationStatus.WARNING)) isWarning=true;
+ }
+ if(isWarning) return ValidationStatus.WARNING;
+ return ValidationStatus.PASSED;
+ }
+
+ public void addChild(ValidationReport obj) {
+ children.add(obj);
+ }
+
+ public void addMessage(ValidationStatus status,String message) {
+ switch (status) {
+ case ERROR:
+ errorMessages.add(message);
+ break;
+ case WARNING :
+ warningMessages.add(message);
+ default:
+ break;
+ }
+ }
+
+
+
+
+ public boolean checkMandatory(T toCheck,String name,Check...checks) {
+ ConstraintCheck check=new ConstraintCheck(toCheck,name,checks);
+ if(check.isError())
+ this.addMessage(ValidationStatus.ERROR, check.getMessage());
+ return !check.isError();
+ }
+
+
+ public ValidationReport(String objectName) {
+ super();
+ this.objectName = objectName;
+ }
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/DefaultCompiler.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/DefaultCompiler.java
new file mode 100644
index 0000000..019f08a
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/DefaultCompiler.java
@@ -0,0 +1,7 @@
+package org.gcube.application.geoportal.common.model.profile;
+
+public class DefaultCompiler {
+
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/Field.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/Field.java
new file mode 100644
index 0000000..dd59a37
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/Field.java
@@ -0,0 +1,11 @@
+package org.gcube.application.geoportal.common.model.profile;
+
+import lombok.Getter;
+
+@Getter
+public class Field {
+
+
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/FieldMapping.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/FieldMapping.java
new file mode 100644
index 0000000..be913ee
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/FieldMapping.java
@@ -0,0 +1,7 @@
+package org.gcube.application.geoportal.common.model.profile;
+
+public class FieldMapping {
+
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/IndexDefinition.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/IndexDefinition.java
new file mode 100644
index 0000000..67ee4dd
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/IndexDefinition.java
@@ -0,0 +1,7 @@
+package org.gcube.application.geoportal.common.model.profile;
+
+public class IndexDefinition {
+
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/IsoMapper.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/IsoMapper.java
new file mode 100644
index 0000000..1cbd4b8
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/IsoMapper.java
@@ -0,0 +1,7 @@
+package org.gcube.application.geoportal.common.model.profile;
+
+public class IsoMapper {
+
+ private String className;
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/Profile.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/Profile.java
new file mode 100644
index 0000000..258c5ab
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/Profile.java
@@ -0,0 +1,24 @@
+package org.gcube.application.geoportal.common.model.profile;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@NoArgsConstructor
+@XmlRootElement
+public class Profile{
+
+ private String name;
+ private String id;
+ private List fields;
+
+ private List defaultCompilers;
+ private List validators;
+ private IsoMapper isoMapper;
+ private List centroidsMapping;
+ private List indexes;
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/Validator.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/Validator.java
new file mode 100644
index 0000000..d161f5d
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/profile/Validator.java
@@ -0,0 +1,5 @@
+package org.gcube.application.geoportal.common.model.profile;
+
+public class Validator {
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/Centroid.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/Centroid.java
new file mode 100644
index 0000000..ee752e9
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/Centroid.java
@@ -0,0 +1,9 @@
+package org.gcube.application.geoportal.common.model.project;
+
+public class Centroid {
+
+ private Double x;
+ private Double y;
+ private Double z;
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/Project.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/Project.java
new file mode 100644
index 0000000..c1801f8
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/Project.java
@@ -0,0 +1,43 @@
+package org.gcube.application.geoportal.common.model.project;
+
+import org.gcube.application.geoportal.common.model.BasicJSONObject;
+
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+public class Project {
+
+
+/**
+ * Project{
+ _id:
+ profile_id:
+ publication :{
+ creation_time:
+ creation_user:
+ last_update_time:
+ last_update_user:
+ version :
+ license :
+ policy :
+ status : VALID,
+ PUBLISHED,INVALID
+ document : {.....}
+ centroid : {
+ x:
+ y:
+ z:}
+ }
+
+ *
+ */
+
+ private String _id;
+ private String profile_id;
+ private Status status;
+ private Object document;
+ private Centroid centroid;
+ private PublicationDetails publication;
+
+ private String json;
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/PublicationDetails.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/PublicationDetails.java
new file mode 100644
index 0000000..3656a12
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/PublicationDetails.java
@@ -0,0 +1,22 @@
+package org.gcube.application.geoportal.common.model.project;
+
+import java.time.LocalDateTime;
+
+import lombok.Data;
+
+@Data
+public class PublicationDetails {
+
+ public static enum Policy{
+ OPEN,RESTRICTED,EMBARGOED;
+ }
+
+ private LocalDateTime creation_time;
+ private String creation_user;
+ private LocalDateTime last_update_time;
+ private String last_update_user;
+ private String version;
+ private String license;
+ private String policy;
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/Status.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/Status.java
new file mode 100644
index 0000000..0783b0a
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/Status.java
@@ -0,0 +1,11 @@
+package org.gcube.application.geoportal.common.model.project;
+
+import java.util.List;
+
+public class Status {
+
+
+ private StatusPhase phase;
+ private List messages;
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/StatusPhase.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/StatusPhase.java
new file mode 100644
index 0000000..522532c
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/StatusPhase.java
@@ -0,0 +1,13 @@
+package org.gcube.application.geoportal.common.model.project;
+
+public enum StatusPhase {
+
+ DRAFT,
+ UNDER_VALIDATION,
+ INVALID,
+ VALID,
+ UNDER_PUBLICATION,
+ PUBLICATION_ERROR,
+ PUBLISHED
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/StoredFile.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/StoredFile.java
new file mode 100644
index 0000000..1309362
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/project/StoredFile.java
@@ -0,0 +1,4 @@
+package org.gcube.application.geoportal.common.model.project;
+
+
+
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/AddSectionToConcessioneRequest.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/AddSectionToConcessioneRequest.java
new file mode 100644
index 0000000..2f18109
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/AddSectionToConcessioneRequest.java
@@ -0,0 +1,21 @@
+package org.gcube.application.geoportal.common.model.rest;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.gcube.application.geoportal.common.rest.TempFile;
+
+@XmlRootElement
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AddSectionToConcessioneRequest {
+
+ private String destinationPath;
+ private List streams;
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/Configuration.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/Configuration.java
new file mode 100644
index 0000000..029618a
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/Configuration.java
@@ -0,0 +1,15 @@
+package org.gcube.application.geoportal.common.model.rest;
+
+import lombok.Data;
+
+@Data
+public class Configuration {
+
+ // Index (postgis + layer) Configuration
+ public PostgisIndexDescriptor index;
+
+
+
+ // Mongo DB Configuration
+ // TBD
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/DatabaseConnection.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/DatabaseConnection.java
new file mode 100644
index 0000000..f03d8bf
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/DatabaseConnection.java
@@ -0,0 +1,16 @@
+package org.gcube.application.geoportal.common.model.rest;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DatabaseConnection {
+
+ private String user;
+ private String pwd;
+ private String url;
+
+}
\ No newline at end of file
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/PostgisIndexDescriptor.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/PostgisIndexDescriptor.java
new file mode 100644
index 0000000..9156f2f
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/PostgisIndexDescriptor.java
@@ -0,0 +1,13 @@
+package org.gcube.application.geoportal.common.model.rest;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+
+@Data
+@AllArgsConstructor
+public class PostgisIndexDescriptor {
+
+ public DatabaseConnection postgisDBIndex;
+ public String wmsLink;
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/QueryRequest.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/QueryRequest.java
new file mode 100644
index 0000000..ba054bc
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/model/rest/QueryRequest.java
@@ -0,0 +1,28 @@
+package org.gcube.application.geoportal.common.model.rest;
+
+import lombok.Data;
+import org.bson.Document;
+
+import java.util.List;
+
+@Data
+public class QueryRequest {
+
+ @Data
+ public static class PagedRequest{
+ private int offset;
+ private int Limit;
+ }
+
+ @Data
+ public static class OrderedRequest {
+ public static enum Direction {ASCENDING,DESCENDING}
+ private Direction direction;
+ private String json;
+ private List fields;
+ }
+ private Document filter;
+ private Document projection;
+ private OrderedRequest ordering;
+ private PagedRequest paging;
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/ConcessioniI.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/ConcessioniI.java
new file mode 100644
index 0000000..ee13b34
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/ConcessioniI.java
@@ -0,0 +1,10 @@
+package org.gcube.application.geoportal.common.rest;
+
+public interface ConcessioniI {
+
+
+ public String create(String toCreate) throws Exception;
+ public String readById(String id) throws Exception;
+ public String getAll() throws Exception;
+ public String addSection(String id,String updated) throws Exception;
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/InterfaceConstants.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/InterfaceConstants.java
new file mode 100644
index 0000000..3ed42f4
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/InterfaceConstants.java
@@ -0,0 +1,44 @@
+package org.gcube.application.geoportal.common.rest;
+
+public class InterfaceConstants {
+
+ public static final String NAMESPACE="http://gcube-system.org/namespaces/data/sdi-service";
+
+ public static final String APPLICATION_BASE_PATH="geoportal-service";
+ public static final String APPLICATION_PATH="/srv";
+ public static final String SERVICE_CLASS="Application";
+ public static final String SERVICE_NAME="GeoPortal";
+
+ public static final class Methods{
+ public static final String PROFILES="profiles";
+ public static final String SECTIONS="sections";
+ public static final String PROJECTS="projects";
+
+ public static final String CONCESSIONI="concessioni";
+ public static final String MONGO_CONCESSIONI="mongo-concessioni";
+
+
+ public static final String PUBLISH_PATH="publish";
+ public static final String REGISTER_FILES_PATH="registerFiles";
+ public static final String DELETE_FILES_PATH="deleteFiles";
+ public static final String CONFIGURATION_PATH="configuration";
+ public static final String SEARCH_PATH="search";
+ public static final String QUERY_PATH="query";
+
+ }
+
+ public static final class Parameters{
+ public static final String PROJECT_ID="project_id";
+ public static final String SECTION_ID="section_id";
+ public static final String PROFILE_ID="profile_id";
+
+// //INVESTIGATE CAPABILITIES
+// public static final String ORDER_BY="order_by";
+// public static final String LIMIT="limit";
+// public static final String OFFSET="offset";
+ public static final String FORCE="force";
+
+ }
+
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/MongoConcessioni.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/MongoConcessioni.java
new file mode 100644
index 0000000..e7e107e
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/MongoConcessioni.java
@@ -0,0 +1,32 @@
+package org.gcube.application.geoportal.common.rest;
+
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.rest.AddSectionToConcessioneRequest;
+import org.gcube.application.geoportal.common.model.rest.Configuration;
+import org.gcube.application.geoportal.common.model.rest.QueryRequest;
+
+import java.util.Iterator;
+
+public interface MongoConcessioni {
+
+ public Concessione createNew(Concessione c) throws Exception;
+ public void deleteById(String id) throws Exception;
+ public void deleteById(String id,Boolean force) throws Exception;
+ public Concessione getById(String id) throws Exception;
+ public Iterator getList()throws Exception;
+ public Concessione publish(String id) throws Exception;
+ public Concessione registerFileSet(String id, AddSectionToConcessioneRequest request) throws Exception;
+ public Concessione cleanFileSet(String id, String path) throws Exception;
+ public Concessione update(String id, String jsonUpdate) throws Exception;
+ public Concessione replace(Concessione replacement) throws Exception;
+
+ public void unPublish(String id)throws Exception;
+
+
+ public Configuration getCurrentConfiguration()throws Exception;
+ public Iterator search(String filter)throws Exception;
+ public Iterator query(QueryRequest request) throws Exception;
+ public String queryForJSON(QueryRequest request) throws Exception;
+
+ public Iterator queryForType(QueryRequest request,Class clazz) throws Exception;
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/ProjectsI.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/ProjectsI.java
new file mode 100644
index 0000000..6ff8a00
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/ProjectsI.java
@@ -0,0 +1,19 @@
+package org.gcube.application.geoportal.common.rest;
+
+import org.gcube.application.geoportal.common.model.project.Project;
+
+import java.util.Iterator;
+
+public interface ProjectsI {
+
+
+ public Iterator getAll() throws Exception;
+ public Iterator getByProfile(String profileId) throws Exception;
+ public Project getById(String profileId,String id) throws Exception;
+ public Iterator getByFilter(String filter)throws Exception;
+ public Iterator getByFilter(String filter, String profileId)throws Exception;
+ public Project registrNew(String profileId, String jsonDocument)throws Exception;
+ public Project update(String profileId, String projectId,String jsonDocument) throws Exception;
+ public void deleteById(String profileId, String projectId)throws Exception;
+ public void deleteById(String profileId, String projectId, Boolean force)throws Exception;
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/TempFile.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/TempFile.java
new file mode 100644
index 0000000..3477b5c
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/rest/TempFile.java
@@ -0,0 +1,15 @@
+package org.gcube.application.geoportal.common.rest;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TempFile {
+
+ private String id;
+ private String filename;
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/CollectionsUtils.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/CollectionsUtils.java
new file mode 100644
index 0000000..a4071a4
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/CollectionsUtils.java
@@ -0,0 +1,44 @@
+package org.gcube.application.geoportal.common.utils;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+public class CollectionsUtils {
+
+ public static boolean equalsCollections(Collection> a, Collection> b) {
+
+ if(a==null&&b!=null)
+ return false;
+ if(a!=null&&b==null)
+ return false;
+
+ if(a==null&&b==null)
+ return true;
+
+ if(a.size()!=b.size())
+ return false;
+
+ Iterator> itA=a.iterator();
+ Iterator> itB=a.iterator();
+ while(itA.hasNext()) {
+ if(!itA.next().equals(itB.next()))
+ return false;
+ }
+
+ return true;
+ }
+
+ public static int hashCode(Collection> a) {
+ if(a==null || a.isEmpty())
+ return 0;
+
+ final int prime = 31;
+ int result = 1;
+
+ Iterator> it=a.iterator();
+ while(it.hasNext())
+ result=prime*result+it.next().hashCode();
+ return result;
+ }
+
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/ContextUtils.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/ContextUtils.java
new file mode 100644
index 0000000..9984053
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/ContextUtils.java
@@ -0,0 +1,41 @@
+package org.gcube.application.geoportal.common.utils;
+
+import static org.gcube.common.authorization.client.Constants.authorizationService;
+
+import org.gcube.common.authorization.library.AuthorizationEntry;
+import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
+import org.gcube.common.scope.api.ScopeProvider;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class ContextUtils {
+
+
+ public static String getCurrentScope(){
+ try{
+ String token=SecurityTokenProvider.instance.get();
+ log.debug("Token is : "+token);
+ if(token==null) throw new Exception("Security Token is null");
+ AuthorizationEntry entry = authorizationService().get(token);
+ return entry.getContext();
+ }catch(Exception e ){
+ log.debug("Unable to resolve token, checking scope provider..",e);
+ return ScopeProvider.instance.get();
+ }
+ }
+
+
+ public static String getCurrentCaller(){
+ try{
+ String token=SecurityTokenProvider.instance.get();
+ log.debug("Token is : "+token);
+ if(token==null) throw new Exception("Security Token is null");
+ AuthorizationEntry entry = authorizationService().get(token);
+ return entry.getClientInfo().getId();
+ }catch(Exception e ){
+ log.debug("Unable to resolve token, checking scope provider..",e);
+ return "Unidentified data-transfer user";
+ }
+ }
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/Files.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/Files.java
new file mode 100644
index 0000000..b730201
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/Files.java
@@ -0,0 +1,48 @@
+package org.gcube.application.geoportal.common.utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.file.Paths;
+
+public class Files {
+
+ public static File getFileFromResources(String fileName) {
+
+ ClassLoader classLoader =Files.class.getClassLoader();
+
+ URL resource = classLoader.getResource(fileName);
+ if (resource == null) {
+ throw new IllegalArgumentException("file is not found!");
+ } else {
+ return new File(resource.getFile());
+ }
+
+ }
+
+
+ public static String readFileAsString(String path, Charset encoding)
+ throws IOException
+ {
+ byte[] encoded = java.nio.file.Files.readAllBytes(Paths.get(path));
+ return new String(encoded, encoding);
+ }
+
+
+ public static String getName(String path) {
+
+ return path.substring((path.contains(File.separator)?path.lastIndexOf(File.separator)+1:0)
+ ,(path.contains(".")?path.lastIndexOf("."):path.length()));
+
+ }
+
+ public static String fixFilename(String toFix) {
+ if(toFix.contains(".")) {
+ String prefix=toFix.substring(toFix.lastIndexOf("."));
+ toFix=toFix.substring(0,toFix.lastIndexOf("."));
+ return toFix.toLowerCase().replaceAll("[\\*\\+\\/\\\\ \\[\\]\\(\\)\\.\\\"\\:\\;\\|]","_")+prefix;
+ }
+ return toFix.toLowerCase().replaceAll("[\\*\\+\\/\\\\ \\[\\]\\(\\)\\.\\\"\\:\\;\\|]","_");
+ }
+}
diff --git a/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/StorageUtils.java b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/StorageUtils.java
new file mode 100644
index 0000000..84ecb52
--- /dev/null
+++ b/geoportal-common/src/main/java/org/gcube/application/geoportal/common/utils/StorageUtils.java
@@ -0,0 +1,55 @@
+package org.gcube.application.geoportal.common.utils;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.UUID;
+
+import org.gcube.application.geoportal.common.rest.InterfaceConstants;
+import org.gcube.application.geoportal.common.rest.TempFile;
+import org.gcube.contentmanagement.blobstorage.service.IClient;
+import org.gcube.contentmanagement.blobstorage.transport.backend.RemoteBackendException;
+import org.gcube.contentmanager.storageclient.wrapper.AccessType;
+import org.gcube.contentmanager.storageclient.wrapper.MemoryType;
+import org.gcube.contentmanager.storageclient.wrapper.StorageClient;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class StorageUtils {
+
+ public static final IClient getClient(){
+ return new StorageClient(InterfaceConstants.SERVICE_CLASS, InterfaceConstants.SERVICE_NAME, ContextUtils.getCurrentCaller(), AccessType.SHARED, MemoryType.VOLATILE).getClient();
+ }
+
+ private IClient client;
+ public StorageUtils() {
+ client=getClient();
+ }
+
+ //return Id
+ public TempFile putOntoStorage(InputStream source,String filename) throws RemoteBackendException, FileNotFoundException{
+ log.debug("Uploading source "+filename);
+ String id=client.put(true).LFile(source).RFile(getUniqueString());
+ return new TempFile(id,filename);
+ }
+
+ public static final boolean checkStorageId(String id){
+ return getClient().getHttpUrl().RFile(id)!=null;
+ }
+
+ public static final String getUrlById(String id){
+ IClient client=getClient();
+ log.debug("Id is "+id);
+ return client.getHttpUrl().RFile(id);
+ }
+
+ public static final void removeById(String id){
+ IClient client=getClient();
+ client.remove().RFile(id);
+ }
+
+
+ public static final String getUniqueString(){
+ return UUID.randomUUID().toString();
+ }
+}
diff --git a/geoportal-common/src/test/java/org/gcube/application/geoportal/common/model/PathsTest.java b/geoportal-common/src/test/java/org/gcube/application/geoportal/common/model/PathsTest.java
new file mode 100644
index 0000000..01b3295
--- /dev/null
+++ b/geoportal-common/src/test/java/org/gcube/application/geoportal/common/model/PathsTest.java
@@ -0,0 +1,67 @@
+package org.gcube.application.geoportal.common.model;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.UUID;
+
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.legacy.Concessione.Paths;
+import org.gcube.application.geoportal.common.model.legacy.LayerConcessione;
+import org.gcube.application.geoportal.common.model.legacy.RelazioneScavo;
+import org.gcube.application.geoportal.common.model.legacy.UploadedImage;
+import org.junit.Test;
+
+
+public class PathsTest {
+
+
+ @Test
+ public void embeddedPaths() {
+ Concessione c=TestModel.prepareConcessione();
+ c=TestModel.setIds(c);
+
+
+
+ LayerConcessione p=(LayerConcessione) c.getContentByPath(Paths.POSIZIONAMENTO);
+ assertEquals(c.getPosizionamentoScavo(), p);
+
+ RelazioneScavo rel=(RelazioneScavo) c.getContentByPath(Paths.RELAZIONE);
+ assertEquals(c.getRelazioneScavo(), rel);
+
+ for(int i=0;i0);
+
+ }
+
+ @Test
+ public void readConcessione() throws JsonProcessingException, IOException {
+ Concessione concessione=mapper.readerFor(Concessione.class).readValue(
+ Files.getFileFromResources("Concessione.json"));
+ System.out.println("Concessione is "+concessione.toString());
+
+ }
+
+ @Test
+ public void generic() throws JsonProcessingException, IOException {
+ Concessione conc=TestModel.prepareConcessione();
+ conc.validate();
+ full(conc);
+ }
+
+
+ public void full(Object obj) throws JsonProcessingException, IOException {
+ String asString=mapper.writeValueAsString(obj);
+ Object other=mapper.readerFor(obj.getClass()).readValue(asString);
+
+ }
+}
diff --git a/geoportal-common/src/test/java/org/gcube/application/geoportal/common/model/TestModel.java b/geoportal-common/src/test/java/org/gcube/application/geoportal/common/model/TestModel.java
new file mode 100644
index 0000000..8bce974
--- /dev/null
+++ b/geoportal-common/src/test/java/org/gcube/application/geoportal/common/model/TestModel.java
@@ -0,0 +1,130 @@
+package org.gcube.application.geoportal.common.model;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.UUID;
+
+import org.gcube.application.geoportal.common.model.legacy.*;
+
+public class TestModel {
+
+ private static final String rnd() {
+ return UUID.randomUUID().toString().replace("-", "_");
+ }
+
+
+ public static final Concessione setIds(Concessione c) {
+ c.setMongo_id(rnd());
+ c.getRelazioneScavo().setMongo_id(rnd());
+ c.getPosizionamentoScavo().setMongo_id(rnd());
+ c.getPianteFineScavo().forEach((LayerConcessione l)->{l.setMongo_id(rnd());});
+ c.getImmaginiRappresentative().forEach((UploadedImage i)->{i.setMongo_id(rnd());});
+ return c;
+ }
+
+ public static Concessione prepareEmptyConcessione() {
+ Concessione concessione=new Concessione();
+
+ // Generic fields
+
+ // Concessione fields
+
+
+
+
+ concessione.setNome("MONGO Italia, forse, ma su ");
+ concessione.setIntroduzione("This is my MONGO project");
+ concessione.setDescrizioneContenuto("It contains this and that");
+
+ concessione.setAuthors(Arrays.asList(new String[] {"Some one","Some, oneelse"}));
+
+ concessione.setContributore("Contrib 1");
+ concessione.setTitolari(Arrays.asList(new String[] {"Some one","Some, oneelse"}));
+ concessione.setResponsabile("Someone");
+ concessione.setEditore("Editore");
+
+ concessione.setFontiFinanziamento(Arrays.asList(new String[] {"Big pharma","Pentagon"}));
+
+
+ concessione.setSoggetto(Arrays.asList(new String[] {"Research Excavation","Archeology"}));
+
+
+ concessione.setDataInizioProgetto(LocalDateTime.now());
+ concessione.setDataFineProgetto(LocalDateTime.now());
+
+ concessione.setLicenzaID("CC-BY");
+
+ concessione.setTitolareLicenza(Arrays.asList(new String[] {"Qualcun altro"}));
+ concessione.setTitolareCopyright(Arrays.asList(new String[] {"Chiedilo in giro"}));
+
+ concessione.setParoleChiaveLibere(Arrays.asList(new String[] {"Robba","Stuff"}));
+ concessione.setParoleChiaveICCD(Arrays.asList(new String[] {"vattelapesca","somthing something"}));
+
+
+ concessione.setCentroidLat(43.0); //N-S
+ concessione.setCentroidLong(9.0); //E-W
+
+ return concessione;
+ }
+
+ public static Concessione prepareConcessione() {
+
+ Concessione concessione=prepareEmptyConcessione();
+
+
+
+ // Attachments
+
+ // Relazione scavo
+ RelazioneScavo relScavo=new RelazioneScavo();
+
+ relScavo.setResponsabili(concessione.getAuthors());
+
+ // Abstract
+ AbstractRelazione abstractRel=new AbstractRelazione();
+ abstractRel.setAbstractEng("This is the abstract");
+ abstractRel.setAbstractIta("Abstract ita");
+ concessione.setAbstractRelazione(abstractRel);
+
+
+
+ concessione.setRelazioneScavo(relScavo);
+ //Immagini rappresentative
+ ArrayList imgs=new ArrayList<>();
+ for(int i=0;i<5;i++) {
+ UploadedImage img=new UploadedImage();
+ img.setTitolo("My image number "+i);
+ img.setDidascalia("You can see my image number "+i);
+ img.setFormat("TIFF");
+ img.setCreationTime(LocalDateTime.now());
+ img.setResponsabili(concessione.getAuthors());
+ imgs.add(img);
+
+ }
+ concessione.setImmaginiRappresentative(imgs);
+ //Posizionamento
+ LayerConcessione posizionamento=new LayerConcessione();
+ posizionamento.setValutazioneQualita("Secondo me si");
+ posizionamento.setMetodoRaccoltaDati("Fattobbene");
+ posizionamento.setScalaAcquisizione("1:10000");
+ posizionamento.setAuthors(concessione.getAuthors());
+ concessione.setPosizionamentoScavo(posizionamento);
+
+ // Piante fine scavo
+ ArrayList piante=new ArrayList();
+ for(int i=0;i<4;i++) {
+ LayerConcessione pianta=new LayerConcessione();
+ pianta.setValutazioneQualita("Secondo me si");
+ pianta.setMetodoRaccoltaDati("Fattobbene");
+ pianta.setScalaAcquisizione("1:10000");
+ pianta.setAuthors(concessione.getAuthors());
+ pianta.setPolicy(AccessPolicy.RESTRICTED);
+ piante.add(pianta);
+ }
+ concessione.setPianteFineScavo(piante);
+
+ return concessione;
+ }
+
+}
diff --git a/geoportal-common/src/test/resources/Concessione.json b/geoportal-common/src/test/resources/Concessione.json
new file mode 100644
index 0000000..f17b3c3
--- /dev/null
+++ b/geoportal-common/src/test/resources/Concessione.json
@@ -0,0 +1,747 @@
+{
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "centroidLat": 43.0,
+ "centroidLong": 9.0,
+ "contributore": "Contrib 1",
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "creationUser": "NO NAME",
+ "dataFineProgetto": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 17,
+ 6000000
+ ],
+ "dataInizioProgetto": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 16,
+ 994000000
+ ],
+ "descrizioneContenuto": "It contains this and that",
+ "editore": "Editore",
+ "folderId": "5f14252f-55df-4c9a-94d9-9ad190efbe6a",
+ "fontiFinanziamento": [
+ "Big pharma",
+ "Pentagon"
+ ],
+ "genericContent": [],
+ "id": 8,
+ "immaginiRappresentative": [
+ {
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 187,
+ "link": "https://data.dev.d4science.org/shub/E_VGFQSExUR1BmdzVHNjI5ZjFJeXE1TUFpWEkxUGllelIyWVZndndKZ3pBaGNPWlNGczdFaUNtMHVZaEd0dXc2Rw==",
+ "mimetype": "image/png",
+ "storageID": "6765deab-b157-494f-83e2-299032e1904c",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 35,
+ 177000000
+ ],
+ "didascalia": "You can see my image number 0",
+ "format": "TIFF",
+ "id": 67,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "My image number 0",
+ "type": "UploadedImage"
+ },
+ {
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 188,
+ "link": "https://data.dev.d4science.org/shub/E_NDVyQnBiMFJ1VDliYS83eEJvYS9vb1JrZ2tQN2orY3ZXNUJia25McFFtNlMrSS91NHNBN3pPVUNzTGN2aE9JOQ==",
+ "mimetype": "image/png",
+ "storageID": "4b4fb9f9-b96d-485d-80c9-713fad8a5c9b",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 35,
+ 177000000
+ ],
+ "didascalia": "You can see my image number 1",
+ "format": "TIFF",
+ "id": 68,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "My image number 1",
+ "type": "UploadedImage"
+ },
+ {
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 189,
+ "link": "https://data.dev.d4science.org/shub/E_YWw0TXVKa29KZFJOeDMwVlRDc29xMW0zSExYdGRJdmxZWEtJSGRVZ3ZBRVEwTnc1cEdMNG1iVVRBN2JDVG9WYQ==",
+ "mimetype": "image/png",
+ "storageID": "2690d6bc-2833-4797-81bb-1c1865f34f34",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 35,
+ 177000000
+ ],
+ "didascalia": "You can see my image number 2",
+ "format": "TIFF",
+ "id": 69,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "My image number 2",
+ "type": "UploadedImage"
+ },
+ {
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 190,
+ "link": "https://data.dev.d4science.org/shub/E_TU9ha0lGMTRhTDl6S2IzWDNmUWROVXZjZzJiSmNrS1BjZ3gycUJvVEI2b0ZDaGxuK1dUWmlsNW1DZE1ESUJPbA==",
+ "mimetype": "image/png",
+ "storageID": "244b0fe0-8f53-469a-9c5e-ac63e37d4622",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 35,
+ 177000000
+ ],
+ "didascalia": "You can see my image number 3",
+ "format": "TIFF",
+ "id": 70,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "My image number 3",
+ "type": "UploadedImage"
+ },
+ {
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 191,
+ "link": "https://data.dev.d4science.org/shub/E_NXZYZnV3RlFTYzRWOTBOMWt0cmFtVUtTU20xWTBQb3daRVV6RU8zTDc5RU9USnZVL3Y1VmpRNHNaajMyelVTMQ==",
+ "mimetype": "image/png",
+ "storageID": "6fab2082-08af-4899-9730-462b011b517d",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 35,
+ 177000000
+ ],
+ "didascalia": "You can see my image number 4",
+ "format": "TIFF",
+ "id": 71,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "My image number 4",
+ "type": "UploadedImage"
+ }
+ ],
+ "introduzione": "This is my project",
+ "lastUpdateTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "lastUpdateUser": "NO NAME",
+ "licenzaID": "CC-BY",
+ "nome": "Italia, forse",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "pianteFineScavo": [
+ {
+ "abstractSection": "Planimetria georeferenziata dell'area indagata al termine delle attività",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 196,
+ "link": "https://data.dev.d4science.org/shub/E_aTZqVlNzRlRVSUFVZXhBNVp2bDdYMDlRTnNwVlRGRXNqMlI3MkxTdXlrWVFJeDF0L3pLemtaTDBwWFA3TVJKUw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "debd7027-56fe-4cff-ae87-b0df94421035",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 193,
+ "link": "https://data.dev.d4science.org/shub/E_UWpOTUYvRTRvV2hCYS8wQ3BaSG5GdG00MXdyeVg2M3dnZk5ZSEd3a0RxdWs0YUJTalFMK1JJQ2x5dFlySTZ4Lw==",
+ "mimetype": "text/plain",
+ "storageID": "d44b073f-6828-4dfd-a1fc-1d5eed93abc5",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 195,
+ "link": "https://data.dev.d4science.org/shub/E_SXUrWi9OZW9MMXpTSzdraGhveXNpaVo3b0Fid1loc1BEdnlqVmdGaWd1U2czb1YxdDhPeHNBWmovV21xRmxXVw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "4e184a77-915b-4ebd-bcb8-08ac8138069b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 194,
+ "link": "https://data.dev.d4science.org/shub/E_RFZ0V2NUaDB5bCt4bGo5MnByZXZoRW5rWnRSWXFoRzdnQmxqTHlYSlhCeTU5RHZ3S2Ywa0ZDUCtUOCtZK3VkdQ==",
+ "mimetype": "text/plain",
+ "storageID": "f0f1fff4-6ee4-47c5-92be-2fd2c1ab5687",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 192,
+ "link": "https://data.dev.d4science.org/shub/E_cFZ6MFgvR1gzWmx0d2hvRmVnVTBQTEszdG1seEN3d2tBcHNsYkFXVlhKRUtucHZKb24xakEwa1IwQWJCTjc3cA==",
+ "mimetype": "application/x-dbf",
+ "storageID": "2c542d5a-ca89-42bb-87c9-1bceb8f0f03b",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "bbox": {
+ "maxLat": 90.0,
+ "maxLong": 180.0,
+ "minLat": -90.0,
+ "minLong": -180.0
+ },
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 72,
+ "layerID": null,
+ "layerName": null,
+ "layerUUID": null,
+ "licenseID": "CC-BY",
+ "metodoRaccoltaDati": "Fattobbene",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "policy": "RESTRICTED",
+ "record": null,
+ "responsabile": "Someone",
+ "scalaAcquisizione": "1:10000",
+ "subTopic": "Archeology",
+ "titolo": "Italia, forse pianta fine scavo",
+ "topicCategory": "Society",
+ "type": "LayerConcessione",
+ "valutazioneQualita": "Secondo me si",
+ "wmsLink": null
+ },
+ {
+ "abstractSection": "Planimetria georeferenziata dell'area indagata al termine delle attività",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 198,
+ "link": "https://data.dev.d4science.org/shub/E_UWpOTUYvRTRvV2hCYS8wQ3BaSG5GdG00MXdyeVg2M3dnZk5ZSEd3a0RxdWs0YUJTalFMK1JJQ2x5dFlySTZ4Lw==",
+ "mimetype": "text/plain",
+ "storageID": "d44b073f-6828-4dfd-a1fc-1d5eed93abc5",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 197,
+ "link": "https://data.dev.d4science.org/shub/E_cFZ6MFgvR1gzWmx0d2hvRmVnVTBQTEszdG1seEN3d2tBcHNsYkFXVlhKRUtucHZKb24xakEwa1IwQWJCTjc3cA==",
+ "mimetype": "application/x-dbf",
+ "storageID": "2c542d5a-ca89-42bb-87c9-1bceb8f0f03b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 200,
+ "link": "https://data.dev.d4science.org/shub/E_SXUrWi9OZW9MMXpTSzdraGhveXNpaVo3b0Fid1loc1BEdnlqVmdGaWd1U2czb1YxdDhPeHNBWmovV21xRmxXVw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "4e184a77-915b-4ebd-bcb8-08ac8138069b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 199,
+ "link": "https://data.dev.d4science.org/shub/E_RFZ0V2NUaDB5bCt4bGo5MnByZXZoRW5rWnRSWXFoRzdnQmxqTHlYSlhCeTU5RHZ3S2Ywa0ZDUCtUOCtZK3VkdQ==",
+ "mimetype": "text/plain",
+ "storageID": "f0f1fff4-6ee4-47c5-92be-2fd2c1ab5687",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 201,
+ "link": "https://data.dev.d4science.org/shub/E_aTZqVlNzRlRVSUFVZXhBNVp2bDdYMDlRTnNwVlRGRXNqMlI3MkxTdXlrWVFJeDF0L3pLemtaTDBwWFA3TVJKUw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "debd7027-56fe-4cff-ae87-b0df94421035",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "bbox": {
+ "maxLat": 90.0,
+ "maxLong": 180.0,
+ "minLat": -90.0,
+ "minLong": -180.0
+ },
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 73,
+ "layerID": null,
+ "layerName": null,
+ "layerUUID": null,
+ "licenseID": "CC-BY",
+ "metodoRaccoltaDati": "Fattobbene",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "policy": "RESTRICTED",
+ "record": null,
+ "responsabile": "Someone",
+ "scalaAcquisizione": "1:10000",
+ "subTopic": "Archeology",
+ "titolo": "Italia, forse pianta fine scavo",
+ "topicCategory": "Society",
+ "type": "LayerConcessione",
+ "valutazioneQualita": "Secondo me si",
+ "wmsLink": null
+ },
+ {
+ "abstractSection": "Planimetria georeferenziata dell'area indagata al termine delle attività",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 202,
+ "link": "https://data.dev.d4science.org/shub/E_cFZ6MFgvR1gzWmx0d2hvRmVnVTBQTEszdG1seEN3d2tBcHNsYkFXVlhKRUtucHZKb24xakEwa1IwQWJCTjc3cA==",
+ "mimetype": "application/x-dbf",
+ "storageID": "2c542d5a-ca89-42bb-87c9-1bceb8f0f03b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 204,
+ "link": "https://data.dev.d4science.org/shub/E_RFZ0V2NUaDB5bCt4bGo5MnByZXZoRW5rWnRSWXFoRzdnQmxqTHlYSlhCeTU5RHZ3S2Ywa0ZDUCtUOCtZK3VkdQ==",
+ "mimetype": "text/plain",
+ "storageID": "f0f1fff4-6ee4-47c5-92be-2fd2c1ab5687",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 205,
+ "link": "https://data.dev.d4science.org/shub/E_SXUrWi9OZW9MMXpTSzdraGhveXNpaVo3b0Fid1loc1BEdnlqVmdGaWd1U2czb1YxdDhPeHNBWmovV21xRmxXVw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "4e184a77-915b-4ebd-bcb8-08ac8138069b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 203,
+ "link": "https://data.dev.d4science.org/shub/E_UWpOTUYvRTRvV2hCYS8wQ3BaSG5GdG00MXdyeVg2M3dnZk5ZSEd3a0RxdWs0YUJTalFMK1JJQ2x5dFlySTZ4Lw==",
+ "mimetype": "text/plain",
+ "storageID": "d44b073f-6828-4dfd-a1fc-1d5eed93abc5",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 206,
+ "link": "https://data.dev.d4science.org/shub/E_aTZqVlNzRlRVSUFVZXhBNVp2bDdYMDlRTnNwVlRGRXNqMlI3MkxTdXlrWVFJeDF0L3pLemtaTDBwWFA3TVJKUw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "debd7027-56fe-4cff-ae87-b0df94421035",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "bbox": {
+ "maxLat": 90.0,
+ "maxLong": 180.0,
+ "minLat": -90.0,
+ "minLong": -180.0
+ },
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 74,
+ "layerID": null,
+ "layerName": null,
+ "layerUUID": null,
+ "licenseID": "CC-BY",
+ "metodoRaccoltaDati": "Fattobbene",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "policy": "RESTRICTED",
+ "record": null,
+ "responsabile": "Someone",
+ "scalaAcquisizione": "1:10000",
+ "subTopic": "Archeology",
+ "titolo": "Italia, forse pianta fine scavo",
+ "topicCategory": "Society",
+ "type": "LayerConcessione",
+ "valutazioneQualita": "Secondo me si",
+ "wmsLink": null
+ },
+ {
+ "abstractSection": "Planimetria georeferenziata dell'area indagata al termine delle attività",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 209,
+ "link": "https://data.dev.d4science.org/shub/E_RFZ0V2NUaDB5bCt4bGo5MnByZXZoRW5rWnRSWXFoRzdnQmxqTHlYSlhCeTU5RHZ3S2Ywa0ZDUCtUOCtZK3VkdQ==",
+ "mimetype": "text/plain",
+ "storageID": "f0f1fff4-6ee4-47c5-92be-2fd2c1ab5687",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 211,
+ "link": "https://data.dev.d4science.org/shub/E_aTZqVlNzRlRVSUFVZXhBNVp2bDdYMDlRTnNwVlRGRXNqMlI3MkxTdXlrWVFJeDF0L3pLemtaTDBwWFA3TVJKUw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "debd7027-56fe-4cff-ae87-b0df94421035",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 207,
+ "link": "https://data.dev.d4science.org/shub/E_cFZ6MFgvR1gzWmx0d2hvRmVnVTBQTEszdG1seEN3d2tBcHNsYkFXVlhKRUtucHZKb24xakEwa1IwQWJCTjc3cA==",
+ "mimetype": "application/x-dbf",
+ "storageID": "2c542d5a-ca89-42bb-87c9-1bceb8f0f03b",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 208,
+ "link": "https://data.dev.d4science.org/shub/E_UWpOTUYvRTRvV2hCYS8wQ3BaSG5GdG00MXdyeVg2M3dnZk5ZSEd3a0RxdWs0YUJTalFMK1JJQ2x5dFlySTZ4Lw==",
+ "mimetype": "text/plain",
+ "storageID": "d44b073f-6828-4dfd-a1fc-1d5eed93abc5",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 210,
+ "link": "https://data.dev.d4science.org/shub/E_SXUrWi9OZW9MMXpTSzdraGhveXNpaVo3b0Fid1loc1BEdnlqVmdGaWd1U2czb1YxdDhPeHNBWmovV21xRmxXVw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "4e184a77-915b-4ebd-bcb8-08ac8138069b",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "bbox": {
+ "maxLat": 90.0,
+ "maxLong": 180.0,
+ "minLat": -90.0,
+ "minLong": -180.0
+ },
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 75,
+ "layerID": null,
+ "layerName": null,
+ "layerUUID": null,
+ "licenseID": "CC-BY",
+ "metodoRaccoltaDati": "Fattobbene",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "policy": "RESTRICTED",
+ "record": null,
+ "responsabile": "Someone",
+ "scalaAcquisizione": "1:10000",
+ "subTopic": "Archeology",
+ "titolo": "Italia, forse pianta fine scavo",
+ "topicCategory": "Society",
+ "type": "LayerConcessione",
+ "valutazioneQualita": "Secondo me si",
+ "wmsLink": null
+ }
+ ],
+ "policy": "OPEN",
+ "posizionamentoScavo": {
+ "abstractSection": "Posizionamento topografico georeferenziato dell’area interessata dalle indagini",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 214,
+ "link": "https://data.dev.d4science.org/shub/E_UjJoQkw2a0VlR3djQnVYMlNaME40VkdLL3pxV21DNmRrWXVZUlFhMk53aXJORVJmM29pcHpPdVc4aHZLUTRwcg==",
+ "mimetype": "text/plain",
+ "storageID": "fac45dad-4840-4fda-b613-0bfd831d8720",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 213,
+ "link": "https://data.dev.d4science.org/shub/E_T0lsR09LbVdqMExWT1ZwZWpZSW4zUXBqZlV2bCt6d3hMbnc5UDBvRW45eENONzB4cXNtZ216cXZFNWVzdjU0eg==",
+ "mimetype": "text/plain",
+ "storageID": "d599e90f-26e0-4b27-b85e-bedd286ff2d7",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 215,
+ "link": "https://data.dev.d4science.org/shub/E_U2NhMXUvMzRycE9YYkRmbHphdC82QlJJN2FEeVd0Y1FEQmxwSjNmcWRTUDZoZHhVQ1VPdjRMVVdOVDcxNTh5Yw==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "f1080875-7f01-4658-9758-9388262ad12c",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 216,
+ "link": "https://data.dev.d4science.org/shub/E_RlBWRW5lUG9nbncxSC9ZQlRURmFSeTQ3Q0ZqdDhOK2luV01uWjUxMTZ4OHREa29US2t3K21RblpjaXFMTWtSSA==",
+ "mimetype": "application/x-shapefile",
+ "storageID": "6b7eeb40-0cd1-4fe5-97b5-b7091e6b7531",
+ "type": "WorkspaceContent"
+ },
+ {
+ "associated": null,
+ "id": 212,
+ "link": "https://data.dev.d4science.org/shub/E_aHQxcDhoRGN0QXdXZTkwUmtKRlJsUFVqWjM4STY3U0JkVGU1L3l1a2t5WkhFWlc4blpoa0QxaDVRaHZCOXR2Nw==",
+ "mimetype": "application/x-dbf",
+ "storageID": "9af11436-2241-4a03-a95b-96849272bc25",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "authors": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "bbox": {
+ "maxLat": 90.0,
+ "maxLong": 180.0,
+ "minLat": -90.0,
+ "minLong": -180.0
+ },
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 76,
+ "layerID": null,
+ "layerName": null,
+ "layerUUID": null,
+ "licenseID": "CC-BY",
+ "metodoRaccoltaDati": "Fattobbene",
+ "paroleChiaveICCD": [
+ "vattelapesca",
+ "somthing something"
+ ],
+ "paroleChiaveLibere": [
+ "Robba",
+ "Stuff"
+ ],
+ "policy": "OPEN",
+ "record": null,
+ "responsabile": "Someone",
+ "scalaAcquisizione": "1:10000",
+ "subTopic": "Archeology",
+ "titolo": "Italia, forse posizionamento scavo",
+ "topicCategory": "Society",
+ "type": "LayerConcessione",
+ "valutazioneQualita": "Secondo me si",
+ "wmsLink": null
+ },
+ "recordType": "CONCESSIONE",
+ "relazioneScavo": {
+ "abstractSection": "simple abstract section",
+ "actualContent": [
+ {
+ "associated": null,
+ "id": 217,
+ "link": "https://data.dev.d4science.org/shub/E_a0JGWWNsY0tFc29CVC8xUW1ROUJhMnVaaWwxNk5TTk5TRlgvQW1tbkpLdDBuNFU3Rkg2VmlFVW53TEUzaEM4aA==",
+ "mimetype": "application/pdf",
+ "storageID": "e0cd721a-89e4-437d-9fba-2bfc197cb4c1",
+ "type": "WorkspaceContent"
+ }
+ ],
+ "creationTime": [
+ 2020,
+ 11,
+ 26,
+ 13,
+ 14,
+ 37,
+ 342000000
+ ],
+ "id": 77,
+ "licenseID": "CC-BY",
+ "policy": "OPEN",
+ "record": null,
+ "responsabili": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolo": "Italia, forse relazione di scavo",
+ "type": "RelazioneScavo"
+ },
+ "responsabile": "Someone",
+ "risorseCorrelate": [],
+ "soggetto": [
+ "Research Excavation",
+ "Archeology"
+ ],
+ "titolareCopyright": ["Chiedilo in giro"],
+ "titolareLicenza": ["Qualcun altro"],
+ "titolari": [
+ "Some one",
+ "Some, oneelse"
+ ],
+ "version": "1.0.0"
+}
\ No newline at end of file
diff --git a/geoportal-common/src/test/resources/ProfileConcessioni.json b/geoportal-common/src/test/resources/ProfileConcessioni.json
new file mode 100644
index 0000000..ed42208
--- /dev/null
+++ b/geoportal-common/src/test/resources/ProfileConcessioni.json
@@ -0,0 +1,29 @@
+{
+ "name" : "Concessioni Profile",
+ "_id" : "",
+ "fields" :[
+ { "name" : "introduzione", "label" : "Introduzione", "type" : "STRING"},
+ { "label" : "Descrizione Contenuto", "type" : "STRING"},
+ { "label" : "Autori", "type" : "STRING", "cardinality" : "MULTIPLE"},
+ { "label" : "Contributore", "type" : "STRING"},
+ { "label" : "Titolari", "type" : "STRING", "cardinality" : "MULTIPLE"},
+
+ { "name":"relazioneScavo", "label" : "Relazione di Scavo", "type" : "DOCUMENT"},
+ { "name":"posizionameno",
+ "label" : "Posizionamento Scavo",
+ "type" : "DOCUMENT",
+ "fields":[
+ { "label" : "Descrizione Contenuto", "type" : "STRING"},
+ { "label" : "Autori", "type" : "STRING", "cardinality" : "MULTIPLE"},
+ { "label" : "Contributore", "type" : "STRING"}
+ ]
+ }
+ ],
+
+ "validators" : [
+ {"name":"Validator Concessioni",
+ "type":"JAVA",
+ "qName":"org.gcube.application.concessioni.Validator"}
+ ]
+
+}
\ No newline at end of file
diff --git a/geoportal-service/CHANGELOG.md b/geoportal-service/CHANGELOG.md
new file mode 100644
index 0000000..e0c69ed
--- /dev/null
+++ b/geoportal-service/CHANGELOG.md
@@ -0,0 +1,36 @@
+This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+# Changelog for org.gcube.application.geoportal-service
+
+## [v1.0.6-SNAPSHOT] 2021-09-20
+Refactored repositories
+
+
+## [v1.0.5-SNAPSHOT] 2021-07-23
+Upgrade to gcube-smartgears-bom 2.1.0
+Fix register postgis table layer
+Added PostgisIndexRecordManager
+
+## [v1.0.4] 2020-11-11
+Mongo integration with Concessione
+Project interface
+TempFile management
+WorkspaceContent and publication for Concessioni-over-mongo
+
+## [v1.0.3] 2020-11-11
+Fixed HTTP method
+
+## [v1.0.2] 2020-11-11
+Delete method
+Excluded upper bound release gCube 5
+
+
+## [v1.0.1] 2020-11-11
+
+Project interface
+
+## [v1.0.0] 2020-11-11
+
+First release
+
+
diff --git a/geoportal-service/FUNDING.md b/geoportal-service/FUNDING.md
new file mode 100644
index 0000000..9e48b94
--- /dev/null
+++ b/geoportal-service/FUNDING.md
@@ -0,0 +1,26 @@
+# Acknowledgments
+
+The projects leading to this software have received funding from a series of European Union programmes including:
+
+- the Sixth Framework Programme for Research and Technological Development
+ - [DILIGENT](https://cordis.europa.eu/project/id/004260) (grant no. 004260).
+- the Seventh Framework Programme for research, technological development and demonstration
+ - [D4Science](https://cordis.europa.eu/project/id/212488) (grant no. 212488);
+ - [D4Science-II](https://cordis.europa.eu/project/id/239019) (grant no.239019);
+ - [ENVRI](https://cordis.europa.eu/project/id/283465) (grant no. 283465);
+ - [iMarine](https://cordis.europa.eu/project/id/283644) (grant no. 283644);
+ - [EUBrazilOpenBio](https://cordis.europa.eu/project/id/288754) (grant no. 288754).
+- the H2020 research and innovation programme
+ - [SoBigData](https://cordis.europa.eu/project/id/654024) (grant no. 654024);
+ - [PARTHENOS](https://cordis.europa.eu/project/id/654119) (grant no. 654119);
+ - [EGI-Engage](https://cordis.europa.eu/project/id/654142) (grant no. 654142);
+ - [ENVRI PLUS](https://cordis.europa.eu/project/id/654182) (grant no. 654182);
+ - [BlueBRIDGE](https://cordis.europa.eu/project/id/675680) (grant no. 675680);
+ - [PerformFISH](https://cordis.europa.eu/project/id/727610) (grant no. 727610);
+ - [AGINFRA PLUS](https://cordis.europa.eu/project/id/731001) (grant no. 731001);
+ - [DESIRA](https://cordis.europa.eu/project/id/818194) (grant no. 818194);
+ - [ARIADNEplus](https://cordis.europa.eu/project/id/823914) (grant no. 823914);
+ - [RISIS 2](https://cordis.europa.eu/project/id/824091) (grant no. 824091);
+ - [EOSC-Pillar](https://cordis.europa.eu/project/id/857650) (grant no. 857650);
+ - [Blue Cloud](https://cordis.europa.eu/project/id/862409) (grant no. 862409);
+ - [SoBigData-PlusPlus](https://cordis.europa.eu/project/id/871042) (grant no. 871042);
diff --git a/geoportal-service/LICENSE.md b/geoportal-service/LICENSE.md
new file mode 100644
index 0000000..3af0507
--- /dev/null
+++ b/geoportal-service/LICENSE.md
@@ -0,0 +1,312 @@
+# European Union Public Licence V. 1.1
+
+
+EUPL © the European Community 2007
+
+
+This European Union Public Licence (the “EUPL”) applies to the Work or Software
+(as defined below) which is provided under the terms of this Licence. Any use of
+the Work, other than as authorised under this Licence is prohibited (to the
+extent such use is covered by a right of the copyright holder of the Work).
+
+The Original Work is provided under the terms of this Licence when the Licensor
+(as defined below) has placed the following notice immediately following the
+copyright notice for the Original Work:
+
+Licensed under the EUPL V.1.1
+
+or has expressed by any other mean his willingness to license under the EUPL.
+
+
+
+## 1. Definitions
+
+In this Licence, the following terms have the following meaning:
+
+- The Licence: this Licence.
+
+- The Original Work or the Software: the software distributed and/or
+ communicated by the Licensor under this Licence, available as Source Code and
+ also as Executable Code as the case may be.
+
+- Derivative Works: the works or software that could be created by the Licensee,
+ based upon the Original Work or modifications thereof. This Licence does not
+ define the extent of modification or dependence on the Original Work required
+ in order to classify a work as a Derivative Work; this extent is determined by
+ copyright law applicable in the country mentioned in Article 15.
+
+- The Work: the Original Work and/or its Derivative Works.
+
+- The Source Code: the human-readable form of the Work which is the most
+ convenient for people to study and modify.
+
+- The Executable Code: any code which has generally been compiled and which is
+ meant to be interpreted by a computer as a program.
+
+- The Licensor: the natural or legal person that distributes and/or communicates
+ the Work under the Licence.
+
+- Contributor(s): any natural or legal person who modifies the Work under the
+ Licence, or otherwise contributes to the creation of a Derivative Work.
+
+- The Licensee or “You”: any natural or legal person who makes any usage of the
+ Software under the terms of the Licence.
+
+- Distribution and/or Communication: any act of selling, giving, lending,
+ renting, distributing, communicating, transmitting, or otherwise making
+ available, on-line or off-line, copies of the Work or providing access to its
+ essential functionalities at the disposal of any other natural or legal
+ person.
+
+
+
+## 2. Scope of the rights granted by the Licence
+
+The Licensor hereby grants You a world-wide, royalty-free, non-exclusive,
+sub-licensable licence to do the following, for the duration of copyright vested
+in the Original Work:
+
+- use the Work in any circumstance and for all usage, reproduce the Work, modify
+- the Original Work, and make Derivative Works based upon the Work, communicate
+- to the public, including the right to make available or display the Work or
+- copies thereof to the public and perform publicly, as the case may be, the
+- Work, distribute the Work or copies thereof, lend and rent the Work or copies
+- thereof, sub-license rights in the Work or copies thereof.
+
+Those rights can be exercised on any media, supports and formats, whether now
+known or later invented, as far as the applicable law permits so.
+
+In the countries where moral rights apply, the Licensor waives his right to
+exercise his moral right to the extent allowed by law in order to make effective
+the licence of the economic rights here above listed.
+
+The Licensor grants to the Licensee royalty-free, non exclusive usage rights to
+any patents held by the Licensor, to the extent necessary to make use of the
+rights granted on the Work under this Licence.
+
+
+
+## 3. Communication of the Source Code
+
+The Licensor may provide the Work either in its Source Code form, or as
+Executable Code. If the Work is provided as Executable Code, the Licensor
+provides in addition a machine-readable copy of the Source Code of the Work
+along with each copy of the Work that the Licensor distributes or indicates, in
+a notice following the copyright notice attached to the Work, a repository where
+the Source Code is easily and freely accessible for as long as the Licensor
+continues to distribute and/or communicate the Work.
+
+
+
+## 4. Limitations on copyright
+
+Nothing in this Licence is intended to deprive the Licensee of the benefits from
+any exception or limitation to the exclusive rights of the rights owners in the
+Original Work or Software, of the exhaustion of those rights or of other
+applicable limitations thereto.
+
+
+
+## 5. Obligations of the Licensee
+
+The grant of the rights mentioned above is subject to some restrictions and
+obligations imposed on the Licensee. Those obligations are the following:
+
+Attribution right: the Licensee shall keep intact all copyright, patent or
+trademarks notices and all notices that refer to the Licence and to the
+disclaimer of warranties. The Licensee must include a copy of such notices and a
+copy of the Licence with every copy of the Work he/she distributes and/or
+communicates. The Licensee must cause any Derivative Work to carry prominent
+notices stating that the Work has been modified and the date of modification.
+
+Copyleft clause: If the Licensee distributes and/or communicates copies of the
+Original Works or Derivative Works based upon the Original Work, this
+Distribution and/or Communication will be done under the terms of this Licence
+or of a later version of this Licence unless the Original Work is expressly
+distributed only under this version of the Licence. The Licensee (becoming
+Licensor) cannot offer or impose any additional terms or conditions on the Work
+or Derivative Work that alter or restrict the terms of the Licence.
+
+Compatibility clause: If the Licensee Distributes and/or Communicates Derivative
+Works or copies thereof based upon both the Original Work and another work
+licensed under a Compatible Licence, this Distribution and/or Communication can
+be done under the terms of this Compatible Licence. For the sake of this clause,
+“Compatible Licence” refers to the licences listed in the appendix attached to
+this Licence. Should the Licensee’s obligations under the Compatible Licence
+conflict with his/her obligations under this Licence, the obligations of the
+Compatible Licence shall prevail.
+
+Provision of Source Code: When distributing and/or communicating copies of the
+Work, the Licensee will provide a machine-readable copy of the Source Code or
+indicate a repository where this Source will be easily and freely available for
+as long as the Licensee continues to distribute and/or communicate the Work.
+
+Legal Protection: This Licence does not grant permission to use the trade names,
+trademarks, service marks, or names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the copyright notice.
+
+
+
+## 6. Chain of Authorship
+
+The original Licensor warrants that the copyright in the Original Work granted
+hereunder is owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each Contributor warrants that the copyright in the modifications he/she brings
+to the Work are owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each time You accept the Licence, the original Licensor and subsequent
+Contributors grant You a licence to their contributions to the Work, under the
+terms of this Licence.
+
+
+
+## 7. Disclaimer of Warranty
+
+The Work is a work in progress, which is continuously improved by numerous
+contributors. It is not a finished work and may therefore contain defects or
+“bugs” inherent to this type of software development.
+
+For the above reason, the Work is provided under the Licence on an “as is” basis
+and without warranties of any kind concerning the Work, including without
+limitation merchantability, fitness for a particular purpose, absence of defects
+or errors, accuracy, non-infringement of intellectual property rights other than
+copyright as stated in Article 6 of this Licence.
+
+This disclaimer of warranty is an essential part of the Licence and a condition
+for the grant of any rights to the Work.
+
+
+
+## 8. Disclaimer of Liability
+
+Except in the cases of wilful misconduct or damages directly caused to natural
+persons, the Licensor will in no event be liable for any direct or indirect,
+material or moral, damages of any kind, arising out of the Licence or of the use
+of the Work, including without limitation, damages for loss of goodwill, work
+stoppage, computer failure or malfunction, loss of data or any commercial
+damage, even if the Licensor has been advised of the possibility of such
+damage. However, the Licensor will be liable under statutory product liability
+laws as far such laws apply to the Work.
+
+
+
+## 9. Additional agreements
+
+While distributing the Original Work or Derivative Works, You may choose to
+conclude an additional agreement to offer, and charge a fee for, acceptance of
+support, warranty, indemnity, or other liability obligations and/or services
+consistent with this Licence. However, in accepting such obligations, You may
+act only on your own behalf and on your sole responsibility, not on behalf of
+the original Licensor or any other Contributor, and only if You agree to
+indemnify, defend, and hold each Contributor harmless for any liability incurred
+by, or claims asserted against such Contributor by the fact You have accepted
+any such warranty or additional liability.
+
+
+
+## 10. Acceptance of the Licence
+
+The provisions of this Licence can be accepted by clicking on an icon “I agree”
+placed under the bottom of a window displaying the text of this Licence or by
+affirming consent in any other similar way, in accordance with the rules of
+applicable law. Clicking on that icon indicates your clear and irrevocable
+acceptance of this Licence and all of its terms and conditions.
+
+Similarly, you irrevocably accept this Licence and all of its terms and
+conditions by exercising any rights granted to You by Article 2 of this Licence,
+such as the use of the Work, the creation by You of a Derivative Work or the
+Distribution and/or Communication by You of the Work or copies thereof.
+
+
+
+## 11. Information to the public
+
+In case of any Distribution and/or Communication of the Work by means of
+electronic communication by You (for example, by offering to download the Work
+from a remote location) the distribution channel or media (for example, a
+website) must at least provide to the public the information requested by the
+applicable law regarding the Licensor, the Licence and the way it may be
+accessible, concluded, stored and reproduced by the Licensee.
+
+
+
+## 12. Termination of the Licence
+
+The Licence and the rights granted hereunder will terminate automatically upon
+any breach by the Licensee of the terms of the Licence.
+
+Such a termination will not terminate the licences of any person who has
+received the Work from the Licensee under the Licence, provided such persons
+remain in full compliance with the Licence.
+
+
+
+## 13. Miscellaneous
+
+Without prejudice of Article 9 above, the Licence represents the complete
+agreement between the Parties as to the Work licensed hereunder.
+
+If any provision of the Licence is invalid or unenforceable under applicable
+law, this will not affect the validity or enforceability of the Licence as a
+whole. Such provision will be construed and/or reformed so as necessary to make
+it valid and enforceable.
+
+The European Commission may publish other linguistic versions and/or new
+versions of this Licence, so far this is required and reasonable, without
+reducing the scope of the rights granted by the Licence. New versions of the
+Licence will be published with a unique version number.
+
+All linguistic versions of this Licence, approved by the European Commission,
+have identical value. Parties can take advantage of the linguistic version of
+their choice.
+
+
+
+## 14. Jurisdiction
+
+Any litigation resulting from the interpretation of this License, arising
+between the European Commission, as a Licensor, and any Licensee, will be
+subject to the jurisdiction of the Court of Justice of the European Communities,
+as laid down in article 238 of the Treaty establishing the European Community.
+
+Any litigation arising between Parties, other than the European Commission, and
+resulting from the interpretation of this License, will be subject to the
+exclusive jurisdiction of the competent court where the Licensor resides or
+conducts its primary business.
+
+
+
+## 15. Applicable Law
+
+This Licence shall be governed by the law of the European Union country where
+the Licensor resides or has his registered office.
+
+This licence shall be governed by the Belgian law if:
+
+- a litigation arises between the European Commission, as a Licensor, and any
+- Licensee; the Licensor, other than the European Commission, has no residence
+- or registered office inside a European Union country.
+
+
+
+## Appendix
+
+
+
+“Compatible Licences” according to article 5 EUPL are:
+
+
+- GNU General Public License (GNU GPL) v. 2
+
+- Open Software License (OSL) v. 2.1, v. 3.0
+
+- Common Public License v. 1.0
+
+- Eclipse Public License v. 1.0
+
+- Cecill v. 2.0
+
diff --git a/geoportal-service/README.md b/geoportal-service/README.md
new file mode 100644
index 0000000..d20b2c8
--- /dev/null
+++ b/geoportal-service/README.md
@@ -0,0 +1,53 @@
+GeoPortal - Service
+--------------------------------------------------
+
+GeoPortal - Service is the main component operating a gCube GeoPortal. It is a SmartGears web application based on top of gCube SDI
+
+## Built with
+* [gCube SDI] (https://gcube.wiki.gcube-system.org/gcube/) - The gCube SDI
+* [gCube SmartGears] (https://gcube.wiki.gcube-system.org/gcube/SmartGears) - The gCube SmartGears framework
+* [OpenJDK](https://openjdk.java.net/) - The JDK used
+* [JAX-RS](https://github.com/eclipse-ee4j/jaxrs-api) - Java™ API for RESTful Web Services
+* [Jersey](https://jersey.github.io/) - JAX-RS runtime
+* [Maven](https://maven.apache.org/) - Dependency Management
+
+## Documentation
+
+Documentation can be found [here](https://gcube.wiki.gcube-system.org/gcube/GeoPortal).
+
+## Change log
+
+See [CHANGELOG.md](CHANGELOG.md).
+
+## License
+
+This project is licensed under the EUPL V.1.1 License - see the [LICENSE.md](LICENSE.md) file for details.
+
+## About the gCube Framework
+This software is part of the [gCubeFramework](https://www.gcube-system.org/ "gCubeFramework"): an
+open-source software toolkit used for building and operating Hybrid Data
+Infrastructures enabling the dynamic deployment of Virtual Research Environments
+by favouring the realisation of reuse oriented policies.
+
+The projects leading to this software have received funding from a series of European Union programmes including:
+
+- the Sixth Framework Programme for Research and Technological Development
+ - DILIGENT (grant no. 004260).
+- the Seventh Framework Programme for research, technological development and demonstration
+ - D4Science (grant no. 212488);
+ - D4Science-II (grant no.239019);
+ - ENVRI (grant no. 283465);
+ - iMarine(grant no. 283644);
+ - EUBrazilOpenBio (grant no. 288754).
+- the H2020 research and innovation programme
+ - SoBigData (grant no. 654024);
+ - PARTHENOS (grant no. 654119);
+ - EGIEngage (grant no. 654142);
+ - ENVRIplus (grant no. 654182);
+ - BlueBRIDGE (grant no. 675680);
+ - PerformFish (grant no. 727610);
+ - AGINFRAplus (grant no. 731001);
+ - DESIRA (grant no. 818194);
+ - ARIADNEplus (grant no. 823914);
+ - RISIS2 (grant no. 824091);
+
diff --git a/geoportal-service/pom.xml b/geoportal-service/pom.xml
new file mode 100644
index 0000000..afde409
--- /dev/null
+++ b/geoportal-service/pom.xml
@@ -0,0 +1,230 @@
+
+ 4.0.0
+ org.gcube.application
+ geoportal-service
+ 1.0.6-SNAPSHOT
+ Geoportal Service
+ war
+
+
+ org.gcube.application.cms
+ gcube-cms-suite
+ 1.0.0-SNAPSHOT
+
+
+
+ https://code-repo.d4science.org/gCubeSystem
+ 1.0
+
+
+
+
+
+
+ scm:git:${gitBaseUrl}/${project.artifactId}.git
+ scm:git:${gitBaseUrl}/${project.artifactId}.git
+ ${gitBaseUrl}/${project.artifactId}.git
+
+
+
+
+
+
+
+ org.gcube.distribution
+ gcube-smartgears-bom
+ 2.1.0
+ pom
+ import
+
+
+
+
+
+
+
+
+
+ org.gcube.core
+ common-smartgears
+
+
+
+
+
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+
+
+
+ org.glassfish.jersey.containers
+ jersey-container-servlet
+
+
+ org.javassist
+ javassist
+
+
+
+
+
+
+
+
+ org.gcube.application
+ geoportal-common
+ [1.0.0,2.0.0)
+
+
+
+
+
+ org.gcube.spatial.data
+ gis-interface
+ [2.4.6,3.0.0)
+
+
+
+
+ net.postgis
+ postgis-jdbc
+ 2.5.0
+
+
+
+
+ org.gcube.spatial.data
+ gcube-geoserver-client
+ [1.0.0-SNAPSHOT,)
+
+
+
+
+ org.gcube.data.transfer
+ data-transfer-library
+ [1.2.1,2.0.0]
+
+
+
+
+ org.gcube.common
+ storagehub-client-library
+ [1.0.0,2.0.0)
+
+
+
+
+
+
+ org.mongodb
+ mongo-java-driver
+ 3.6.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ org.projectlombok
+ lombok
+ 1.14.8
+
+
+
+
+
+ org.glassfish.jersey.test-framework.providers
+ jersey-test-framework-provider-simple
+ test
+
+
+
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+ org.apache.logging.log4j
+ log4j-slf4j18-impl
+ 2.13.3
+ test
+
+
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/AppManager.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/AppManager.java
new file mode 100644
index 0000000..517218a
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/AppManager.java
@@ -0,0 +1,18 @@
+package org.gcube.application.geoportal.service;
+
+public class AppManager {
+
+// implements ApplicationManager{
+//}
+//
+// @Override
+// public void onInit() {
+// ImplementationProvider.get().shutdown();
+// }
+//
+// @Override
+// public void onShutdown() {
+// ImplementationProvider.get().shutdown();
+// }
+
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/GeoPortalService.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/GeoPortalService.java
new file mode 100644
index 0000000..7fb5902
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/GeoPortalService.java
@@ -0,0 +1,39 @@
+package org.gcube.application.geoportal.service;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
+import org.gcube.application.geoportal.common.rest.InterfaceConstants;
+import org.gcube.application.geoportal.service.rest.ConcessioniOverMongo;
+import org.gcube.application.geoportal.service.rest.Profiles;
+import org.gcube.application.geoportal.service.rest.Projects;
+import org.gcube.application.geoportal.service.rest.Sections;
+import org.gcube.application.geoportal.service.utils.Serialization;
+import org.glassfish.jersey.server.ResourceConfig;
+
+import javax.ws.rs.ApplicationPath;
+
+@ApplicationPath(InterfaceConstants.APPLICATION_PATH)
+public class GeoPortalService extends ResourceConfig{
+
+
+
+ public GeoPortalService() {
+ super();
+ //Register interrfaces
+// registerClasses(Concessioni.class);
+ registerClasses(ConcessioniOverMongo.class);
+ registerClasses(Projects.class);
+ registerClasses(Sections.class);
+ registerClasses(Profiles.class);
+
+
+
+
+
+ JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
+ provider.setMapper(Serialization.mapper);
+ register(provider);
+
+ }
+
+
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/InterfaceUtils.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/InterfaceUtils.java
new file mode 100644
index 0000000..8155d1c
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/InterfaceUtils.java
@@ -0,0 +1,5 @@
+package org.gcube.application.geoportal.service;
+
+public class InterfaceUtils {
+
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/ServiceConstants.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/ServiceConstants.java
new file mode 100644
index 0000000..8b46015
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/ServiceConstants.java
@@ -0,0 +1,15 @@
+package org.gcube.application.geoportal.service;
+
+
+public class ServiceConstants {
+
+ public static final String SE_GNA_DB_FLAG="GNA_DB";
+ public static final String SE_GNA_DB_CATEGORY="Database";
+
+ public static final String MONGO_SE_PLATFORM="mongodb";
+ public static final String MONGO_SE_GNA_FLAG="internal-db";
+
+
+
+
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/ImplementationProvider.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/ImplementationProvider.java
new file mode 100644
index 0000000..b1c069b
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/ImplementationProvider.java
@@ -0,0 +1,63 @@
+package org.gcube.application.geoportal.service.engine;
+
+//import org.gcube.application.geoportal.managers.AbstractRecordManager;
+//import org.gcube.application.geoportal.managers.EMFProvider;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.Synchronized;
+import org.gcube.application.geoportal.service.engine.providers.*;
+
+public class ImplementationProvider {
+
+ private static ImplementationProvider instance=null;
+
+ @Synchronized
+ public static ImplementationProvider get() {
+ if(instance==null) {
+ instance=new ImplementationProvider();
+ }
+ return instance;
+ }
+
+
+ @Getter
+ @Setter
+ private MongoConnectionProvider mongoConnectionProvider=new MongoConnectionProvider();
+
+ @Getter
+ @Setter
+ private MongoClientProvider mongoClientProvider=new MongoClientProvider();
+
+
+ @Getter
+ @Setter
+ private StorageClientProvider storageProvider=new StorageClientProvider();
+
+ @Getter
+ @Setter
+ private PostgisConnectionProvider dbProvider=new PostgisConnectionProvider();
+
+
+// @Getter
+// @Setter
+// private EMFProvider emfProvider=new ScopedEMFProvider();
+
+
+ @Getter
+ @Setter
+ private StorageHubProvider sHubProvider=new StorageHubProvider();
+
+ public void shutdown() {
+ // Stop JPA
+// AbstractRecordManager.shutdown();
+ mongoConnectionProvider.shustdown();
+ mongoClientProvider.shustdown();
+ }
+
+ public void startup() {
+// AbstractRecordManager.setDefaultProvider(emfProvider);
+ mongoConnectionProvider.init();
+ mongoClientProvider.init();
+ }
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/SDIManager.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/SDIManager.java
new file mode 100644
index 0000000..d1099f7
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/SDIManager.java
@@ -0,0 +1,410 @@
+package org.gcube.application.geoportal.service.engine;
+
+import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
+import it.geosolutions.geoserver.rest.GeoServerRESTPublisher.UploadMethod;
+import it.geosolutions.geoserver.rest.GeoServerRESTReader;
+import it.geosolutions.geoserver.rest.decoder.RESTFeatureType;
+import it.geosolutions.geoserver.rest.decoder.RESTLayer;
+import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder;
+import it.geosolutions.geoserver.rest.encoder.datastore.GSPostGISDatastoreEncoder;
+import it.geosolutions.geoserver.rest.encoder.feature.GSFeatureTypeEncoder;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.gcube.application.geoportal.common.model.legacy.*;
+import org.gcube.application.geoportal.common.model.rest.DatabaseConnection;
+import org.gcube.application.geoportal.common.utils.Files;
+import org.gcube.application.geoportal.service.model.internal.db.PostgisTable;
+import org.gcube.application.geoportal.service.model.internal.faults.SDIInteractionException;
+import org.gcube.common.storagehub.client.dsl.FileContainer;
+import org.gcube.data.transfer.library.DataTransferClient;
+import org.gcube.data.transfer.library.TransferResult;
+import org.gcube.data.transfer.library.faults.RemoteServiceException;
+import org.gcube.data.transfer.model.Destination;
+import org.gcube.data.transfer.model.DestinationClashPolicy;
+import org.gcube.data.transfer.model.RemoteFileDescriptor;
+import org.gcube.spatial.data.gis.GISInterface;
+import org.gcube.spatial.data.gis.is.AbstractGeoServerDescriptor;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Slf4j
+public class SDIManager {
+
+ static private final String EPSG_4326="EPSG:4326";
+ static private final String WGS84_FULL="GEOGCS[\"WGS 84\", DATUM[\"World Geodetic System 1984\", SPHEROID[\"WGS 84\", 6378137.0, 298.257223563, AUTHORITY[\"EPSG\",\"7030\"]],"+
+ "AUTHORITY[\"EPSG\",\"6326\"]], PRIMEM[\"Greenwich\", 0.0, AUTHORITY[\"EPSG\",\"8901\"]], UNIT[\"degree\", 0.017453292519943295],"+
+ "AXIS[\"Geodetic longitude\", EAST], AXIS[\"Geodetic latitude\", NORTH], AUTHORITY[\"EPSG\",\"4326\"]]";
+
+
+ public static final Pattern HOSTNAME_PATTERN=Pattern.compile("(?<=\\:\\/\\/)[^\\:]*");
+ public static final Pattern PORT_PATTERN=Pattern.compile("(?<=\\:)[\\d]+");
+ public static final Pattern DB_NAME_PATTERN=Pattern.compile("(?<=\\/)[^\\/]*(?=$)");
+
+
+ private final GISInterface gis;
+ @Getter
+ private final DataTransferClient dtGeoServer;
+ private final String geoserverHostName;
+
+ private final AbstractGeoServerDescriptor currentGeoserver;
+
+
+ public SDIManager() throws SDIInteractionException {
+ try{
+ log.debug("Initializing GIS Interface..");
+ gis=GISInterface.get();
+ currentGeoserver=gis.getCurrentGeoServer();
+ if(currentGeoserver==null)
+ throw new Exception("Unable to contact data transfer for geoserver ");
+
+ log.debug("Found geoserver descriptor "+currentGeoserver);
+ geoserverHostName=new URL(currentGeoserver.getUrl()).getHost();
+
+ log.debug("Contacting Data Transfer from geoserver {} ",geoserverHostName);
+ dtGeoServer=DataTransferClient.getInstanceByEndpoint("http://"+geoserverHostName);
+ if(!currentGeoserver.getReader().existGeoserver())
+ throw new Exception("Geoserver not reachable");
+ }catch(Exception e) {
+ throw new SDIInteractionException("Unable to initialize SDI Manager",e);
+ }
+ }
+
+
+ public RemoteFileDescriptor getGeoServerRemoteFolder() throws RemoteServiceException {
+ return dtGeoServer.getWebClient().getInfo("geoserver/GNA");
+ }
+
+ public String createWorkspace(String toCreate) throws SDIInteractionException {
+ try {
+ if(!currentGeoserver.getReader().getWorkspaceNames().contains(toCreate)) {
+ log.debug("Creating workspace : "+toCreate);
+ if(!currentGeoserver.getPublisher().createWorkspace(toCreate))
+ throw new SDIInteractionException("Unable to create workspace "+toCreate);
+ }else log.debug("Workspace "+toCreate+" exists.");
+ return toCreate;
+ } catch (IllegalArgumentException | MalformedURLException e) {
+ throw new SDIInteractionException("Unable to create workspace "+toCreate,e);
+ }
+ }
+
+
+ // GEOSERVER-PERSISTENCE-ID / GNA / PROJECT-ID/ LAYER-ID /FILENAME(no extension)/...
+
+ public GeoServerContent pushShapeLayerFileSet(SDILayerDescriptor currentElement,String workspace, String projectId) throws SDIInteractionException{
+ try {
+// String remoteFolder=null;
+// String fileName=null;
+
+ log.debug("Publishing "+currentElement+" files to geoserver @ "+geoserverHostName);
+
+ GeoServerContent content=new GeoServerContent();
+ content.setGeoserverHostName(geoserverHostName);
+ content.setWorkspace(workspace);
+ WorkspaceManager wsManager=new WorkspaceManager();
+
+
+
+
+ currentElement.getActualContent().forEach((PersistedContent c)->{
+ try {
+ if(c instanceof WorkspaceContent) {
+ WorkspaceContent wc=(WorkspaceContent) c;
+ FileContainer fc=wsManager.getFileById(wc.getStorageID());
+
+ String completeFilename=Files.fixFilename(fc.get().getName());
+ String filename=completeFilename.contains(".")?completeFilename.substring(0, completeFilename.lastIndexOf(".")):completeFilename;
+
+
+ Destination destination=new Destination(completeFilename);
+ destination.setCreateSubfolders(true);
+ destination.setOnExistingFileName(DestinationClashPolicy.REWRITE);
+ destination.setOnExistingSubFolder(DestinationClashPolicy.APPEND);
+
+ destination.setPersistenceId("geoserver");
+ destination.setSubFolder("GNA/"+projectId+"/"+
+ currentElement.getMongo_id()+"/"+filename);
+
+ log.debug("Sending "+wc+" to "+destination);
+ TransferResult result=dtGeoServer.httpSource(fc.getPublicLink(), destination);
+ log.debug("Transferred "+result);
+
+
+ content.getFileNames().add(completeFilename);
+
+ content.setGeoserverPath(result.getRemotePath().substring(0,result.getRemotePath().lastIndexOf("/")));
+ }
+ }catch(Throwable t) {
+ log.warn("Unable to transfer Persisted content"+c,t);
+ }
+
+ });
+
+
+
+
+
+
+ if(content.getFileNames().isEmpty())
+ throw new SDIInteractionException("No Persisted content found in "+currentElement);
+
+ String completeFileName=content.getFileNames().get(0);
+ String filename=completeFileName.contains(".")?completeFileName.substring(0, completeFileName.lastIndexOf(".")):completeFileName;
+
+ String remoteFolder=content.getGeoserverPath();
+
+ String toSetLayerName=filename;
+ int count=0;
+ GeoServerRESTReader gsReader=currentGeoserver.getReader();
+ while(gsReader.getLayer(workspace,toSetLayerName)!=null){
+ count++;
+ toSetLayerName=filename+"_"+count;
+ log.debug("layer for "+filename+" already existing, trying "+toSetLayerName);
+ }
+
+
+ String storeName=toSetLayerName+"_store";
+ content.setStore(storeName);
+ content.setFeatureType(toSetLayerName);
+
+ GeoServerRESTPublisher publisher=currentGeoserver.getPublisher();
+ log.debug("Trying to create remote workspace : "+workspace);
+ createWorkspace(workspace);
+
+ log.debug("Publishing remote folder "+remoteFolder);
+
+ URL directoryPath=new URL("file:"+remoteFolder+"/"+filename+".shp");
+
+
+ //TODO Evaluate SRS
+
+ boolean published=publisher.publishShp(
+ workspace,
+ storeName,
+ null,
+ toSetLayerName,
+ // UploadMethod.FILE, // neeeds zip
+ UploadMethod.EXTERNAL, // needs shp
+ directoryPath.toURI(),
+ EPSG_4326, //SRS
+ ""); // default style
+
+ if(!published) {
+ throw new SDIInteractionException("Unable to publish layer "+toSetLayerName+" under "+workspace+". Unknown Geoserver fault.");
+ }
+
+ currentElement.setLayerName(toSetLayerName);
+
+ RESTLayer l=gsReader.getLayer(workspace, toSetLayerName);
+ RESTFeatureType f= gsReader.getFeatureType(l);
+ /*http://geoserver1.dev.d4science.org/geoserver/gna_conc_18/wms?
+ service=WMS&version=1.1.0&request=GetMap&layers=gna_conc_18:pos&
+ styles=&bbox=8.62091913167495,40.62975046683799,8.621178639172953,40.630257904721645&
+ width=392&height=768&srs=EPSG:4326&format=application/openlayers */
+
+
+ currentElement.setWmsLink(
+ String.format("https://%1$s/geoserver/%2$s/wms?"
+ +"service=WMS&version=1.1.0&request=GetMap&layers=%2$s:%3$s&"
+ + "styles=&bbox=%4$f,%5$f,%6$f,%7$f&srs=%8$s&format=application/openlayers&width=%9$d&height=%10$d",
+ geoserverHostName,
+ workspace,
+ toSetLayerName,
+ f.getMinX(),
+ f.getMinY(),
+ f.getMaxX(),
+ f.getMaxY(),
+ EPSG_4326,
+ 400,
+ 400));
+
+ currentElement.setWorkspace(workspace);
+ currentElement.setBbox(new BBOX(f.getMaxY(), f.getMaxX(), f.getMinY(), f.getMinX()));
+
+
+ // TODO Metadata
+ return content;
+// } catch (InvalidSourceException | SourceNotSetException | FailedTransferException | InitializationException
+// | InvalidDestinationException | DestinationNotSetException e) {
+// throw new SDIInteractionException("Unable to transfer fileSet for content "+currentElement,e);
+ } catch (SDIInteractionException e) {
+ throw e;
+ } catch (Throwable t) {
+ throw new SDIInteractionException("Unexpected internal fault while interacting with SDI.",t);
+ }
+ }
+
+ private String createStore(GSPostGISDatastoreEncoder encoder, String workspace) throws SDIInteractionException {
+ String storeName=encoder.getName();
+ try {
+ log.debug("Looking for datastore "+storeName+" under "+workspace);
+
+ if(currentGeoserver.getReader().getDatastore(workspace,storeName)==null)
+
+ if(!currentGeoserver.getDataStoreManager().create(workspace, encoder))
+ throw new SDIInteractionException("Unable to create store "+storeName+" in "+workspace);
+ log.debug("Store "+storeName+" exists under "+workspace);
+ return storeName;
+ } catch (IllegalArgumentException | MalformedURLException e) {
+ throw new SDIInteractionException("Unable to create store "+storeName,e);
+ }
+ }
+
+ private String createStoreFromPostgisDB(String workspace, String storeName, DatabaseConnection connection) throws SDIInteractionException{
+ String connectionUrl=connection.getUrl();
+
+ Matcher hostname=HOSTNAME_PATTERN.matcher(connectionUrl);
+ if (!hostname.find()) throw new SDIInteractionException("Unable to get Hostname from "+connection);
+
+ Matcher port = PORT_PATTERN.matcher(connectionUrl);
+ if (!port.find()) throw new SDIInteractionException("Unable to get PORT from "+connection);
+
+ Matcher db = DB_NAME_PATTERN.matcher(connectionUrl);
+ if (!db.find()) throw new SDIInteractionException("Unable to get DB from "+connection);
+
+
+ GSPostGISDatastoreEncoder encoder=new GSPostGISDatastoreEncoder(storeName);
+ encoder.setHost(hostname.group());
+ encoder.setPort(Integer.parseInt(port.group()));
+ encoder.setDatabase(db.group());
+ encoder.setSchema("public");
+ encoder.setUser(connection.getUser());
+ encoder.setPassword(connection.getPwd());
+ encoder.setLooseBBox(true);
+ encoder.setDatabaseType("postgis");
+ encoder.setEnabled(true);
+ encoder.setFetchSize(1000);
+ encoder.setValidateConnections(true);
+
+ return createStore(encoder,workspace);
+ }
+ private String createStoreFromJNDIDB(String workspace,String storeName) throws SDIInteractionException {
+ //SET BY PROVISIONING
+ GSPostGISDatastoreEncoder encoder=new GSPostGISDatastoreEncoder(storeName);
+ encoder.setJndiReferenceName("java:comp/env/jdbc/postgres");
+ encoder.setLooseBBox(true);
+ encoder.setDatabaseType("postgis");
+ encoder.setEnabled(true);
+ encoder.setFetchSize(1000);
+ encoder.setValidateConnections(true);
+ return createStore(encoder,workspace);
+ }
+
+ private String publishStyle(File sldFile,String name) throws SDIInteractionException {
+ try {
+ if(!currentGeoserver.getReader().existsStyle(name)) {
+ log.debug("Registering style "+name);
+ if(!currentGeoserver.getPublisher().publishStyle(sldFile, name))
+ throw new SDIInteractionException("Unable to register style "+name);
+ }else log.debug("Style "+name+" already existing");
+ return name;
+ } catch (IllegalArgumentException | MalformedURLException e) {
+ throw new SDIInteractionException("Unable to create style "+name,e);
+ }
+
+ }
+
+ public String configureCentroidLayer(String name, String workspace, String storeName, PostgisTable table, DatabaseConnection connection) throws SDIInteractionException {
+
+ GSFeatureTypeEncoder fte=new GSFeatureTypeEncoder();
+ fte.setAbstract("Centroid layer for "+name);
+ fte.setEnabled(true);
+ fte.setNativeCRS(WGS84_FULL);
+ fte.setTitle(name);
+ fte.setName(name);
+
+
+ // GeoServer loads all fields
+// fte.setAttribute(attrs);
+
+
+ fte.setLatLonBoundingBox(-180.0, -90.0, 180.0, 90.0, WGS84_FULL);
+
+ String style="clustered_centroids";
+
+ GSLayerEncoder layerEncoder=new GSLayerEncoder();
+ layerEncoder.setDefaultStyle(style);
+ layerEncoder.setEnabled(true);
+ layerEncoder.setQueryable(true);
+ try {
+ //Checking workspace
+ createWorkspace(workspace);
+ //Checking store
+ createStoreFromPostgisDB(workspace, storeName,connection);
+ //Checking layer
+ publishStyle(Files.getFileFromResources("styles/clustered_points.sld"),style);
+
+ log.info("Creating layer in {} : {} with FTE {} , LE {}",workspace,storeName,fte,layerEncoder);
+ if(currentGeoserver.getReader().getLayer(workspace, name)==null)
+ if(!currentGeoserver.getPublisher().publishDBLayer(workspace, storeName, fte, layerEncoder))
+ throw new SDIInteractionException("Unable to create layer "+name);
+ log.debug("layer "+name+" already exists");
+
+
+ String link=String.format("https://%1$s/geoserver/%2$s/wms?"
+ +"service=WMS&version=1.1.0&request=GetMap&layers=%2$s:%3$s&"
+ + "styles=&bbox=%4$s,%5$s,%6$s,%7$s&srs=%8$s&format=application/openlayers&width=%9$d&height=%10$d",
+ geoserverHostName,
+ workspace,
+ name,
+ "-1563071.166172796",
+ "4789738.204048398",
+ "4334926.486925308",
+ "5828118.072551585",
+ EPSG_4326,
+ 400,
+ 400);
+
+ return name;
+ } catch (IllegalArgumentException | MalformedURLException e) {
+ throw new SDIInteractionException("Unable to create layer "+name,e);
+ }
+
+
+ }
+
+
+ public void deleteContent(GeoServerContent toDelete) throws IllegalArgumentException, MalformedURLException, RemoteServiceException {
+ log.info("Deleting geoserver layer "+toDelete);
+
+ String geoserverHostName=toDelete.getGeoserverHostName();
+ log.debug("Looking for geoserver {}",geoserverHostName);
+
+ AbstractGeoServerDescriptor geoServerDescriptor=null;
+
+ for(AbstractGeoServerDescriptor gs :gis.getCurrentCacheElements(false)){
+ log.debug("Checking gs {}",gs);
+ if(new URL(gs.getUrl()).getHost().equals(geoserverHostName))
+ geoServerDescriptor=gs;
+ }
+ if(geoServerDescriptor == null) throw new IllegalArgumentException("Unable to find geoserver "+geoserverHostName);
+
+ GeoServerRESTPublisher publisher=geoServerDescriptor.getPublisher();
+
+ //delete layer
+ //delete store
+ log.debug("Removing DS {} : {} ",toDelete.getWorkspace(),toDelete.getStore());
+ publisher.removeDatastore(toDelete.getWorkspace(), toDelete.getStore(), true);
+
+ //delete WS if empty
+ GeoServerRESTReader reader=geoServerDescriptor.getReader();
+ log.debug("Checking if WS {} is empty",toDelete.getWorkspace());
+ if(reader.getDatastores(toDelete.getWorkspace()).isEmpty()) {
+ log.debug("Deleting emtpy workspace "+toDelete.getWorkspace());
+ publisher.removeWorkspace(toDelete.getWorkspace(), true);
+ }
+ //delete file
+
+
+ // TODO REMOVE HARDCODED PATCH
+ String path=toDelete.getGeoserverPath().replace("/srv/geoserver_data","geoserver");
+ log.info("Deleting files at {} [{}]",path,toDelete.getGeoserverPath());
+// path=toDelete.getGeoserverPath();
+ dtGeoServer.getWebClient().delete(path);
+ }
+
+
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/WorkspaceManager.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/WorkspaceManager.java
new file mode 100644
index 0000000..e83f90d
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/WorkspaceManager.java
@@ -0,0 +1,137 @@
+package org.gcube.application.geoportal.service.engine;
+
+import lombok.*;
+import lombok.extern.slf4j.Slf4j;
+import org.gcube.application.geoportal.common.model.legacy.WorkspaceContent;
+import org.gcube.application.geoportal.common.utils.Files;
+import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException;
+import org.gcube.common.storagehub.client.dsl.FileContainer;
+import org.gcube.common.storagehub.client.dsl.FolderContainer;
+import org.gcube.common.storagehub.client.dsl.StorageHubClient;
+import org.gcube.common.storagehub.model.exceptions.StorageHubException;
+
+import javax.validation.constraints.NotNull;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+@Slf4j
+public class WorkspaceManager {
+
+ private static final String APP_FOLDER=".GNA_RECORDS";
+
+
+ private StorageHubClient sgClient=null;
+ private FolderContainer appBase=null;
+
+ @Getter
+ @Setter
+ @AllArgsConstructor
+ @RequiredArgsConstructor
+ public static class FolderOptions{
+ @NotNull
+ private String folderName;
+ private String folderDescription;
+ private FolderContainer parent;
+ }
+
+ @Getter
+ @Setter
+ @AllArgsConstructor
+ @RequiredArgsConstructor
+ public static class FileOptions{
+ @NotNull
+ private String fileName;
+ @NonNull
+ private InputStream is;
+
+ private String fileDescription;
+ private FolderContainer parent;
+
+ }
+
+
+ public WorkspaceManager() throws ConfigurationException, StorageHubException {
+ sgClient= ImplementationProvider.get().getSHubProvider().getObject();
+ appBase=getApplicationBaseFolder(sgClient);
+ }
+
+ public FolderContainer createFolder(FolderOptions opts) throws StorageHubException {
+ if(opts.getParent()==null)
+ opts.setParent(appBase);
+ return createFolder(opts,sgClient);
+ }
+
+ public FileContainer getFileById(String id) throws StorageHubException {
+ return sgClient.open(id).asFile();
+ }
+
+ public FolderContainer getFolderById(String id) throws StorageHubException {
+ return sgClient.open(id).asFolder();
+ }
+
+ public void removeFolderById(String id) throws StorageHubException {
+ sgClient.open(id).asFolder().delete();
+ }
+
+ public FolderContainer getSubFolder(FolderContainer parentFolder,String path) throws StorageHubException {
+ try{
+ return parentFolder.openByRelativePath(path).asFolder();
+ }catch(StorageHubException e) {
+ log.debug("Missing subPath "+path);
+ FolderContainer targetParent=parentFolder;
+ String targetName=path;
+ if(path.contains("/")) {
+ String parent=path.substring(0, path.lastIndexOf("/"));
+ log.debug("Checking intermediate "+parent);
+ targetParent=getSubFolder(parentFolder,parent);
+ targetName=path.substring(path.lastIndexOf("/")+1);
+ }
+ log.debug("Creating "+targetName);
+ return createFolder(new FolderOptions(targetName,"",targetParent),sgClient);
+ }
+ }
+
+
+ public WorkspaceContent storeToWS(FileOptions opts) throws FileNotFoundException, StorageHubException {
+ FileContainer item=createFile(opts,sgClient);
+ item=sgClient.open(item.getId()).asFile();
+
+ WorkspaceContent content=new WorkspaceContent();
+ content.setLink(item.getPublicLink().toString());
+ content.setMimetype(item.get().getContent().getMimeType());
+ content.setStorageID(item.getId());
+ return content;
+
+ }
+
+ public void deleteFromWS(WorkspaceContent toDelete) throws StorageHubException {
+ sgClient.open(toDelete.getStorageID()).asFile().forceDelete();
+ }
+
+ // STATIC SYNCH METHODS
+
+ @Synchronized
+ public static FolderContainer getApplicationBaseFolder(StorageHubClient sgClient) throws StorageHubException {
+ FolderContainer vre=sgClient.openVREFolder();
+ try {
+ return vre.openByRelativePath(APP_FOLDER).asFolder();
+ }catch(StorageHubException e) {
+ log.debug("APP Fodler missing. Initializing..");
+ FolderContainer toReturn= vre.newFolder(APP_FOLDER, "Base folder for GNA records");
+ toReturn.setHidden();
+ return toReturn;
+ }
+ }
+
+ @Synchronized
+ private static FolderContainer createFolder(FolderOptions opts, StorageHubClient sgClient) throws StorageHubException {
+ opts.setFolderName(Files.fixFilename(opts.getFolderName()));
+ return opts.getParent().newFolder(opts.getFolderName(),opts.getFolderDescription());
+ }
+
+ @Synchronized
+ private static FileContainer createFile(FileOptions opts, StorageHubClient sgClient) throws StorageHubException {
+ opts.setFileName(Files.fixFilename(opts.getFileName()));
+ return opts.getParent().uploadFile(opts.getIs(), opts.getFileName(), opts.getFileDescription());
+ }
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/cache/Cache.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/cache/Cache.java
new file mode 100644
index 0000000..158c59a
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/cache/Cache.java
@@ -0,0 +1,9 @@
+package org.gcube.application.geoportal.service.engine.cache;
+
+public class Cache {
+
+ public Cache() {
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ConcessioniMongoManager.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ConcessioniMongoManager.java
new file mode 100644
index 0000000..1bbfdbf
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ConcessioniMongoManager.java
@@ -0,0 +1,433 @@
+package org.gcube.application.geoportal.service.engine.mongo;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.mongodb.client.MongoDatabase;
+import lombok.Synchronized;
+import lombok.extern.slf4j.Slf4j;
+import org.bson.Document;
+import org.bson.types.ObjectId;
+import org.gcube.application.geoportal.common.model.legacy.*;
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport;
+import org.gcube.application.geoportal.common.model.legacy.report.ValidationReport.ValidationStatus;
+import org.gcube.application.geoportal.common.model.rest.QueryRequest;
+import org.gcube.application.geoportal.common.rest.TempFile;
+import org.gcube.application.geoportal.common.utils.Files;
+import org.gcube.application.geoportal.service.engine.ImplementationProvider;
+import org.gcube.application.geoportal.service.engine.SDIManager;
+import org.gcube.application.geoportal.service.engine.WorkspaceManager;
+import org.gcube.application.geoportal.service.engine.WorkspaceManager.FileOptions;
+import org.gcube.application.geoportal.service.engine.WorkspaceManager.FolderOptions;
+import org.gcube.application.geoportal.service.engine.postgis.PostgisIndex;
+import org.gcube.application.geoportal.service.engine.providers.StorageClientProvider;
+import org.gcube.application.geoportal.service.model.internal.faults.*;
+import org.gcube.application.geoportal.service.utils.Serialization;
+import org.gcube.common.storagehub.client.dsl.FolderContainer;
+import org.gcube.data.transfer.library.faults.RemoteServiceException;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.sql.SQLException;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.function.Consumer;
+
+@Slf4j
+public class ConcessioniMongoManager extends MongoManager{
+
+
+
+ public ConcessioniMongoManager() throws ConfigurationException {
+ super();
+ }
+ private static final String collectionName="legacyConcessioni";
+ private static final String DB_NAME="gna_dev";
+
+
+ private MongoDatabase db=null;
+
+ @Override
+ @Synchronized
+ protected MongoDatabase getDatabase() {
+ if(db==null) {
+ db=client.getDatabase(DB_NAME);
+ }
+ return db;
+ }
+
+ protected static Document asDocument (Concessione c) throws JsonProcessingException {
+ Document toReturn=Document.parse(Serialization.write(c));
+ if(c.getMongo_id()!=null&&!c.getMongo_id().isEmpty())
+ toReturn.append(ID, asId(c.getMongo_id()));
+ return toReturn;
+ }
+
+ protected static Concessione asConcessione (Document d) throws JsonProcessingException, IOException {
+ return Serialization.read(d.toJson(), Concessione.class);
+ }
+
+
+ // *** PUBLIC METHODS
+
+
+ public Concessione registerNew(Concessione toRegister) throws IOException {
+ log.trace("Registering {} ",toRegister);
+ toRegister.setDefaults();
+ ObjectId id=insert(asDocument(toRegister), collectionName);
+
+ Concessione toReturn=asConcessione(getById(id,collectionName));
+ toReturn.setMongo_id(asString(id));
+
+ return asConcessione(replace(asDocument(toReturn),collectionName));
+ }
+
+ public Concessione replace(Concessione toRegister) throws IOException {
+ log.trace("Replacing {} ",toRegister);
+ toRegister.setDefaults();
+ return asConcessione(replace(asDocument(toRegister),collectionName));
+ }
+
+ public Concessione update(String id,String json) throws IOException {
+ log.trace("Updating id {} with {} ",id,json);
+ Concessione toReturn=asConcessione(update(asId(id),asDoc(json),collectionName));
+ log.debug("Refreshing defaults..");
+ toReturn.setDefaults();
+ return asConcessione(replace(asDocument(toReturn),collectionName));
+ }
+
+
+
+ public Iterable list(){
+ LinkedBlockingQueue queue=new LinkedBlockingQueue();
+ iterate(null,null, collectionName).forEach(
+ new Consumer() {
+ @Override
+ public void accept(Document d) {
+ try {
+ queue.put(asConcessione(d));
+ }catch(Throwable t) {
+ log.error("Unable to read Document as concessione ",t);
+ log.debug("Document was "+d.toJson());
+ }
+ }
+ });
+ return queue;
+ }
+
+ public Iterable search(Document filter){
+ log.info("Searching concessione for filter {} ",filter);
+ LinkedBlockingQueue queue=new LinkedBlockingQueue();
+ iterate(filter,null,collectionName).forEach(
+ (Consumer super Document>) (Document d)->{try{
+ queue.put(asConcessione(d));
+ }catch(Throwable t){log.warn("Unable to translate "+d);}});
+ log.info("Returned {} elements ",queue.size());
+ return queue;
+ }
+
+ public Iterable query(QueryRequest queryRequest){
+ log.info("Searching concessione for filter {} ",queryRequest);
+ LinkedBlockingQueue queue=new LinkedBlockingQueue();
+ query(queryRequest,collectionName).forEach(
+ (Consumer super Document>) (Document d)->{try{
+ queue.put(d);
+ }catch(Throwable t){log.warn("Unable to translate "+d);}});
+ log.info("Returned {} elements ",queue.size());
+ return queue;
+ }
+
+ public Concessione getById(String id)throws IOException {
+ log.debug("Loading by ID "+id);
+ return asConcessione(getById(asId(id),collectionName));
+ }
+
+ public void deleteById(String id,boolean force) throws DeletionException {
+ log.debug("Deleting by ID {}, force {}",id,force);
+ try{
+ Concessione concessione =unpublish(id);
+ try{
+ // UNPUBLISH
+
+ if (!concessione.getReport().getStatus().equals(ValidationStatus.PASSED)&&!force)
+ throw new DeletionException("Unable to unpublish "+concessione.getMongo_id());
+ //clean WS
+
+ concessione = removeContent(concessione);
+
+ if (!concessione.getReport().getStatus().equals(ValidationStatus.PASSED)&&!force)
+ throw new DeletionException("Unable to unpublish "+concessione.getMongo_id());
+
+ delete(asId(id), collectionName);
+ }catch(DeletionException e) {
+ //storing updated - partially deleted
+ replace(asDocument(concessione), collectionName);
+ throw e;
+ }
+ }catch(Throwable t){
+ throw new DeletionException("Unable to delete "+id,t);
+ }
+ }
+
+
+
+ public Concessione unpublish(String id) throws DeletionException {
+ try{
+ Concessione toReturn=asConcessione(getById(asId(id),collectionName));
+ removeFromIndex(toReturn);
+ log.debug("Removed from centroids "+toReturn.getMongo_id());
+ toReturn = unpublish(toReturn);
+ log.debug("Concessione after unpublishing is "+toReturn);
+ return asConcessione(replace(asDocument(toReturn),collectionName));
+ }catch(Throwable t){
+ throw new DeletionException("Unable to unpublish "+id,t);
+ }
+ }
+
+ public Concessione publish(String id) throws JsonProcessingException, IOException, InvalidStateException{
+ Concessione toReturn=asConcessione(getById(asId(id),collectionName));
+ toReturn.setDefaults();
+ toReturn.validate();
+
+ // MATERIALIZE LAYERS
+ toReturn=publish(toReturn);
+ // replace(asDocument(toReturn),collectionName);
+
+ // CREATE INDEXES
+ toReturn=index(toReturn);
+ // replace(asDocument(toReturn),collectionName);
+
+ return asConcessione(replace(asDocument(toReturn),collectionName));
+ }
+
+
+
+
+ private static Concessione removeContent(Concessione concessione) throws DeletionException {
+ if(concessione.getFolderId()==null) {
+ log.debug("No content for " + concessione.getMongo_id());
+ return concessione;
+ }
+ try {
+ log.debug("Removing content for " + concessione.getMongo_id());
+ WorkspaceManager manager = new WorkspaceManager();
+ manager.removeFolderById(concessione.getFolderId());
+
+ //Removing references from Object
+ concessione.setFolderId(null);
+ ArrayList list = new ArrayList<>();
+ list.add(concessione.getPosizionamentoScavo());
+ list.addAll(concessione.getPianteFineScavo());
+ list.addAll(concessione.getImmaginiRappresentative());
+ list.addAll(concessione.getGenericContent());
+ for (AssociatedContent c : list) {
+ c.getActualContent().clear();
+ }
+ return concessione;
+ }catch(Throwable t){
+ throw new DeletionException("Unable to delete from WS ",t);
+ }
+
+ }
+
+ public Concessione unregisterFileset(String id, String toClearPath) throws Exception {
+ log.info("Clearing Fileset at {} for {} ",toClearPath,id);
+ try {
+ WorkspaceManager ws=new WorkspaceManager();
+ Concessione c = getById(id);
+ AssociatedContent toClearContent=c.getContentByPath(toClearPath);
+ log.debug("Found content {} for path {}",toClearContent,toClearPath);
+
+ //checking if published content
+ for(PersistedContent persisted : toClearContent.getActualContent()){
+ if(persisted instanceof GeoServerContent) throw new Exception ("Cannot clear concessione "+id+" at "+toClearContent+", because it is published.");
+ }
+
+ for(PersistedContent persisted : toClearContent.getActualContent()){
+ if(persisted instanceof WorkspaceContent) ws.deleteFromWS((WorkspaceContent) persisted);
+ }
+ toClearContent.getActualContent().clear();
+
+ log.debug("Updating dafults for {} ",c);
+ c.setDefaults();
+ return asConcessione(replace(asDocument(c),collectionName));
+
+ }catch(Exception e) {
+ throw new Exception("Unable to unregister files.",e);
+ }
+ }
+
+ public Concessione persistContent(String id, String destinationPath, List files) throws Exception{
+ log.info("Persisting {} files for path {} in concessione ",files.size(),destinationPath,id);
+ try{
+ Concessione c = getById(id);
+ WorkspaceManager ws=new WorkspaceManager();
+ //Check Init Base folder
+ FolderContainer baseFolder=null;
+ if(c.getFolderId()==null) {
+ String folderName=Files.fixFilename("mConcessione"+"_"+c.getNome()+"_"+Serialization.FULL_FORMATTER.format(LocalDateTime.now()));
+ log.info("Creating folder {} for Concessione ID {} ",folderName,id);
+ FolderContainer folder=ws.createFolder(new FolderOptions(folderName, "Base Folder for "+c.getNome(),null));
+ c.setFolderId(folder.getId());
+ }
+
+ log.debug("Folder id is : "+c.getFolderId());
+ baseFolder=ws.getFolderById(c.getFolderId());
+
+ AssociatedContent section=c.getContentByPath(destinationPath);
+ log.debug("Found section {} for path {}",section,destinationPath);
+ store(section,files,ws,baseFolder);
+ log.debug("Updating dafults for {} ",c);
+ c.setDefaults();
+ return asConcessione(replace(asDocument(c),collectionName));
+ }catch(Exception e) {
+ throw new Exception("Unable to save file.",e);
+ }
+ }
+
+ private static Concessione index(Concessione record) {
+ log.info("Indexing {} ",record.getId());
+ ValidationReport report= new ValidationReport("Index Report ");
+ PostgisIndex index;
+ try {
+ index = new PostgisIndex();
+ index.registerCentroid(record);
+ report.addMessage(ValidationStatus.PASSED, "Registered centroid");
+ } catch (SDIInteractionException | PublishException | SQLException | ConfigurationException e) {
+ log.error("Unable to index {} ",record,e);
+ report.addMessage(ValidationStatus.WARNING, "Internal error while indexing.");
+ }
+ return record;
+ }
+
+ private static Concessione removeFromIndex(Concessione record) {
+ log.info("Removing from index {} ",record.getMongo_id());
+ ValidationReport report= new ValidationReport("Remove From Index Report ");
+ PostgisIndex index;
+ try {
+ index = new PostgisIndex();
+ index.removeCentroid(record);
+ report.addMessage(ValidationStatus.PASSED, "Removed centroid");
+ } catch (SDIInteractionException | SQLException | ConfigurationException e) {
+ log.error("Unable to reove from index {} ",record,e);
+ report.addMessage(ValidationStatus.WARNING, "Internal error while removing from index.");
+ }
+ return record;
+ }
+
+
+
+ private static Concessione publish(Concessione conc) {
+
+ // CHECK CONDITION BY PROFILE
+
+
+ log.debug("Publishing "+conc.getNome());
+
+ ValidationReport report=new ValidationReport("Publish report");
+ try {
+ SDIManager sdiManager=new SDIManager();
+ ArrayList list=new ArrayList();
+
+ //Concessione
+ String workspace= sdiManager.createWorkspace("gna_conc_"+conc.getMongo_id());
+ list.add(conc.getPosizionamentoScavo());
+ list.addAll(conc.getPianteFineScavo());
+
+ for(AssociatedContent c:list) {
+ if(c instanceof LayerConcessione) {
+ try {
+ List p=c.getActualContent();
+
+ GeoServerContent geoserverPersisted=sdiManager.pushShapeLayerFileSet((SDILayerDescriptor)c, workspace, conc.getMongo_id());
+ // geoserverPersisted.setAssociated(c);
+
+
+ p.add(geoserverPersisted);
+ c.setActualContent(p);
+ }catch(SDIInteractionException e) {
+ log.warn("Unable to publish layers.",e);
+ report.addMessage(ValidationStatus.WARNING, "Layer "+c.getTitolo()+" non pubblicato.");
+ }
+ report.addMessage(ValidationStatus.PASSED, "Pubblicato layer "+c.getTitolo());
+ }
+ }
+
+
+ } catch (SDIInteractionException e1) {
+ report.addMessage(ValidationStatus.WARNING, "Unable to publish layers "+e1.getMessage());
+ }
+
+ conc.setReport(report);
+ return conc;
+ }
+
+ private static final Concessione unpublish(Concessione concessione){
+ ValidationReport report=new ValidationReport("Unpublish report");
+ try{
+ SDIManager sdi=new SDIManager();
+ ArrayList list=new ArrayList();
+
+ list.add(concessione.getPosizionamentoScavo());
+ list.addAll(concessione.getPianteFineScavo());
+ for(AssociatedContent c:list) {
+ if(c instanceof LayerConcessione) {
+ List contents=c.getActualContent();
+ List toRemove=new ArrayList<>();
+ for(PersistedContent p:contents){
+ if(p instanceof GeoServerContent){
+ try {
+ sdi.deleteContent((GeoServerContent) p);
+ toRemove.add(p);
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ } catch (RemoteServiceException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ c.getActualContent().removeAll(toRemove);
+ }
+ }
+ }catch(SDIInteractionException e){
+ report.addMessage(ValidationStatus.WARNING, "Unable to unpublish layers "+e.getMessage());
+ }
+ concessione.setReport(report);
+ return concessione;
+ }
+
+
+
+ private static final void store(AssociatedContent content,List files, WorkspaceManager ws, FolderContainer base) throws Exception {
+ FolderContainer sectionParent=null;
+
+ if(content instanceof RelazioneScavo)
+ sectionParent = ws .createFolder(new FolderOptions(
+ "relazione","Relazione di scavo : "+content.getTitolo(),base));
+
+ else if (content instanceof UploadedImage)
+ sectionParent = ws .createFolder(new FolderOptions(
+ "imgs","Immagini rappresentative : "+content.getTitolo(),base));
+
+ else if (content instanceof SDILayerDescriptor)
+ //SDI Section
+ if(content instanceof LayerConcessione)
+ sectionParent = ws .createFolder(new FolderOptions(
+ content.getTitolo(),"Layer Concessione : "+content.getTitolo(),ws.getSubFolder(base,"layers")));
+ else throw new Exception("Invalid SDI Content "+content);
+ else if (content instanceof OtherContent )
+ sectionParent = ws .createFolder(new FolderOptions(
+ content.getTitolo(),"Relazione di scavo : "+content.getTitolo(),ws.getSubFolder(base,"other")));
+ else throw new Exception("Invalid Content "+content);
+
+ content.setActualContent(new ArrayList());
+ StorageClientProvider storage=ImplementationProvider.get().getStorageProvider();
+ for(TempFile f : files) {
+ WorkspaceContent wsContent=ws.storeToWS(new FileOptions(f.getFilename(), storage.open(f.getId()), "Imported via GeoPortal", sectionParent));
+ log.debug("Registered "+wsContent+" for "+content);
+ content.getActualContent().add(wsContent);
+ }
+ content.setMongo_id(asString(new ObjectId()));
+ }
+
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/MongoManager.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/MongoManager.java
new file mode 100644
index 0000000..d5e0c61
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/MongoManager.java
@@ -0,0 +1,152 @@
+package org.gcube.application.geoportal.service.engine.mongo;
+
+
+import com.mongodb.Block;
+import com.mongodb.MongoClient;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.FindOneAndReplaceOptions;
+import com.mongodb.client.model.FindOneAndUpdateOptions;
+import com.mongodb.client.model.ReturnDocument;
+import lombok.extern.slf4j.Slf4j;
+import org.bson.Document;
+import org.bson.types.ObjectId;
+import org.gcube.application.geoportal.common.model.rest.QueryRequest;
+import org.gcube.application.geoportal.service.engine.ImplementationProvider;
+import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException;
+
+import static com.mongodb.client.model.Filters.eq;
+import static com.mongodb.client.model.Sorts.ascending;
+import static com.mongodb.client.model.Sorts.descending;
+
+@Slf4j
+public abstract class MongoManager {
+
+ protected MongoClient client=null;
+
+ protected static final String ID="_id";
+
+ protected static final ObjectId asId(String id) {return new ObjectId(id);}
+ protected static final String asString(ObjectId id) {return id.toHexString();}
+
+ protected static final String asString(Document d) {return d.toJson();}
+ protected static final Document asDoc(String json) {return Document.parse(json);}
+
+ public MongoManager() throws ConfigurationException {
+ client=ImplementationProvider.get().getMongoClientProvider().getObject();
+
+ log.info("Got Mongo Client at "+client.getConnectPoint());
+ // NOT AUTHORIZED
+// log.debug("Existing databases "+client.getDatabaseNames());
+ }
+
+// private abstract MongoDatabase getDatabase() {
+// return client.getDatabase("gna-db");
+// }
+
+ // TODO check if existing DB
+ protected abstract MongoDatabase getDatabase();
+
+ //*********** PROJECTS
+ // NB BsonId
+ protected ObjectId insert(Document proj, String collectionName) {
+ MongoDatabase database=getDatabase();
+ MongoCollection collection = database.getCollection(collectionName);
+
+ // Check if _id is present
+ ObjectId id=proj.getObjectId(ID);
+ if(id==null) {
+ proj.append(ID, new ObjectId());
+ id=proj.getObjectId(ID);
+ }
+
+
+ collection.insertOne(Document.parse(proj.toJson()));
+ return id;
+ }
+
+ public void delete(ObjectId id, String collectionName) {
+ MongoDatabase database=getDatabase();
+ MongoCollection collection = database.getCollection(collectionName);
+ collection.deleteOne(eq(ID,id));
+ }
+
+
+
+ public Document getById(ObjectId id,String collectionName) {
+ MongoDatabase database=getDatabase();
+ MongoCollection coll=database.getCollection(collectionName);
+ return coll.find(new Document(ID,id)).first();
+ }
+
+
+ public FindIterable iterate(Document filter, Document projection, String collectionName) {
+ log.debug("Iterate over {} ",collectionName);
+ MongoDatabase database=getDatabase();
+ MongoCollection coll=database.getCollection(collectionName);
+
+ if(filter == null) filter=new Document();
+
+ log.debug("Applying Filter "+filter.toJson());
+
+
+ if(projection != null ) {
+ log.debug("Applying projection "+projection.toJson());
+ return coll.find(filter).projection(projection);
+ }else return coll.find(filter);
+
+ }
+
+ public FindIterable query(QueryRequest request, String collectionName){
+
+ FindIterable toReturn=iterate(request.getFilter(), request.getProjection(),collectionName);
+
+
+
+ if(request.getOrdering()!=null){
+ if(request.getOrdering().getDirection().equals(QueryRequest.OrderedRequest.Direction.ASCENDING))
+ toReturn=toReturn.sort(ascending(request.getOrdering().getFields()));
+ else toReturn=toReturn.sort(descending(request.getOrdering().getFields()));
+ }
+
+ //Paging
+ if(request.getPaging()!=null){
+ QueryRequest.PagedRequest paging=request.getPaging();
+ toReturn=toReturn.skip(paging.getOffset()).limit(paging.getLimit());
+ }
+
+ return toReturn;
+ }
+
+
+ public FindIterable iterateForClass(Document filter,String collectionName,Class clazz) {
+ MongoDatabase database=getDatabase();
+ MongoCollection coll=database.getCollection(collectionName);
+ if(filter==null)
+ return coll.find(clazz);
+ else
+ return coll.find(filter,clazz);
+ }
+
+ public Document replace(Document toUpdate,String collectionName) {
+ MongoDatabase database=getDatabase();
+ MongoCollection coll=database.getCollection(collectionName);
+ return coll.findOneAndReplace(
+ eq(ID,toUpdate.getObjectId(ID)), toUpdate,new FindOneAndReplaceOptions().returnDocument(ReturnDocument.AFTER));
+
+ }
+
+ public Document update(ObjectId id, Document updateSet, String collectionName) {
+ MongoDatabase database=getDatabase();
+ MongoCollection coll=database.getCollection(collectionName);
+ return coll.findOneAndUpdate(
+ eq(ID,id),
+ updateSet,
+ new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER));
+ }
+
+ //********** PROFILES
+
+
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ProfiledMongoManager.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ProfiledMongoManager.java
new file mode 100644
index 0000000..55de3e1
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/mongo/ProfiledMongoManager.java
@@ -0,0 +1,5 @@
+package org.gcube.application.geoportal.service.engine.mongo;
+
+public class ProfiledMongoManager {
+
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/postgis/PostgisDBManager.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/postgis/PostgisDBManager.java
new file mode 100644
index 0000000..ed67b0b
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/postgis/PostgisDBManager.java
@@ -0,0 +1,194 @@
+package org.gcube.application.geoportal.service.engine.postgis;
+
+import lombok.Synchronized;
+import lombok.extern.slf4j.Slf4j;
+import org.gcube.application.geoportal.common.model.legacy.BBOX;
+import org.gcube.application.geoportal.common.model.rest.DatabaseConnection;
+import org.gcube.application.geoportal.service.model.internal.db.PostgisTable;
+import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException;
+import org.gcube.application.geoportal.service.model.internal.faults.DataParsingException;
+import org.gcube.application.geoportal.service.utils.ISUtils;
+
+import java.sql.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Slf4j
+public class PostgisDBManager implements PostgisDBManagerI {
+
+ @Synchronized
+ public static PostgisDBManager get() throws SQLException, ConfigurationException {
+ if(config==null) {
+ log.debug("Looking for Default Configuration.. ");
+
+ // TODO GENERIC
+ DatabaseConnection defaultConfiguration=
+ ISUtils.queryForDB("postgis", "Concessioni");
+
+ log.debug("Found configuration : "+defaultConfiguration);
+ config=defaultConfiguration;
+ }
+ return new PostgisDBManager();
+ }
+ public static PostgisDBManagerI get(boolean autocommit) throws SQLException, ConfigurationException {
+ PostgisDBManager toReturn=get();
+ toReturn.conn.setAutoCommit(autocommit);
+ return toReturn;
+ }
+
+ private static DatabaseConnection config;
+
+
+
+
+
+
+ private static Connection getConnection() throws SQLException {
+
+ Connection toReturn= DriverManager.getConnection(config.getUrl(),config.getUser(),config.getPwd());
+
+ //TODO configure behaviour
+ toReturn.setAutoCommit(false);
+ return toReturn;
+ }
+
+
+
+ private Connection conn=null;
+
+
+ private PostgisDBManager() throws SQLException {
+ conn=getConnection();
+ }
+
+ @Override
+ public void create(PostgisTable toCreate) throws SQLException {
+ String createStmt=toCreate.getCreateStatement();
+ log.debug("Executing create : "+createStmt);
+ conn.createStatement().executeUpdate(createStmt);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.gcube.application.geoportal.PostgisDBManagerI#commit()
+ */
+ @Override
+ public void commit() throws SQLException {
+ conn.commit();
+ }
+
+// /* (non-Javadoc)
+// * @see org.gcube.application.geoportal.PostgisDBManagerI#evaluateBoundingBox(org.gcube.application.geoportal.model.PostgisTable)
+// */
+// @Override
+// public BBOX evaluateBoundingBox(PostgisTable table) throws SQLException, DataParsingException {
+// ResultSet rs=conn.createStatement().executeQuery("Select ST_Extent("+table.getGeometryColumn()+") as extent from "+table.getTablename());
+// if(rs.next())
+// return DBUtils.parseST_Extent(rs.getString("extent"));
+// else throw new SQLException("No extent returned");
+// }
+
+ /* (non-Javadoc)
+ * @see org.gcube.application.geoportal.PostgisDBManagerI#evaluateBoundingBox(org.gcube.application.geoportal.model.PostgisTable)
+ */
+ @Override
+ public PostgisTable.POINT evaluateCentroid(PostgisTable table) throws SQLException, DataParsingException {
+ ResultSet rs=conn.createStatement().executeQuery("Select ST_AsText(ST_Centroid(ST_Collect("+table.getGeometryColumn()+"))) as centroid from "+table.getTablename());
+ if(rs.next())
+ return PostgisTable.POINT.parsePOINT(rs.getString("centroid"));
+ else throw new SQLException("No extent returned");
+ }
+
+ /* (non-Javadoc)
+ * @see org.gcube.application.geoportal.PostgisDBManagerI#prepareInsertStatement(org.gcube.application.geoportal.model.PostgisTable, boolean, boolean)
+ */
+ @Override
+ public PreparedStatement prepareInsertStatement(PostgisTable target, boolean createTable, boolean geometryAsText) throws SQLException {
+ if(createTable) {
+ create(target);
+ }
+ String insertStmt=target.getInsertionStatement(geometryAsText);
+ log.debug("Preparing insert statement : "+insertStmt);
+ return conn.prepareStatement(insertStmt);
+ }
+
+
+ @Override
+ public int deleteByFieldValue(PostgisTable target, PostgisTable.Field field, Object value) throws SQLException {
+ String query=target.getDeleteByFieldStatement(field);
+ log.debug("Preparing DELETE SQL {} with field {} = {} ",query,field,value);
+
+ PreparedStatement stmt = conn.prepareStatement(query);
+ target.setObjectInPreparedStatement(field, value, stmt, 1);
+ int result=stmt.executeUpdate();
+ log.debug("DELETED {} rows ",result);
+ return result;
+ }
+
+ @Override
+ public DatabaseConnection getConnectionDescriptor() {
+ return config;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.gcube.application.geoportal.PostgisDBManagerI#deleteTable(java.lang.String)
+ */
+ @Override
+ public void deleteTable(String tableName) throws SQLException {
+ conn.createStatement().executeUpdate("DROP TABLE "+tableName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.gcube.application.geoportal.PostgisDBManagerI#truncate(java.lang.String)
+ */
+ @Override
+ public void truncate(String tableName) throws SQLException{
+ conn.createStatement().executeUpdate("TRUNCATE Table "+tableName);
+ }
+
+ @Override
+ public ResultSet queryAll(PostgisTable table) throws SQLException {
+ // TODO Check schema
+ return conn.createStatement().executeQuery("Select * from "+table.getTablename());
+ }
+
+
+ // *********************** INNER UTILS CLASS
+
+ protected static class DBUtils {
+
+
+ private static Pattern pattern = Pattern.compile("(?!=\\d\\.\\d\\.)([\\d.]+)");
+
+ public static BBOX parseST_Extent(String extent) throws DataParsingException {
+ //BOX(11.9122574810083 44.2514144864263,11.9761128271586 44.2912342569845)
+ try {
+ log.debug("Parsing BBOX "+extent);
+ Matcher m=pattern.matcher(extent);
+
+ // Scanner sc = new Scanner(extent);
+ // double minLong = sc.nextDouble(),
+ // minLat = sc.nextDouble(),
+ // maxLong = sc.nextDouble(),
+ // maxLat= sc.nextDouble();
+
+ if(!m.find()) throw new DataParsingException("Unable to get minLong ");
+ Double minLong=Double.parseDouble(m.group(1));
+
+ if(!m.find()) throw new DataParsingException("Unable to get minLat ");
+ Double minLat=Double.parseDouble(m.group(1));
+
+ if(!m.find()) throw new DataParsingException("Unable to get maxLong ");
+ Double maxLong=Double.parseDouble(m.group(1));
+
+ if(!m.find()) throw new DataParsingException("Unable to get maxLat ");
+ Double maxLat=Double.parseDouble(m.group(1));
+ return new BBOX(maxLat, maxLong, minLat, minLong);
+ }catch(Throwable t) {
+ throw new DataParsingException("Invalid BBOX "+extent,t);
+ }
+ }
+ }
+}
+
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/postgis/PostgisDBManagerI.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/postgis/PostgisDBManagerI.java
new file mode 100644
index 0000000..bd1cfb4
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/postgis/PostgisDBManagerI.java
@@ -0,0 +1,37 @@
+package org.gcube.application.geoportal.service.engine.postgis;
+
+import org.gcube.application.geoportal.common.model.rest.DatabaseConnection;
+import org.gcube.application.geoportal.service.model.internal.db.PostgisTable;
+import org.gcube.application.geoportal.service.model.internal.faults.DataParsingException;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public interface PostgisDBManagerI {
+
+ void commit() throws SQLException;
+
+
+
+
+
+ PreparedStatement prepareInsertStatement(PostgisTable target, boolean createTable, boolean geometryAsText)
+ throws SQLException;
+
+
+ void deleteTable(String tableName) throws SQLException;
+
+ void truncate(String tableName) throws SQLException;
+
+ void create(PostgisTable toCreate) throws SQLException;
+
+ PostgisTable.POINT evaluateCentroid(PostgisTable table) throws SQLException, DataParsingException;
+
+
+ ResultSet queryAll(PostgisTable table) throws SQLException;
+
+ int deleteByFieldValue(PostgisTable target, PostgisTable.Field field, Object value) throws SQLException;
+
+ DatabaseConnection getConnectionDescriptor();
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/postgis/PostgisIndex.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/postgis/PostgisIndex.java
new file mode 100644
index 0000000..9ff150f
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/postgis/PostgisIndex.java
@@ -0,0 +1,187 @@
+package org.gcube.application.geoportal.service.engine.postgis;
+
+import lombok.extern.slf4j.Slf4j;
+import org.gcube.application.geoportal.common.model.legacy.Concessione;
+import org.gcube.application.geoportal.common.model.rest.DatabaseConnection;
+import org.gcube.application.geoportal.common.model.rest.PostgisIndexDescriptor;
+import org.gcube.application.geoportal.service.engine.ImplementationProvider;
+import org.gcube.application.geoportal.service.engine.SDIManager;
+import org.gcube.application.geoportal.service.model.internal.db.DBConstants;
+import org.gcube.application.geoportal.service.model.internal.db.PostgisTable;
+import org.gcube.application.geoportal.service.model.internal.db.PostgisTable.Field;
+import org.gcube.application.geoportal.service.model.internal.db.PostgisTable.FieldType;
+import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException;
+import org.gcube.application.geoportal.service.model.internal.faults.PublishException;
+import org.gcube.application.geoportal.service.model.internal.faults.SDIInteractionException;
+import org.gcube.application.geoportal.service.utils.Serialization;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+;
+
+@Slf4j
+public class PostgisIndex {
+
+ static{
+ try {
+ Class.forName("org.postgresql.Driver");
+ Class.forName("org.postgis.DriverWrapper");
+ } catch (Exception var2) {
+ throw new RuntimeException(var2);
+ }
+ }
+
+
+ private SDIManager sdiManager;
+ private String wmsLink=null;
+ private static PostgisDBManager getDB() throws ConfigurationException {
+ return ImplementationProvider.get().getDbProvider().getObject();
+ };
+
+ public PostgisIndex() throws SDIInteractionException, SQLException, ConfigurationException {
+ super();
+ this.sdiManager=new SDIManager();
+ this.wmsLink=init();
+ }
+
+
+ public PostgisIndexDescriptor getInfo() throws ConfigurationException, SDIInteractionException, SQLException {
+ DatabaseConnection conn=getDB().getConnectionDescriptor();
+ return new PostgisIndexDescriptor(conn,wmsLink);
+ }
+
+ protected PostgisTable getCentroidsTable() {
+ return DBConstants.Concessioni.CENTROIDS;
+ }
+
+ public String init() throws SQLException, ConfigurationException, SDIInteractionException {
+ log.debug("Contacting postgis DB .. ");
+ PostgisDBManagerI db=ImplementationProvider.get().getDbProvider().getObject();
+ log.debug("Checking if centroids table exists..");
+ PostgisTable table=getCentroidsTable();
+ db.create(table);
+ db.commit();
+ return sdiManager.configureCentroidLayer("centroids_concessioni", "gna", "gna_postgis",table,db.getConnectionDescriptor());
+ }
+
+
+
+ public void registerCentroid(Concessione record) throws PublishException{
+
+ try {
+ log.debug("Evaluating Centroid");
+ Map centroidRow=evaluateCentroid(record);
+
+ log.debug("Contacting postgis DB .. ");
+ PostgisDBManagerI db=ImplementationProvider.get().getDbProvider().getObject();
+
+ PostgisTable centroidsTable=getCentroidsTable();
+ log.debug("Inserting / updated centroid Row {} ",centroidRow);
+
+ PreparedStatement ps = db.prepareInsertStatement(centroidsTable, true, true);
+
+ log.debug("Deleting centroid if present. ID is "+record.getId());
+ db.deleteByFieldValue(centroidsTable, new Field(DBConstants.Concessioni.PRODUCT_ID,FieldType.TEXT), record.getMongo_id());
+
+ centroidsTable.fillCSVPreparedStatament(centroidRow, ps, false);
+ ps.executeUpdate();
+ db.commit();
+
+
+ }catch(SQLException e) {
+ log.warn("Unable to publish Centroid for record "+record,e);
+ throw new PublishException("Unable to publish centroid.",e, null);
+ } catch (ConfigurationException e) {
+ log.warn("Unable to contact centroids db "+record.getRecordType(),e);
+ throw new PublishException("Unable to publish centroid.",e, null);
+ }
+
+ }
+
+
+
+
+ public void removeCentroid(Concessione record) {
+ try {
+ PostgisDBManagerI db=ImplementationProvider.get().getDbProvider().getObject();
+ PostgisTable centroidsTable=getCentroidsTable();
+ log.debug("Deleting centroid if present. ID is "+record.getMongo_id());
+ int result= db.deleteByFieldValue(centroidsTable, new Field(DBConstants.Concessioni.PRODUCT_ID,FieldType.TEXT), record.getMongo_id());
+ db.commit();
+ log.info("Removed {} entries from gif Index with mongo id {} ",result,record.getMongo_id());
+ }catch(Exception e) {
+ log.warn("Unable to remove centroid ",e);
+ }
+ }
+
+
+ protected static Map evaluateCentroid(Concessione record){
+
+
+ // CENTROID
+ Map centroidsRow=new HashMap();
+ centroidsRow.put(DBConstants.Concessioni.PRODUCT_ID, record.getMongo_id());
+ centroidsRow.put(DBConstants.Concessioni.ANNO, record.getDataInizioProgetto().getYear()+"");
+ centroidsRow.put(DBConstants.Concessioni.NOME, record.getNome());
+ centroidsRow.put(DBConstants.Concessioni.REGIONE, ""); //TODO
+
+
+
+ if(record.getCentroidLat()==null||record.getCentroidLat()==0)
+ try {
+ log.debug("Evaluating Centroid latitude for record "+record);
+ record.setCentroidLat((record.getPosizionamentoScavo().getBbox().getMaxLat()+
+ record.getPosizionamentoScavo().getBbox().getMinLat())/2);
+ }catch (Throwable t) {
+ log.warn("Unable to evaluate centroid latitude "+t);
+ }
+
+ if(record.getCentroidLong()==null||record.getCentroidLong()==0)
+ try {
+ log.debug("Evaluating Centroid Longituted for record "+record);
+ record.setCentroidLong((record.getPosizionamentoScavo().getBbox().getMaxLong()+
+ record.getPosizionamentoScavo().getBbox().getMinLong())/2);
+ }catch (Throwable t) {
+ log.warn("Unable to evaluate centroid latitude "+t);
+ }
+
+
+ centroidsRow.put(DBConstants.Defaults.XCOORD_FIELD, record.getCentroidLong()+"");
+ centroidsRow.put(DBConstants.Defaults.YCOORD_FIELD, record.getCentroidLat()+"");
+
+ //Updated Schema
+ centroidsRow.put(DBConstants.Concessioni.DESCRIZIONE,record.getIntroduzione());
+ centroidsRow.put(DBConstants.Concessioni.CONTENUTO,record.getDescrizioneContenuto());
+ centroidsRow.put(DBConstants.Concessioni.AUTORE,asString(record.getAuthors()));
+ centroidsRow.put(DBConstants.Concessioni.CONTRIBUTORE,record.getContributore());
+ centroidsRow.put(DBConstants.Concessioni.TITOLARE,asString(record.getTitolari()));
+ centroidsRow.put(DBConstants.Concessioni.RESPONSABILE,record.getResponsabile());
+ centroidsRow.put(DBConstants.Concessioni.EDITORE,record.getEditore());
+ centroidsRow.put(DBConstants.Concessioni.FINANZIAMENTO,asString(record.getFontiFinanziamento()));
+ centroidsRow.put(DBConstants.Concessioni.SOGGETTO,asString(record.getSoggetto()));
+ centroidsRow.put(DBConstants.Concessioni.RISORSE,asString(record.getRisorseCorrelate()));
+ centroidsRow.put(DBConstants.Concessioni.DATE_SCAVO,Serialization.FULL_FORMATTER.format(record.getDataFineProgetto()));
+ centroidsRow.put(DBConstants.Concessioni.DATA_ARCHIVIAZIONE,Serialization.FULL_FORMATTER.format(record.getLastUpdateTime()));
+ centroidsRow.put(DBConstants.Concessioni.VERSIONE,record.getVersion());
+ centroidsRow.put(DBConstants.Concessioni.LICENZA,record.getLicenzaID());
+ centroidsRow.put(DBConstants.Concessioni.TITOLARE_LICENZA,asString(record.getTitolareLicenza()));
+ centroidsRow.put(DBConstants.Concessioni.ACCESSO,record.getPolicy().toString());
+ centroidsRow.put(DBConstants.Concessioni.PAROLE_CHIAVE,asString(record.getParoleChiaveLibere()));
+
+ return centroidsRow;
+ }
+
+
+ private static String asString(Collection> coll) {
+ if(coll==null||coll.isEmpty()) return "";
+ StringBuilder builder=new StringBuilder();
+ for(Object t : coll) {
+ builder.append(t.toString() +",");
+ }
+ return builder.substring(0, builder.lastIndexOf(","));
+ }
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/AbstractScopedMap.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/AbstractScopedMap.java
new file mode 100644
index 0000000..50f4871
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/AbstractScopedMap.java
@@ -0,0 +1,67 @@
+package org.gcube.application.geoportal.service.engine.providers;
+
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import lombok.Synchronized;
+import lombok.extern.slf4j.Slf4j;
+import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException;
+import org.gcube.application.geoportal.service.utils.ContextUtils;
+
+import java.time.LocalDateTime;
+import java.time.temporal.TemporalAmount;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Slf4j
+@RequiredArgsConstructor
+public abstract class AbstractScopedMap implements Engine{
+
+ // scope-> object
+ private ConcurrentHashMap> scopeMap=new ConcurrentHashMap>();
+
+ @Setter
+ private TemporalAmount TTL=null;
+
+ @NonNull
+ private String name;
+ @Synchronized
+ public T getObject() throws ConfigurationException {
+ String currentScope=ContextUtils.getCurrentScope();
+ log.debug(name+" : obtaining object for context "+currentScope);
+
+ TTLObject found=scopeMap.get(currentScope);
+
+ if(found== null){
+ log.debug(name+" : init object for context "+currentScope);
+ TTLObject toPut=new TTLObject(LocalDateTime.now(),retrieveObject());
+ scopeMap.put(currentScope, toPut);
+ return toPut.getTheObject();
+ }
+
+ if(TTL!=null) {
+ if(!found.getCreationTime().plus(TTL).isBefore(LocalDateTime.now())) {
+ log.debug(name+" : elapsed TTL, disposing..");
+ dispose(found.getTheObject());
+ found=scopeMap.put(currentScope, new TTLObject(LocalDateTime.now(),retrieveObject()));
+ }
+ }else {log.debug(name+" : TTL is null, never disposing..");}
+ return found.getTheObject();
+ }
+
+
+ @Override
+ public void shustdown() {
+ log.warn(name + ": shutting down");
+ scopeMap.forEach((String s,TTLObject o)->{
+ try{if(o!=null&&o.getTheObject()!=null)
+ dispose(o.getTheObject());
+ }catch(Throwable t) {
+ log.warn(name +": unable to dispose ",t);
+ }
+ });
+ }
+
+ protected abstract T retrieveObject() throws ConfigurationException;
+
+ protected abstract void dispose(T toDispose);
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/Engine.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/Engine.java
new file mode 100644
index 0000000..0e93075
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/Engine.java
@@ -0,0 +1,12 @@
+package org.gcube.application.geoportal.service.engine.providers;
+
+import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException;
+
+
+public interface Engine {
+
+ public void init();
+ public void shustdown();
+
+ public T getObject() throws ConfigurationException;
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/MongoClientProvider.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/MongoClientProvider.java
new file mode 100644
index 0000000..a8d15d5
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/MongoClientProvider.java
@@ -0,0 +1,47 @@
+package org.gcube.application.geoportal.service.engine.providers;
+
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
+import lombok.extern.slf4j.Slf4j;
+import org.gcube.application.geoportal.service.engine.ImplementationProvider;
+import org.gcube.application.geoportal.service.model.internal.db.MongoConnection;
+import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException;
+
+@Slf4j
+public class MongoClientProvider extends AbstractScopedMap{
+
+ public MongoClientProvider() {
+ super("MongoClient cache");
+
+// setTTL(Duration.of(10, ChronoUnit.MINUTES));
+ }
+
+ @Override
+ protected MongoClient retrieveObject() throws ConfigurationException {
+ MongoConnection conn=ImplementationProvider.get().getMongoConnectionProvider().getObject();
+ log.debug("Connecting to "+conn);
+
+ MongoCredential credential = MongoCredential.createCredential(conn.getUser(), conn.getDatabase(),
+ conn.getPassword().toCharArray());
+
+
+
+ MongoClientOptions options = MongoClientOptions.builder().sslEnabled(true).build();
+
+ return new MongoClient(new ServerAddress(conn.getHosts().get(0),conn.getPort()),
+ credential,
+ options);
+ }
+
+ @Override
+ protected void dispose(MongoClient toDispose) {
+ toDispose.close();
+ }
+
+ @Override
+ public void init() {
+ // TODO Auto-generated method stub
+ }
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/MongoConnectionProvider.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/MongoConnectionProvider.java
new file mode 100644
index 0000000..9833b26
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/MongoConnectionProvider.java
@@ -0,0 +1,32 @@
+package org.gcube.application.geoportal.service.engine.providers;
+
+import org.gcube.application.geoportal.service.ServiceConstants;
+import org.gcube.application.geoportal.service.model.internal.db.MongoConnection;
+import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException;
+import org.gcube.application.geoportal.service.utils.ISUtils;
+
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
+
+public class MongoConnectionProvider extends AbstractScopedMap{
+
+ public MongoConnectionProvider() {
+ super("MongoDBInfo Cache");
+ setTTL(Duration.of(2,ChronoUnit.MINUTES));
+ }
+
+ @Override
+ protected MongoConnection retrieveObject() throws ConfigurationException {
+ return ISUtils.queryForMongoDB(ServiceConstants.MONGO_SE_PLATFORM, ServiceConstants.MONGO_SE_GNA_FLAG);
+ }
+
+ @Override
+ protected void dispose(MongoConnection toDispose) {
+
+ }
+
+ @Override
+ public void init() {
+ // TODO Auto-generated method stub
+ }
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/PostgisConnectionProvider.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/PostgisConnectionProvider.java
new file mode 100644
index 0000000..26a2e9c
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/PostgisConnectionProvider.java
@@ -0,0 +1,33 @@
+package org.gcube.application.geoportal.service.engine.providers;
+
+import org.gcube.application.geoportal.service.engine.postgis.PostgisDBManager;
+import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException;
+
+import java.sql.SQLException;
+
+public class PostgisConnectionProvider extends AbstractScopedMap{
+
+
+ public PostgisConnectionProvider() {
+ super("Postgis connection descriptor cache");
+ }
+
+ @Override
+ protected PostgisDBManager retrieveObject() throws ConfigurationException {
+ try {
+ return PostgisDBManager.get();
+ } catch (SQLException throwables) {
+ throw new ConfigurationException(throwables);
+ }
+ }
+
+ @Override
+ protected void dispose(PostgisDBManager toDispose) {
+// toDispose.close();
+ }
+
+ @Override
+ public void init() {
+//
+ }
+}
diff --git a/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/ProfileMapCache.java b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/ProfileMapCache.java
new file mode 100644
index 0000000..d9a8eb4
--- /dev/null
+++ b/geoportal-service/src/main/java/org/gcube/application/geoportal/service/engine/providers/ProfileMapCache.java
@@ -0,0 +1,34 @@
+package org.gcube.application.geoportal.service.engine.providers;
+
+import org.gcube.application.geoportal.common.model.profile.Profile;
+import org.gcube.application.geoportal.service.model.internal.faults.ConfigurationException;
+
+import java.util.Map;
+
+
+public class ProfileMapCache extends AbstractScopedMap