blob: 7801d521af69420660c610ecc09f2284a26c9f21 [file] [log] [blame]
Jon Skeet68036862008-10-22 13:30:34 +01001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.
3// http://code.google.com/p/protobuf/
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16using System;
17using System.Collections.Generic;
18using Google.ProtocolBuffers.Collections;
19using Google.ProtocolBuffers.Descriptors;
20using Google.ProtocolBuffers.FieldAccess;
21using System.Collections;
22
23namespace Google.ProtocolBuffers {
24
25 /// <summary>
26 /// All generated protocol message classes extend this class. It implements
27 /// most of the IMessage interface using reflection. Users
28 /// can ignore this class as an implementation detail.
29 /// </summary>
30 public abstract class GeneratedMessage<TMessage, TBuilder> : AbstractMessage<TMessage, TBuilder>
31 where TMessage : GeneratedMessage<TMessage, TBuilder>
32 where TBuilder : GeneratedBuilder<TMessage, TBuilder> {
33
34 private UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance;
35
36 /// <summary>
37 /// Returns the message as a TMessage.
38 /// </summary>
39 protected abstract TMessage ThisMessage { get; }
40
41 internal FieldAccessorTable<TMessage, TBuilder> FieldAccessorsFromBuilder {
42 get { return InternalFieldAccessors; }
43 }
44
45 protected abstract FieldAccessorTable<TMessage, TBuilder> InternalFieldAccessors { get; }
46
47 public override MessageDescriptor DescriptorForType {
48 get { return InternalFieldAccessors.Descriptor; }
49 }
50
51 internal IDictionary<FieldDescriptor, Object> GetMutableFieldMap() {
52
53 // Use a SortedList so we'll end up serializing fields in order
54 var ret = new SortedList<FieldDescriptor, object>();
55 MessageDescriptor descriptor = DescriptorForType;
56 foreach (FieldDescriptor field in descriptor.Fields) {
57 IFieldAccessor<TMessage, TBuilder> accessor = InternalFieldAccessors[field];
58 if (field.IsRepeated) {
59 if (accessor.GetRepeatedCount(ThisMessage) != 0) {
60 ret[field] = accessor.GetValue(ThisMessage);
61 }
62 } else if (HasField(field)) {
63 ret[field] = accessor.GetValue(ThisMessage);
64 }
65 }
66 return ret;
67 }
68
69 public override bool IsInitialized {
70 get {
71 /* if (!DescriptorForType.HasRequiredFields) {
72 return true;
73 }*/
74 // Check that all required fields are present.
75 foreach (FieldDescriptor field in DescriptorForType.Fields) {
76 if (field.IsRequired && !HasField(field)) {
77 return false;
78 }
79 }
80
81 // Check that embedded messages are initialized.
82 // This code is similar to that in AbstractMessage, but we don't
83 // fetch all the field values - just the ones we need to.
84 foreach (FieldDescriptor field in DescriptorForType.Fields) {
85 if (field.MappedType == MappedType.Message) {
86 if (field.IsRepeated) {
87 // We know it's an IList<T>, but not the exact type - so
88 // IEnumerable is the best we can do. (C# generics aren't covariant yet.)
89 foreach (IMessage element in (IEnumerable) this[field]) {
90 if (!element.IsInitialized) {
91 return false;
92 }
93 }
94 } else {
95 if (HasField(field) && !((IMessage) this[field]).IsInitialized) {
96 return false;
97 }
98 }
99 }
100 }
101 return true;
102 }
103 }
104
105 public override IDictionary<FieldDescriptor, object> AllFields {
106 get { return Dictionaries.AsReadOnly(GetMutableFieldMap()); }
107 }
108
109 public override bool HasField(FieldDescriptor field) {
110 return InternalFieldAccessors[field].Has(ThisMessage);
111 }
112
113 public override int GetRepeatedFieldCount(FieldDescriptor field) {
114 return InternalFieldAccessors[field].GetRepeatedCount(ThisMessage);
115 }
116
117 public override object this[FieldDescriptor field, int index] {
118 get { return InternalFieldAccessors[field].GetRepeatedValue(ThisMessage, index); }
119 }
120
121 public override object this[FieldDescriptor field] {
122 get { return InternalFieldAccessors[field].GetValue(ThisMessage); }
123 }
124
125 public override UnknownFieldSet UnknownFields {
126 get { return unknownFields; }
127 }
128
129 /// <summary>
130 /// Replaces the set of unknown fields for this message. This should
131 /// only be used before a message is built, by the builder. (In the
132 /// Java code it is private, but the builder is nested so has access
133 /// to it.)
134 /// </summary>
135 internal void SetUnknownFields(UnknownFieldSet fieldSet) {
136 unknownFields = fieldSet;
137 }
138 }
139}