OneStop4All-Indexer 2.7.1__tar.gz → 2.8.0.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2/OneStop4All_Indexer.egg-info}/PKG-INFO +1 -1
- {onestop4all_indexer-2.7.1/OneStop4All_Indexer.egg-info → onestop4all_indexer-2.8.0.dev2}/PKG-INFO +1 -1
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_dataset.py +25 -10
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_repository.py +21 -9
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/setup.py +1 -1
- onestop4all_indexer-2.8.0.dev2/utils/configs.py +89 -0
- onestop4all_indexer-2.7.1/utils/configs.py +0 -44
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/LICENSE +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/OneStop4All_Indexer.egg-info/SOURCES.txt +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/OneStop4All_Indexer.egg-info/dependency_links.txt +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/OneStop4All_Indexer.egg-info/entry_points.txt +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/OneStop4All_Indexer.egg-info/requires.txt +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/OneStop4All_Indexer.egg-info/top_level.txt +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/data_repositories/__init__.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/data_repositories/repository_base.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/data_repositories/repository_n4eorganization.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/data_repositories/repository_person.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/data_repositories/repository_resource_links.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/data_repositories/repository_theme.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/__init__.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_article.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_base.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_dataservice.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_document.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_learningresource.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_metadatastandards.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_organization.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_service.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_softwaresourcecode.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/pyproject.toml +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/setup.cfg +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/utils/__init__.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/utils/cli.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/utils/harvest.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/utils/solr.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/utils/sparql.py +0 -0
- {onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/utils/util.py +0 -0
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2/OneStop4All_Indexer.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OneStop4All-Indexer
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0.dev2
|
|
4
4
|
Summary: Library to harvest data from NFDI4Earth-KnowledgeHub to OneStop4All-Index
|
|
5
5
|
Author: Markus Konkol, Arne Vogt, Tom Niers, Ralf Klammer
|
|
6
6
|
Author-email: m.konkol@52north.org, a.vogt@52north.org, tom.niers@tu-dresden.de, ralf.klammer@tu-dresden.de
|
{onestop4all_indexer-2.7.1/OneStop4All_Indexer.egg-info → onestop4all_indexer-2.8.0.dev2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OneStop4All-Indexer
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0.dev2
|
|
4
4
|
Summary: Library to harvest data from NFDI4Earth-KnowledgeHub to OneStop4All-Index
|
|
5
5
|
Author: Markus Konkol, Arne Vogt, Tom Niers, Ralf Klammer
|
|
6
6
|
Author-email: m.konkol@52north.org, a.vogt@52north.org, tom.niers@tu-dresden.de, ralf.klammer@tu-dresden.de
|
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_dataset.py
RENAMED
|
@@ -24,9 +24,9 @@ class Dataset_Harvester(HarvesterCordra):
|
|
|
24
24
|
iteration_end=None,
|
|
25
25
|
page_size=50000,
|
|
26
26
|
query='type:"Dataset"',
|
|
27
|
-
#query='id:"n4e/dthb-oai-pangaea.de-doi-10.1594-PANGAEA.981078"', #downloadURL: https://cordra.knowledgehub.test.n4e.geo.tu-dresden.de/objects/n4e/dthb-oai-pangaea.de-doi-10.1594-PANGAEA.981078
|
|
28
|
-
#query='id:"n4e/dthb-GB_NERC_BAS_PDC_01994"', #accessURL: https://cordra.knowledgehub.test.n4e.geo.tu-dresden.de/objects/n4e/dthb-GB_NERC_BAS_PDC_01994
|
|
29
|
-
#query='id:"n4e/dthb-6A0D8B9D-1BBD-441B-BA5C-6159EE41EE71"', #multiple accessURLs: https://cordra.knowledgehub.nfdi4earth.de/objects/n4e/dthb-6A0D8B9D-1BBD-441B-BA5C-6159EE41EE71,
|
|
27
|
+
# query='id:"n4e/dthb-oai-pangaea.de-doi-10.1594-PANGAEA.981078"', #downloadURL: https://cordra.knowledgehub.test.n4e.geo.tu-dresden.de/objects/n4e/dthb-oai-pangaea.de-doi-10.1594-PANGAEA.981078
|
|
28
|
+
# query='id:"n4e/dthb-GB_NERC_BAS_PDC_01994"', #accessURL: https://cordra.knowledgehub.test.n4e.geo.tu-dresden.de/objects/n4e/dthb-GB_NERC_BAS_PDC_01994
|
|
29
|
+
# query='id:"n4e/dthb-6A0D8B9D-1BBD-441B-BA5C-6159EE41EE71"', #multiple accessURLs: https://cordra.knowledgehub.nfdi4earth.de/objects/n4e/dthb-6A0D8B9D-1BBD-441B-BA5C-6159EE41EE71,
|
|
30
30
|
solr_validation=True,
|
|
31
31
|
**kw,
|
|
32
32
|
):
|
|
@@ -35,9 +35,15 @@ class Dataset_Harvester(HarvesterCordra):
|
|
|
35
35
|
self.links_repo = links_repo
|
|
36
36
|
self.removed_geometries = []
|
|
37
37
|
self.solr_validator = SolrValidator()
|
|
38
|
-
self.iteration_start =
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
self.iteration_start = (
|
|
39
|
+
int(iteration_start)
|
|
40
|
+
if iteration_start is not None
|
|
41
|
+
else iteration_start
|
|
42
|
+
)
|
|
43
|
+
self.iteration_end = (
|
|
44
|
+
int(iteration_end) if iteration_end is not None else iteration_end
|
|
45
|
+
)
|
|
46
|
+
self.page_size = int(page_size) if page_size is not None else page_size
|
|
41
47
|
self.query = query
|
|
42
48
|
self.solr_validation = solr_validation
|
|
43
49
|
log.info("#" * 20)
|
|
@@ -277,7 +283,9 @@ class Dataset_Harvester(HarvesterCordra):
|
|
|
277
283
|
if val:
|
|
278
284
|
self.addValue(
|
|
279
285
|
dict=datasets[subject],
|
|
280
|
-
attribute="distribution"
|
|
286
|
+
attribute="distribution"
|
|
287
|
+
+ self.flatten_separator
|
|
288
|
+
+ "accessURL",
|
|
281
289
|
value=val,
|
|
282
290
|
)
|
|
283
291
|
if "title" in distribution:
|
|
@@ -288,16 +296,23 @@ class Dataset_Harvester(HarvesterCordra):
|
|
|
288
296
|
if val:
|
|
289
297
|
self.addValue(
|
|
290
298
|
dict=datasets[subject],
|
|
291
|
-
attribute="distribution"
|
|
299
|
+
attribute="distribution"
|
|
300
|
+
+ self.flatten_separator
|
|
301
|
+
+ "title",
|
|
292
302
|
value=val,
|
|
293
303
|
)
|
|
294
304
|
if "downloadURL" in distribution:
|
|
305
|
+
print(distribution["downloadURL"])
|
|
295
306
|
for download_url in distribution["downloadURL"]:
|
|
296
|
-
val = self.get_string_from_jsonld(
|
|
307
|
+
val = self.get_string_from_jsonld(
|
|
308
|
+
download_url, subject
|
|
309
|
+
)
|
|
297
310
|
if val:
|
|
298
311
|
self.addValue(
|
|
299
312
|
dict=datasets[subject],
|
|
300
|
-
attribute="distribution"
|
|
313
|
+
attribute="distribution"
|
|
314
|
+
+ self.flatten_separator
|
|
315
|
+
+ "downloadURL",
|
|
301
316
|
value=val,
|
|
302
317
|
)
|
|
303
318
|
elif key == "spatialCoverage":
|
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_repository.py
RENAMED
|
@@ -27,7 +27,7 @@ class Repository_Harvester(Harvester):
|
|
|
27
27
|
{
|
|
28
28
|
?subject rdf:type ?type.
|
|
29
29
|
?subject ?predicate ?object.
|
|
30
|
-
FILTER (?predicate NOT IN (dct:publisher, dcat:distribution, dcat:contactPoint))
|
|
30
|
+
FILTER (?predicate NOT IN (dct:publisher, dcat:distribution, dcat:contactPoint, n4e:hasCertificate))
|
|
31
31
|
}
|
|
32
32
|
UNION{
|
|
33
33
|
VALUES ?predicate { dct:publisher }
|
|
@@ -44,6 +44,13 @@ class Repository_Harvester(Harvester):
|
|
|
44
44
|
?metadataStandard dct:title ?object.
|
|
45
45
|
optional {?metadataStandard n4e:hasWebsite ?metadataStandard_homepage.}
|
|
46
46
|
}
|
|
47
|
+
UNION {
|
|
48
|
+
VALUES ?predicate { n4e:hasCertificate }
|
|
49
|
+
?subject rdf:type ?type;
|
|
50
|
+
n4e:hasCertificate ?certificate.
|
|
51
|
+
optional { ?certificate n4e:certificateName ?certificate_name }
|
|
52
|
+
bind(coalesce(?certificate_name, ?certificate) as ?object)
|
|
53
|
+
}
|
|
47
54
|
UNION {
|
|
48
55
|
VALUES ?predicate { dcat:contactPoint }
|
|
49
56
|
?subject rdf:type ?type;
|
|
@@ -157,9 +164,8 @@ class Repository_Harvester(Harvester):
|
|
|
157
164
|
|
|
158
165
|
#execute additional sparql query to determine if (some) datasets in this repository are harvested by n4e
|
|
159
166
|
#key = subject
|
|
160
|
-
has_harvested_datasets = self.request_has_harvested_datasets(repo_subject=key)
|
|
161
|
-
repo["isHarvestedByNFDI4Earth"] = has_harvested_datasets
|
|
162
|
-
|
|
167
|
+
has_harvested_datasets = self.request_has_harvested_datasets(repo_subject=key, repo=repo)
|
|
168
|
+
repo["isHarvestedByNFDI4Earth"] = has_harvested_datasets
|
|
163
169
|
|
|
164
170
|
return repos_list
|
|
165
171
|
|
|
@@ -536,7 +542,7 @@ class Repository_Harvester(Harvester):
|
|
|
536
542
|
r["object"]["value"],
|
|
537
543
|
)
|
|
538
544
|
|
|
539
|
-
def request_has_harvested_datasets(self, repo_subject):
|
|
545
|
+
def request_has_harvested_datasets(self, repo_subject, repo=None):
|
|
540
546
|
sparql_query = """
|
|
541
547
|
PREFIX n4e: <http://nfdi4earth.de/ontology/>
|
|
542
548
|
select COUNT(?s) AS ?datasetCount
|
|
@@ -552,7 +558,13 @@ class Repository_Harvester(Harvester):
|
|
|
552
558
|
|
|
553
559
|
if not hits or not hits[0]:
|
|
554
560
|
return False
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
561
|
+
|
|
562
|
+
# Check for Earth Data Portal repo
|
|
563
|
+
if repo is not None and (
|
|
564
|
+
repo["id"] == "n4e-service0044"
|
|
565
|
+
or "Earth Data Portal" in repo["title"]):
|
|
566
|
+
return True
|
|
567
|
+
|
|
568
|
+
count = int(hits[0]["datasetCount"]["value"])
|
|
569
|
+
has_harvested_datasets = count > 0
|
|
570
|
+
return has_harvested_datasets
|
|
@@ -2,7 +2,7 @@ from setuptools import find_packages, setup
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="OneStop4All-Indexer",
|
|
5
|
-
version="2.
|
|
5
|
+
version="2.8.0.dev2",
|
|
6
6
|
description="Library to harvest data from NFDI4Earth-KnowledgeHub to OneStop4All-Index",
|
|
7
7
|
author="Markus Konkol, Arne Vogt, Tom Niers, Ralf Klammer",
|
|
8
8
|
author_email="m.konkol@52north.org, a.vogt@52north.org, tom.niers@tu-dresden.de, ralf.klammer@tu-dresden.de",
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from jproperties import Properties
|
|
4
|
+
|
|
5
|
+
log = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
app_properties = Properties()
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
with open("./application.properties", "rb") as config_file:
|
|
12
|
+
app_properties.load(config_file)
|
|
13
|
+
except FileNotFoundError:
|
|
14
|
+
app_properties = Properties()
|
|
15
|
+
log.warning(
|
|
16
|
+
"Warnung: application.properties not found! "
|
|
17
|
+
"Using default values and environment variables only."
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def parse_bool_config(value):
|
|
22
|
+
if value.lower() in ["false", "0", "f", "no", "n"]:
|
|
23
|
+
return False
|
|
24
|
+
elif value.lower() in ["true", "1", "t", "yes", "y"]:
|
|
25
|
+
return True
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# merge env variables and application.properties
|
|
29
|
+
# if env varible is set override application.properties
|
|
30
|
+
config = {
|
|
31
|
+
"cordra_endpoint": os.getenv(
|
|
32
|
+
"CORDRA_ENDPOINT",
|
|
33
|
+
default=(
|
|
34
|
+
app_properties.get("cordra_endpoint").data
|
|
35
|
+
if app_properties.get("cordra_endpoint")
|
|
36
|
+
else None
|
|
37
|
+
),
|
|
38
|
+
),
|
|
39
|
+
"sparql_endpoint": os.getenv(
|
|
40
|
+
"SPARQL_ENDPOINT",
|
|
41
|
+
default=(
|
|
42
|
+
app_properties.get("sparql_endpoint").data
|
|
43
|
+
if app_properties.get("sparql_endpoint")
|
|
44
|
+
else None
|
|
45
|
+
),
|
|
46
|
+
),
|
|
47
|
+
"solr_auth": os.getenv(
|
|
48
|
+
"SOLR_AUTH",
|
|
49
|
+
default=(
|
|
50
|
+
app_properties.get("solr_auth").data
|
|
51
|
+
if app_properties.get("solr_auth")
|
|
52
|
+
else None
|
|
53
|
+
),
|
|
54
|
+
),
|
|
55
|
+
"solr_core": os.getenv(
|
|
56
|
+
"SOLR_CORE",
|
|
57
|
+
default=(
|
|
58
|
+
app_properties.get("solr_core").data
|
|
59
|
+
if app_properties.get("solr_core")
|
|
60
|
+
else None
|
|
61
|
+
),
|
|
62
|
+
),
|
|
63
|
+
"solr_url": os.getenv(
|
|
64
|
+
"SOLR_URL",
|
|
65
|
+
default=(
|
|
66
|
+
app_properties.get("solr_url").data
|
|
67
|
+
if app_properties.get("solr_url")
|
|
68
|
+
else None
|
|
69
|
+
),
|
|
70
|
+
),
|
|
71
|
+
"mailserver_url": os.getenv(
|
|
72
|
+
"MAILSERVER_URL",
|
|
73
|
+
default=(
|
|
74
|
+
app_properties.get("mailserver_url").data
|
|
75
|
+
if app_properties.get("mailserver_url")
|
|
76
|
+
else None
|
|
77
|
+
),
|
|
78
|
+
),
|
|
79
|
+
"reset_index": parse_bool_config(
|
|
80
|
+
os.getenv(
|
|
81
|
+
"RESET_INDEX",
|
|
82
|
+
default=(
|
|
83
|
+
app_properties.get("reset_index").data
|
|
84
|
+
if app_properties.get("reset_index")
|
|
85
|
+
else None
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
),
|
|
89
|
+
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from jproperties import Properties
|
|
3
|
-
|
|
4
|
-
app_properties = Properties()
|
|
5
|
-
|
|
6
|
-
with open("./application.properties", "rb") as config_file:
|
|
7
|
-
app_properties.load(config_file)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def parse_bool_config(value):
|
|
11
|
-
if value.lower() in ["false", "0", "f", "no", "n"]:
|
|
12
|
-
return False
|
|
13
|
-
elif value.lower() in ["true", "1", "t", "yes", "y"]:
|
|
14
|
-
return True
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# merge env variables and application.properties
|
|
18
|
-
# if env varible is set override application.properties
|
|
19
|
-
config = {
|
|
20
|
-
"cordra_endpoint": os.getenv(
|
|
21
|
-
"CORDRA_ENDPOINT", default=app_properties.get("cordra_endpoint").data
|
|
22
|
-
),
|
|
23
|
-
"sparql_endpoint": os.getenv(
|
|
24
|
-
"SPARQL_ENDPOINT", default=app_properties.get("sparql_endpoint").data
|
|
25
|
-
),
|
|
26
|
-
"solr_auth": os.getenv(
|
|
27
|
-
"SOLR_AUTH", default=app_properties.get("solr_auth").data
|
|
28
|
-
),
|
|
29
|
-
"solr_core": os.getenv(
|
|
30
|
-
"SOLR_CORE", default=app_properties.get("solr_core").data
|
|
31
|
-
),
|
|
32
|
-
"solr_url": os.getenv(
|
|
33
|
-
"SOLR_URL", default=app_properties.get("solr_url").data
|
|
34
|
-
),
|
|
35
|
-
"mailserver_url": os.getenv(
|
|
36
|
-
"MAILSERVER_URL", default=app_properties.get("mailserver_url").data
|
|
37
|
-
),
|
|
38
|
-
"reset_index": parse_bool_config(
|
|
39
|
-
os.getenv(
|
|
40
|
-
"RESET_INDEX",
|
|
41
|
-
default=app_properties.get("reset_index").data,
|
|
42
|
-
)
|
|
43
|
-
),
|
|
44
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/data_repositories/repository_base.py
RENAMED
|
File without changes
|
|
File without changes
|
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/data_repositories/repository_person.py
RENAMED
|
File without changes
|
|
File without changes
|
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/data_repositories/repository_theme.py
RENAMED
|
File without changes
|
|
File without changes
|
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_article.py
RENAMED
|
File without changes
|
|
File without changes
|
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_dataservice.py
RENAMED
|
File without changes
|
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_document.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_organization.py
RENAMED
|
File without changes
|
{onestop4all_indexer-2.7.1 → onestop4all_indexer-2.8.0.dev2}/harvesters/harvester_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|