11package com .googlecode .objectify .util ;
22
33import com .google .cloud .datastore .Key ;
4+ import com .google .common .base .Preconditions ;
45import com .google .common .io .BaseEncoding ;
56import com .google .protobuf .DescriptorProtos ;
7+ import com .google .protobuf .DescriptorProtos .DescriptorProto ;
8+ import com .google .protobuf .DescriptorProtos .DescriptorProto .Builder ;
9+ import com .google .protobuf .DescriptorProtos .FieldDescriptorProto ;
10+ import com .google .protobuf .DescriptorProtos .FieldDescriptorProto .Label ;
11+ import com .google .protobuf .DescriptorProtos .FieldDescriptorProto .Type ;
612import com .google .protobuf .Descriptors ;
13+ import com .google .protobuf .Descriptors .FieldDescriptor ;
714import com .google .protobuf .DynamicMessage ;
815import com .google .protobuf .InvalidProtocolBufferException ;
916import lombok .SneakyThrows ;
1825 * @author Fred Wulff
1926 */
2027public enum KeyFormat {
21- INSTANCE ;
28+ /** Normal one to use */
29+ INSTANCE {
30+ @ Override
31+ protected Builder makeReferenceBuilder () {
32+ return super .makeReferenceBuilder ()
33+ .addField (
34+ FieldDescriptorProto
35+ .newBuilder ()
36+ .setLabel (Label .LABEL_OPTIONAL )
37+ .setType (Type .TYPE_STRING )
38+ .setName ("name_space" )
39+ .setNumber (20 )
40+ .build ()
41+ );
42+ }
43+ },
44+
45+ /**
46+ * Special version that does not include name_space in the descriptor, and therefore preserves the exact-to-the-byte
47+ * format of Objectify v6.0.7 and before.
48+ */
49+ NAMESPACELESS ;
2250
2351 // We build the descriptor for the App Engine Onestore Reference type in code
2452 // to avoid depending on the App Engine libraries.
@@ -31,11 +59,15 @@ public enum KeyFormat {
3159
3260 @ SneakyThrows
3361 KeyFormat () {
34- keyDescriptor = initializeFileDescriptor ();
62+ this .keyDescriptor = Descriptors .FileDescriptor .buildFrom (DescriptorProtos .FileDescriptorProto .newBuilder ()
63+ .addMessageType (makeElementBuilder ().build ())
64+ .addMessageType (makePathBuilder ().build ())
65+ .addMessageType (makeReferenceBuilder ().build ())
66+ .build (), new Descriptors .FileDescriptor []{});
3567 }
3668
37- private Descriptors . FileDescriptor initializeFileDescriptor () throws Descriptors . DescriptorValidationException {
38- final DescriptorProtos . DescriptorProto elementDescriptor = DescriptorProtos .DescriptorProto .newBuilder ()
69+ private Builder makeElementBuilder () {
70+ return DescriptorProtos .DescriptorProto .newBuilder ()
3971 .setName ("Element" )
4072 .addField (
4173 DescriptorProtos .FieldDescriptorProto .newBuilder ()
@@ -60,9 +92,11 @@ private Descriptors.FileDescriptor initializeFileDescriptor() throws Descriptors
6092 .setName ("name" )
6193 .setNumber (4 )
6294 .build ()
63- ).build ();
95+ );
96+ }
6497
65- final DescriptorProtos .DescriptorProto pathDescriptor = DescriptorProtos .DescriptorProto .newBuilder ()
98+ private Builder makePathBuilder () {
99+ return DescriptorProtos .DescriptorProto .newBuilder ()
66100 .setName ("Path" )
67101 .addField (
68102 DescriptorProtos .FieldDescriptorProto .newBuilder ()
@@ -72,42 +106,29 @@ private Descriptors.FileDescriptor initializeFileDescriptor() throws Descriptors
72106 .setTypeName ("Element" )
73107 .setNumber (1 )
74108 .build ()
75- ).build ();
109+ );
110+ }
76111
77- final DescriptorProtos .DescriptorProto referenceDescriptor = DescriptorProtos .DescriptorProto .newBuilder ()
112+ protected Builder makeReferenceBuilder () {
113+ return DescriptorProto .newBuilder ()
78114 .setName ("Reference" )
79115 .addField (
80- DescriptorProtos .FieldDescriptorProto
81- .newBuilder ()
82- .setLabel (DescriptorProtos .FieldDescriptorProto .Label .LABEL_REQUIRED )
83- .setType (DescriptorProtos .FieldDescriptorProto .Type .TYPE_STRING )
116+ FieldDescriptorProto .newBuilder ()
117+ .setLabel (Label .LABEL_REQUIRED )
118+ .setType (Type .TYPE_STRING )
84119 .setName ("app" )
85120 .setNumber (13 )
86- .build ())
87- .addField (
88- DescriptorProtos .FieldDescriptorProto
89- .newBuilder ()
90- .setLabel (DescriptorProtos .FieldDescriptorProto .Label .LABEL_OPTIONAL )
91- .setType (DescriptorProtos .FieldDescriptorProto .Type .TYPE_STRING )
92- .setName ("name_space" )
93- .setNumber (20 )
94- .build ())
121+ .build ()
122+ )
95123 .addField (
96- DescriptorProtos .FieldDescriptorProto
97- .newBuilder ()
98- .setLabel (DescriptorProtos .FieldDescriptorProto .Label .LABEL_REQUIRED )
99- .setType (DescriptorProtos .FieldDescriptorProto .Type .TYPE_MESSAGE )
124+ FieldDescriptorProto .newBuilder ()
125+ .setLabel (Label .LABEL_REQUIRED )
126+ .setType (Type .TYPE_MESSAGE )
100127 .setTypeName ("Path" )
101128 .setName ("path" )
102129 .setNumber (14 )
103- .build ())
104- .build ();
105-
106- return Descriptors .FileDescriptor .buildFrom (DescriptorProtos .FileDescriptorProto .newBuilder ()
107- .addMessageType (elementDescriptor )
108- .addMessageType (pathDescriptor )
109- .addMessageType (referenceDescriptor )
110- .build (), new Descriptors .FileDescriptor []{});
130+ .build ()
131+ );
111132 }
112133
113134 public Key parseOldStyleAppEngineKey (final String urlsafeKey ) throws InvalidProtocolBufferException {
@@ -165,7 +186,13 @@ public String formatOldStyleAppEngineKey(Key key) {
165186 fullProjectId = "s~" + fullProjectId ;
166187 }
167188 keyMessageBuilder .setField (referenceDescriptor .findFieldByName ("app" ), fullProjectId );
168- keyMessageBuilder .setField (referenceDescriptor .findFieldByName ("name_space" ), key .getNamespace ());
189+
190+ if (key .getNamespace () != null ) {
191+ final FieldDescriptor namespaceDescriptor = referenceDescriptor .findFieldByName ("name_space" );
192+ Preconditions .checkArgument (namespaceDescriptor != null , "This key formatter does not know how to handle namespaces" );
193+ keyMessageBuilder .setField (namespaceDescriptor , key .getNamespace ());
194+ }
195+
169196 final Descriptors .Descriptor elementDescriptor = keyDescriptor .findMessageTypeByName ("Element" );
170197
171198 final List <DynamicMessage > elementMessages = new ArrayList <>();
0 commit comments