UninitializedMessageException.cs 4.1 KB

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