1 // Copyright 2008, Google Inc. All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26 // Walk a KML NetworkLink hierarchy.
27 // Fetches and parses the NetworkLinks in a given file recursively.
28 // Prints a count of the number of KML files fetched and the total number
29 // of each kind of Feature in the hierachy.
30
31 #include <iostream>
32 #include <map>
33 #include <string>
34 #include "kml/dom.h"
35 #include "kml/dom/xsd.h" // TODO: expose Xsd::ElementName() properly
36 #include "kml/engine.h"
37 #include "curlfetch.h"
38
39 using kmldom::ElementPtr;
40 using kmldom::FeaturePtr;
41 using kmldom::NetworkLinkPtr;
42 using kmldom::OverlayPtr;
43 using kmldom::StylePtr;
44 using kmlengine::KmlFile;
45 using kmlengine::KmlFilePtr;
46 using kmlengine::KmlCache;
47 using kmlengine::GetRootFeature;
48 using kmlengine::VisitFeatureHierarchy;
49 using std::cerr;
50 using std::cout;
51 using std::endl;
52
53 static void CountFeature(int type_id);
54 static void PrintFeatureCounts();
55 static void PrintFileCount();
56 static void WalkKmlFile(const KmlFilePtr& kml_file);
57
58 static int file_count;
59 static int feature_count;
60 static size_t data_size;
61 static size_t style_size;
62 static size_t balloon_size;
63
PrintFileCount()64 static void PrintFileCount() {
65 cout << "files " << file_count << endl;
66 cout << "features " << feature_count << endl;
67 cout << "data bytes " << data_size << endl;
68 cout << "style bytes " << style_size << endl;
69 cout << "balloon bytes " << balloon_size << endl;
70 }
71
72 typedef std::map<int,int> feature_counter_t;
73 feature_counter_t feature_counter;
74
CountFeature(int type_id)75 static void CountFeature(int type_id) {
76 ++feature_count;
77 feature_counter_t::const_iterator entry = feature_counter.find(type_id);
78 if (entry == feature_counter.end()) {
79 feature_counter[type_id] = 1;
80 } else {
81 ++feature_counter[type_id];
82 }
83 }
84
PrintFeatureCounts()85 static void PrintFeatureCounts() {
86 for (feature_counter_t::const_iterator iter = feature_counter.begin();
87 iter != feature_counter.end(); ++iter) {
88 std::string element_name;
89 cout << kmldom::Xsd::GetSchema()->ElementName(iter->first) << " "
90 << iter->second << endl;
91 }
92 }
93
94 class FeatureCounter : public kmlengine::FeatureVisitor {
95 public:
FeatureCounter(const KmlFilePtr & kml_file)96 FeatureCounter(const KmlFilePtr& kml_file)
97 : kml_file_(kml_file) {}
98
VisitFeature(const kmldom::FeaturePtr & feature)99 virtual void VisitFeature(const kmldom::FeaturePtr& feature) {
100 CountFeature(feature->Type());
101 StylePtr style = CreateResolvedStyle(feature, kml_file_,
102 kmldom::STYLESTATE_NORMAL);
103 std::string style_string = kmldom::SerializePretty(style);
104 style_size += style_string.size();
105 std::string balloon_text = CreateBalloonText(kml_file_, feature);
106 balloon_size += balloon_text.size();
107 if (OverlayPtr overlay = AsOverlay(feature)) {
108 std::string data;
109 if (kmlengine::FetchIcon(kml_file_, overlay, &data)) {
110 cout << " bytes " << data.size() << endl;
111 data_size += data.size();
112 } else {
113 cout << "fetch failed " << endl;
114 }
115 }
116 }
117
118 private:
119 const KmlFilePtr kml_file_;
120 };
121
HandleFile(const KmlFilePtr & kml_file)122 static void HandleFile(const KmlFilePtr& kml_file) {
123 cout << kml_file->get_url() << endl;
124 ++file_count;
125 FeatureCounter feature_counter(kml_file);
126 VisitFeatureHierarchy(GetRootFeature(kml_file->get_root()), feature_counter);
127 }
128
WalkNetworkLinks(const KmlFilePtr & kml_file)129 static void WalkNetworkLinks(const KmlFilePtr& kml_file) {
130 const kmlengine::ElementVector& link_vector =
131 kml_file->get_link_parent_vector();
132 for (size_t i = 0; i < link_vector.size(); ++i) {
133 if (NetworkLinkPtr networklink = AsNetworkLink(link_vector[i])) {
134 if (KmlFilePtr child = kmlengine::FetchLink(kml_file, networklink)) {
135 WalkKmlFile(child);
136 }
137 }
138 }
139 }
140
WalkKmlFile(const KmlFilePtr & kml_file)141 static void WalkKmlFile(const KmlFilePtr& kml_file) {
142 // First walk through this KmlFile's Features.
143 HandleFile(kml_file);
144 // Then walk recursively through all of its NetworkLinks.
145 WalkNetworkLinks(kml_file);
146 }
147
main(int argc,char ** argv)148 int main(int argc, char** argv) {
149 if (argc != 2) {
150 cout << "usage: " << argv[0] << " url" << endl;
151 return 1;
152 }
153 const char* kml_url = argv[1];
154 CurlNetFetcher curl_net_fetcher;
155 KmlCache kml_cache(&curl_net_fetcher, 30);
156 const KmlFilePtr kml_file = kml_cache.FetchKmlAbsolute(kml_url);
157 if (!kml_file) {
158 cerr << "failed: " << kml_url << endl;
159 return 1;
160 }
161 WalkKmlFile(kml_file);
162 PrintFileCount();
163 PrintFeatureCounts();
164 }
165