UninitializedMessageException.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // 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.
  16. using System;
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.Text;
  20. using Google.ProtocolBuffers.Collections;
  21. using Google.ProtocolBuffers.Descriptors;
  22. namespace Google.ProtocolBuffers {
  23. /// <summary>
  24. /// TODO(jonskeet): Write summary text.
  25. /// </summary>
  26. public sealed class UninitializedMessageException : Exception {
  27. private readonly IList<string> missingFields;
  28. public UninitializedMessageException(IMessage message)
  29. : this(FindMissingFields(message)) {
  30. }
  31. private UninitializedMessageException(IList<string> missingFields)
  32. : base(BuildDescription(missingFields)) {
  33. this.missingFields = Lists.AsReadOnly(missingFields);
  34. }
  35. /// <summary>
  36. /// Converts this exception into an InvalidProtocolBufferException.
  37. /// When a parsed message is missing required fields, this should be thrown
  38. /// instead of UninitializedMessageException.
  39. /// </summary>
  40. public InvalidProtocolBufferException AsInvalidProtocolBufferException() {
  41. return new InvalidProtocolBufferException(Message);
  42. }
  43. /// <summary>
  44. /// Constructs the description string for a given list of missing fields.
  45. /// </summary>
  46. private static string BuildDescription(IEnumerable<string> missingFields) {
  47. StringBuilder description = new StringBuilder("Message missing required fields: ");
  48. bool first = true;
  49. foreach(string field in missingFields) {
  50. if (first) {
  51. first = false;
  52. } else {
  53. description.Append(", ");
  54. }
  55. description.Append(field);
  56. }
  57. return description.ToString();
  58. }
  59. /// <summary>
  60. /// Returns a list of the full "paths" of missing required
  61. /// fields in the specified message.
  62. /// </summary>
  63. private static IList<String> FindMissingFields(IMessage message) {
  64. List<String> results = new List<String>();
  65. FindMissingFields(message, "", results);
  66. return results;
  67. }
  68. /// <summary>
  69. /// Recursive helper implementing FindMissingFields.
  70. /// </summary>
  71. private static void FindMissingFields(IMessage message, String prefix, List<String> results) {
  72. foreach (FieldDescriptor field in message.DescriptorForType.Fields) {
  73. if (field.IsRequired && !message.HasField(field)) {
  74. results.Add(prefix + field.Name);
  75. }
  76. }
  77. foreach (KeyValuePair<FieldDescriptor, object> entry in message.AllFields) {
  78. FieldDescriptor field = entry.Key;
  79. object value = entry.Value;
  80. if (field.MappedType == MappedType.Message) {
  81. if (field.IsRepeated) {
  82. int i = 0;
  83. foreach (object element in (IEnumerable) value) {
  84. FindMissingFields((IMessage) element, SubMessagePrefix(prefix, field, i++), results);
  85. }
  86. } else {
  87. if (message.HasField(field)) {
  88. FindMissingFields((IMessage) value, SubMessagePrefix(prefix, field, -1), results);
  89. }
  90. }
  91. }
  92. }
  93. }
  94. private static String SubMessagePrefix(String prefix, FieldDescriptor field, int index) {
  95. StringBuilder result = new StringBuilder(prefix);
  96. if (field.IsExtension) {
  97. result.Append('(')
  98. .Append(field.FullName)
  99. .Append(')');
  100. } else {
  101. result.Append(field.Name);
  102. }
  103. if (index != -1) {
  104. result.Append('[')
  105. .Append(index)
  106. .Append(']');
  107. }
  108. result.Append('.');
  109. return result.ToString();
  110. }
  111. }
  112. }