1# =================================================================
2#
3# Authors: Tom Kralidis <tomkralidis@gmail.com>
4#
5# Copyright (c) 2021 Tom Kralidis
6#
7# Permission is hereby granted, free of charge, to any person
8# obtaining a copy of this software and associated documentation
9# files (the "Software"), to deal in the Software without
10# restriction, including without limitation the rights to use,
11# copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the
13# Software is furnished to do so, subject to the following
14# conditions:
15#
16# The above copyright notice and this permission notice shall be
17# included in all copies or substantial portions of the Software.
18#
19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26# OTHER DEALINGS IN THE SOFTWARE.
27#
28# =================================================================
29
30import logging
31
32LOGGER = logging.getLogger(__name__)
33
34
35class BaseProvider:
36    """generic Provider ABC"""
37
38    def __init__(self, provider_def):
39        """
40        Initialize object
41
42        :param provider_def: provider definition
43
44        :returns: pygeoapi.provider.base.BaseProvider
45        """
46
47        try:
48            self.name = provider_def['name']
49            self.type = provider_def['type']
50            self.data = provider_def['data']
51        except KeyError:
52            raise RuntimeError('name/type/data are required')
53
54        self.options = provider_def.get('options', None)
55        self.id_field = provider_def.get('id_field', None)
56        self.uri_field = provider_def.get('uri_field', None)
57        self.x_field = provider_def.get('x_field', None)
58        self.y_field = provider_def.get('y_field', None)
59        self.time_field = provider_def.get('time_field')
60        self.title_field = provider_def.get('title_field')
61        self.properties = provider_def.get('properties', [])
62        self.file_types = provider_def.get('file_types', [])
63        self.fields = {}
64
65        # for coverage providers
66        self.axes = []
67        self.crs = None
68        self.num_bands = None
69
70    def get_fields(self):
71        """
72        Get provider field information (names, types)
73
74        :returns: dict of fields
75        """
76
77        raise NotImplementedError()
78
79    def get_data_path(self, baseurl, urlpath, dirpath):
80        """
81        Gets directory listing or file description or raw file dump
82
83        :param baseurl: base URL of endpoint
84        :param urlpath: base path of URL
85        :param dirpath: directory basepath (equivalent of URL)
86
87        :returns: `dict` of file listing or `dict` of GeoJSON item or raw file
88        """
89
90        raise NotImplementedError()
91
92    def get_metadata(self):
93        """
94        Provide data/file metadata
95
96        :returns: `dict` of metadata construct (format
97                  determined by provider/standard)
98        """
99
100        raise NotImplementedError()
101
102    def query(self):
103        """
104        query the provider
105
106        :returns: dict of 0..n GeoJSON features or coverage data
107        """
108
109        raise NotImplementedError()
110
111    def get(self, identifier):
112        """
113        query the provider by id
114
115        :param identifier: feature id
116        :returns: dict of single GeoJSON feature
117        """
118
119        raise NotImplementedError()
120
121    def create(self, new_feature):
122        """Create a new feature
123        """
124
125        raise NotImplementedError()
126
127    def update(self, identifier, new_feature):
128        """Updates an existing feature id with new_feature
129
130        :param identifier: feature id
131        :param new_feature: new GeoJSON feature dictionary
132        """
133
134        raise NotImplementedError()
135
136    def get_coverage_domainset(self):
137        """
138        Provide coverage domainset
139
140        :returns: CIS JSON object of domainset metadata
141        """
142
143        raise NotImplementedError()
144
145    def get_coverage_rangetype(self):
146        """
147        Provide coverage rangetype
148
149        :returns: CIS JSON object of rangetype metadata
150        """
151
152        raise NotImplementedError()
153
154    def delete(self, identifier):
155        """Deletes an existing feature
156
157        :param identifier: feature id
158        """
159
160        raise NotImplementedError()
161
162    def __repr__(self):
163        return '<BaseProvider> {}'.format(self.type)
164
165
166class ProviderGenericError(Exception):
167    """provider generic error"""
168    pass
169
170
171class ProviderConnectionError(ProviderGenericError):
172    """provider connection error"""
173    pass
174
175
176class ProviderTypeError(ProviderGenericError):
177    """provider type error"""
178    pass
179
180
181class ProviderInvalidQueryError(ProviderGenericError):
182    """provider invalid query error"""
183    pass
184
185
186class ProviderQueryError(ProviderGenericError):
187    """provider query error"""
188    pass
189
190
191class ProviderItemNotFoundError(ProviderGenericError):
192    """provider item not found query error"""
193    pass
194
195
196class ProviderNoDataError(ProviderGenericError):
197    """provider no data error"""
198    pass
199
200
201class ProviderNotFoundError(ProviderGenericError):
202    """provider not found error"""
203    pass
204
205
206class ProviderVersionError(ProviderGenericError):
207    """provider incorrect version error"""
208    pass
209