1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2004-2021 musikcube team
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 //    * Redistributions of source code must retain the above copyright notice,
11 //      this list of conditions and the following disclaimer.
12 //
13 //    * Redistributions in binary form must reproduce the above copyright
14 //      notice, this list of conditions and the following disclaimer in the
15 //      documentation and/or other materials provided with the distribution.
16 //
17 //    * Neither the name of the author nor the names of other contributors may
18 //      be used to endorse or promote products derived from this software
19 //      without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 //
33 //////////////////////////////////////////////////////////////////////////////
34 
35 #pragma once
36 
37 #include <musikcore/library/QueryBase.h>
38 #include <musikcore/db/Connection.h>
39 #include <musikcore/library/track/Track.h>
40 #include <musikcore/library/track/TrackList.h>
41 #include <musikcore/library/query/util/Serialization.h>
42 
43 #pragma warning(push, 0)
44 #include <nlohmann/json.hpp>
45 #pragma warning(pop)
46 
47 namespace musik { namespace core { namespace library { namespace query {
48 
49     class TrackListQueryBase : public musik::core::library::query::QueryBase {
50         public:
51             typedef std::shared_ptr<musik::core::TrackList> Result;
52             typedef std::shared_ptr<std::set<size_t>> Headers;
53             typedef std::shared_ptr<std::map<size_t, size_t>> Durations;
54 
55             DELETE_COPY_AND_ASSIGNMENT_DEFAULTS(TrackListQueryBase)
56 
TrackListQueryBase()57             TrackListQueryBase() {
58                 this->limit = -1;
59                 this->offset = 0;
60             }
61 
62             /* virtual methods we define */
63             virtual Result GetResult() = 0;
64             virtual Headers GetHeaders() = 0;
65             virtual Durations GetDurations() = 0;
66             virtual size_t GetQueryHash() = 0;
67 
68             virtual void SetLimitAndOffset(int limit, int offset = 0) noexcept {
69                 this->limit = limit;
70                 this->offset = offset;
71             }
72 
GetSdkResult()73             virtual musik::core::sdk::ITrackList* GetSdkResult() {
74                 return new WrappedTrackList(GetResult());
75             }
76 
77         protected:
78 
79             /* for IMetadataProxy */
80 
GetLimitAndOffset()81             std::string GetLimitAndOffset() {
82                 if (this->limit > 0 && this->offset >= 0) {
83                     return u8fmt("LIMIT %d OFFSET %d", this->limit, this->offset);
84                 }
85                 return "";
86             }
87 
88             /* for ISerialization */
89 
FinalizeSerializedQueryWithLimitAndOffset(nlohmann::json & output)90             const std::string FinalizeSerializedQueryWithLimitAndOffset(nlohmann::json &output) {
91                 auto& options = output["options"];
92                 options["limit"] = this->limit;
93                 options["offset"] = this->offset;
94                 return output.dump();
95             }
96 
ExtractLimitAndOffsetFromDeserializedQuery(const nlohmann::json & options)97             void ExtractLimitAndOffsetFromDeserializedQuery(const nlohmann::json& options) {
98                 this->limit = options.value("limit", -1);
99                 this->offset = options.value("offset", 0);
100             }
101 
InitializeSerializedResultWithHeadersAndTrackList()102             nlohmann::json InitializeSerializedResultWithHeadersAndTrackList() {
103                 nlohmann::json output = {
104                     { "result", {
105                         { "headers", *this->GetHeaders() },
106                         { "durations", serialization::DurationMapToJsonMap(*this->GetDurations()) },
107                         { "trackList", serialization::TrackListToJson(*this->GetResult(), true) }
108                     }}
109                 };
110                 return output;
111             }
112 
DeserializeTrackListAndHeaders(nlohmann::json & result,ILibraryPtr library,TrackListQueryBase * query)113             void DeserializeTrackListAndHeaders(
114                 nlohmann::json& result,
115                 ILibraryPtr library,
116                 TrackListQueryBase* query)
117             {
118                 serialization::JsonArrayToSet<std::set<size_t>, size_t>(result["headers"], *query->GetHeaders());
119                 serialization::JsonMapToDuration(result["durations"], *query->GetDurations());
120                 serialization::TrackListFromJson(result["trackList"], *query->GetResult(), library, true);
121             }
122 
123         private:
124             int limit, offset;
125 
126             class WrappedTrackList : public musik::core::sdk::ITrackList {
127                 public:
WrappedTrackList(Result wrapped)128                     WrappedTrackList(Result wrapped) noexcept {
129                         this->wrapped = wrapped;
130                     }
131 
~WrappedTrackList()132                     virtual ~WrappedTrackList() {
133                     }
134 
Release()135                     void Release() noexcept override {
136                         delete this;
137                     }
138 
Count()139                     size_t Count() const override {
140                         return this->wrapped->Count();
141                     }
142 
GetId(size_t index)143                     int64_t GetId(size_t index) const override {
144                         return this->wrapped->GetId(index);
145                     }
146 
IndexOf(int64_t id)147                     int IndexOf(int64_t id) const override {
148                         return this->wrapped->IndexOf(id);
149                     }
150 
GetTrack(size_t index)151                     musik::core::sdk::ITrack* GetTrack(size_t index) const override  {
152                         return this->wrapped->GetTrack(index);
153                     }
154 
155                 private:
156                     Result wrapped;
157             };
158     };
159 
160 } } } }
161