154 lines
5.5 KiB
Python
154 lines
5.5 KiB
Python
from __future__ import annotations
|
|
|
|
from pydantic import BaseModel
|
|
|
|
from app.core.errors import AppError
|
|
from app.providers.base import ProviderCapability
|
|
from app.providers.fixture import FixtureProvider
|
|
from app.providers.grb import GRBProvider
|
|
from app.providers.manual import ManualProvider
|
|
from app.providers.osm import OSMProvider
|
|
|
|
|
|
class ProviderDatasetMapping(BaseModel):
|
|
provider_name: str
|
|
dataset_role: str
|
|
source_name: str
|
|
reference_required: bool
|
|
write_path: str = "DatasetService"
|
|
|
|
|
|
class ProviderImportResult(BaseModel):
|
|
provider_name: str
|
|
status: str
|
|
message: str
|
|
requested_layers: list[str]
|
|
dataset_id: str | None = None
|
|
dataset_role: str | None = None
|
|
source_name: str | None = None
|
|
|
|
|
|
class ExternalProviderRegistry:
|
|
def __init__(self) -> None:
|
|
self.providers = {
|
|
"grb": GRBProvider(),
|
|
"osm": OSMProvider(),
|
|
"manual": ManualProvider(),
|
|
"fixture": FixtureProvider(),
|
|
}
|
|
|
|
def list_capabilities(self) -> list[ProviderCapability]:
|
|
return [provider.capability for provider in self.providers.values()]
|
|
|
|
def get(self, provider_name: str):
|
|
normalized = provider_name.strip().lower()
|
|
if normalized not in self.providers:
|
|
raise AppError(code="PROVIDER_NOT_FOUND", message="Provider not found", status_code=404)
|
|
return self.providers[normalized]
|
|
|
|
def fetch(self, provider_name: str, project_id: str, area_id: str | None, layers: list[str]) -> dict:
|
|
provider = self.get(provider_name)
|
|
return provider.fetch(project_id=project_id, area_id=area_id, layers=layers)
|
|
|
|
def dataset_mapping(self, provider_name: str, requested_dataset_role: str | None = None) -> ProviderDatasetMapping:
|
|
provider = self.get(provider_name)
|
|
if provider.provider_name == "osm":
|
|
dataset_role = "reference" if requested_dataset_role == "reference" else "source"
|
|
return ProviderDatasetMapping(
|
|
provider_name="osm",
|
|
dataset_role=dataset_role,
|
|
source_name="osm",
|
|
reference_required=requested_dataset_role == "reference",
|
|
)
|
|
return ProviderDatasetMapping(
|
|
provider_name=provider.provider_name,
|
|
dataset_role="reference",
|
|
source_name=provider.provider_name,
|
|
reference_required=True,
|
|
)
|
|
|
|
def import_contract(
|
|
self,
|
|
provider_name: str,
|
|
project_id: str,
|
|
area_id: str | None,
|
|
layers: list[str],
|
|
requested_dataset_role: str | None = None,
|
|
) -> ProviderImportResult:
|
|
del project_id, area_id
|
|
provider = self.get(provider_name)
|
|
mapping = self.dataset_mapping(provider.provider_name, requested_dataset_role=requested_dataset_role)
|
|
if provider.provider_name == "grb":
|
|
return ProviderImportResult(
|
|
provider_name="grb",
|
|
status="bounded_request_required",
|
|
message=(
|
|
"Use the governed project GRB acquisition endpoint with an EPSG:4326 bounding box "
|
|
"and one supported layer."
|
|
),
|
|
requested_layers=layers,
|
|
dataset_role=mapping.dataset_role,
|
|
source_name=mapping.source_name,
|
|
)
|
|
if provider.provider_name == "osm":
|
|
return ProviderImportResult(
|
|
provider_name=provider.provider_name,
|
|
status="not_configured",
|
|
message=f"No live {provider.display_name} import is configured.",
|
|
requested_layers=layers,
|
|
dataset_role=mapping.dataset_role,
|
|
source_name=mapping.source_name,
|
|
)
|
|
if provider.provider_name == "manual":
|
|
return ProviderImportResult(
|
|
provider_name="manual",
|
|
status="upload_flow_required",
|
|
message="Manual provider data must use the existing dataset upload/reference flow.",
|
|
requested_layers=layers,
|
|
dataset_role=mapping.dataset_role,
|
|
source_name=mapping.source_name,
|
|
)
|
|
return ProviderImportResult(
|
|
provider_name="fixture",
|
|
status="fixture_flow_required",
|
|
message="Fixture provider data must use checked-in demo/test fixture flows.",
|
|
requested_layers=layers,
|
|
dataset_role=mapping.dataset_role,
|
|
source_name=mapping.source_name,
|
|
)
|
|
|
|
|
|
_registry = ExternalProviderRegistry()
|
|
|
|
|
|
def list_provider_capabilities() -> list[ProviderCapability]:
|
|
return _registry.list_capabilities()
|
|
|
|
|
|
def get_provider(provider_name: str):
|
|
return _registry.get(provider_name)
|
|
|
|
|
|
def fetch_provider_data(provider_name: str, project_id: str, area_id: str | None, layers: list[str]) -> dict:
|
|
return _registry.fetch(provider_name, project_id, area_id, layers)
|
|
|
|
|
|
def get_provider_dataset_mapping(provider_name: str, requested_dataset_role: str | None = None) -> ProviderDatasetMapping:
|
|
return _registry.dataset_mapping(provider_name, requested_dataset_role=requested_dataset_role)
|
|
|
|
|
|
def import_provider_dataset(
|
|
provider_name: str,
|
|
project_id: str,
|
|
area_id: str | None,
|
|
layers: list[str],
|
|
requested_dataset_role: str | None = None,
|
|
) -> ProviderImportResult:
|
|
return _registry.import_contract(
|
|
provider_name=provider_name,
|
|
project_id=project_id,
|
|
area_id=area_id,
|
|
layers=layers,
|
|
requested_dataset_role=requested_dataset_role,
|
|
)
|