1 #include <mbgl/style/sources/geojson_source.hpp>
2 #include <mbgl/style/sources/geojson_source_impl.hpp>
3 #include <mbgl/style/source_observer.hpp>
4 #include <mbgl/style/conversion/json.hpp>
5 #include <mbgl/style/conversion/geojson.hpp>
6 #include <mbgl/storage/file_source.hpp>
7 #include <mbgl/util/logging.hpp>
8
9 namespace mbgl {
10 namespace style {
11
GeoJSONSource(const std::string & id,const GeoJSONOptions & options)12 GeoJSONSource::GeoJSONSource(const std::string& id, const GeoJSONOptions& options)
13 : Source(makeMutable<Impl>(std::move(id), options)) {
14 }
15
16 GeoJSONSource::~GeoJSONSource() = default;
17
impl() const18 const GeoJSONSource::Impl& GeoJSONSource::impl() const {
19 return static_cast<const Impl&>(*baseImpl);
20 }
21
setURL(const std::string & url_)22 void GeoJSONSource::setURL(const std::string& url_) {
23 url = std::move(url_);
24
25 // Signal that the source description needs a reload
26 if (loaded || req) {
27 loaded = false;
28 req.reset();
29 observer->onSourceDescriptionChanged(*this);
30 }
31 }
32
setGeoJSON(const mapbox::geojson::geojson & geoJSON)33 void GeoJSONSource::setGeoJSON(const mapbox::geojson::geojson& geoJSON) {
34 req.reset();
35 baseImpl = makeMutable<Impl>(impl(), geoJSON);
36 observer->onSourceChanged(*this);
37 }
38
getURL() const39 optional<std::string> GeoJSONSource::getURL() const {
40 return url;
41 }
42
loadDescription(FileSource & fileSource)43 void GeoJSONSource::loadDescription(FileSource& fileSource) {
44 if (!url) {
45 loaded = true;
46 return;
47 }
48
49 if (req) {
50 return;
51 }
52
53 req = fileSource.request(Resource::source(*url), [this](Response res) {
54 if (res.error) {
55 observer->onSourceError(
56 *this, std::make_exception_ptr(std::runtime_error(res.error->message)));
57 } else if (res.notModified) {
58 return;
59 } else if (res.noContent) {
60 observer->onSourceError(
61 *this, std::make_exception_ptr(std::runtime_error("unexpectedly empty GeoJSON")));
62 } else {
63 conversion::Error error;
64 optional<GeoJSON> geoJSON = conversion::convertJSON<GeoJSON>(*res.data, error);
65 if (!geoJSON) {
66 Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s",
67 error.message.c_str());
68 // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for
69 // tiles to load.
70 baseImpl = makeMutable<Impl>(impl(), GeoJSON{ FeatureCollection{} });
71 } else {
72 baseImpl = makeMutable<Impl>(impl(), *geoJSON);
73 }
74
75 loaded = true;
76 observer->onSourceLoaded(*this);
77 }
78 });
79 }
80
81 } // namespace style
82 } // namespace mbgl
83