1+ // Copyright 2021, Nitric Technologies Pty Ltd.
2+ //
3+ // Licensed under the Apache License, Version 2.0 (the "License");
4+ // you may not use this file except in compliance with the License.
5+ // You may obtain a copy of the License at
6+ //
7+ // http://www.apache.org/licenses/LICENSE-2.0
8+ //
9+ // Unless required by applicable law or agreed to in writing, software
10+ // distributed under the License is distributed on an "AS IS" BASIS,
11+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ // See the License for the specific language governing permissions and
13+ // limitations under the License.
14+ using System ;
15+ using System . Collections . Generic ;
16+ using DocumentServiceClient = Nitric . Proto . Document . v1 . DocumentService . DocumentServiceClient ;
17+ using GrpcKey = Nitric . Proto . Document . v1 . Key ;
18+ using Nitric . Proto . Document . v1 ;
19+ using Util = Nitric . Api . Common . Util ;
20+ using Google . Protobuf . WellKnownTypes ;
21+ namespace Nitric . Api . Document
22+ {
23+ public class DocumentRef < T > where T : IDictionary < string , object > , new ( )
24+ {
25+ const int DEPTH_LIMIT = 1 ;
26+
27+ private readonly DocumentServiceClient documentClient ;
28+ public readonly Key < T > Key ;
29+ private readonly CollectionRef < T > collection ;
30+
31+ protected DocumentRef ( ) { }
32+ internal DocumentRef (
33+ DocumentServiceClient documentClient ,
34+ CollectionRef < T > collection ,
35+ string documentId )
36+ {
37+ this . documentClient = documentClient ;
38+ this . Key = new Key < T > ( collection , documentId ) ;
39+ this . collection = collection ;
40+ }
41+
42+ public Document < T > Get ( )
43+ {
44+ DocumentGetRequest request = new DocumentGetRequest ( ) ;
45+ request . Key = this . Key . ToKey ( ) ;
46+
47+ var response = this . documentClient . Get ( request ) ;
48+
49+ return new Document < T > (
50+ this ,
51+ DocumentToGeneric ( response . Document . Content )
52+ ) ;
53+ }
54+ public void Set ( T value )
55+ {
56+ if ( value == null )
57+ {
58+ throw new ArgumentNullException ( "Provide non-null value" ) ;
59+ }
60+ var request = new DocumentSetRequest
61+ {
62+ Key = this . Key . ToKey ( ) ,
63+ Content = Util . ObjToStruct ( value ) ,
64+ } ;
65+ this . documentClient . Set ( request ) ;
66+ }
67+
68+ public void Delete ( )
69+ {
70+ var request = new DocumentDeleteRequest
71+ {
72+ Key = this . Key . ToKey ( ) ,
73+ } ;
74+ this . documentClient . Delete ( request ) ;
75+ }
76+
77+ private int Depth ( int depth , Collection collection )
78+ {
79+ return ( collection . Parent != null ) ?
80+ Depth ( depth + 1 , collection . Parent . Collection ) : depth ;
81+ }
82+
83+ public CollectionRef < T > Collection ( string name )
84+ {
85+ if ( string . IsNullOrEmpty ( name ) )
86+ {
87+ throw new ArgumentNullException ( name ) ;
88+ }
89+ if ( Depth ( 0 , this . collection . ToGrpcCollection ( ) ) >= DEPTH_LIMIT )
90+ {
91+ throw new NotSupportedException ( "Currently subcollection are only able to be nested " + DEPTH_LIMIT + "deep" ) ;
92+ }
93+ return new CollectionRef < T > ( this . documentClient , name , this . Key ) ;
94+ }
95+
96+ //Utility function to convert a struct document to its generic counterpart
97+ protected T DocumentToGeneric ( Struct content )
98+ {
99+ T doc = new T ( ) ;
100+ foreach ( var kv in content . Fields )
101+ {
102+ doc . Add ( kv . Key , UnwrapValue ( kv . Value ) ) ;
103+ }
104+ return doc ;
105+ }
106+ private object UnwrapValue ( Value value )
107+ {
108+ switch ( value . KindCase )
109+ {
110+ case Value . KindOneofCase . StringValue :
111+ return value . StringValue ;
112+ case Value . KindOneofCase . BoolValue :
113+ return value . BoolValue ;
114+ case Value . KindOneofCase . NumberValue :
115+ return value . NumberValue ;
116+ case Value . KindOneofCase . NullValue :
117+ return null ;
118+ case Value . KindOneofCase . StructValue :
119+ Dictionary < string , object > unwrappedStruct = new Dictionary < string , object > ( ) ;
120+ foreach ( var kv in value . StructValue . Fields )
121+ {
122+ unwrappedStruct . Add ( kv . Key , UnwrapValue ( kv . Value ) ) ;
123+ }
124+ return unwrappedStruct ;
125+ case Value . KindOneofCase . ListValue :
126+ List < object > unwrappedList = new List < object > ( ) ;
127+ foreach ( Value v in value . ListValue . Values )
128+ {
129+ unwrappedList . Add ( UnwrapValue ( v ) ) ;
130+ }
131+ return unwrappedList ;
132+ default :
133+ throw new ArgumentException ( "Provide proto-value" ) ;
134+ }
135+ }
136+ }
137+ }
0 commit comments