/thirdparty/breakpad/third_party/protobuf/protobuf/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java

http://github.com/tomahawk-player/tomahawk · Java · 241 lines · 100 code · 19 blank · 122 comment · 26 complexity · aea9087da5867b8e265dfae3eeba8da0 MD5 · raw file

  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // http://code.google.com/p/protobuf/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. package com.google.protobuf;
  31. /**
  32. * <code>SingleFieldBuilder</code> implements a structure that a protocol
  33. * message uses to hold a single field of another protocol message. It supports
  34. * the classical use case of setting an immutable {@link Message} as the value
  35. * of the field and is highly optimized around this.
  36. * <br>
  37. * It also supports the additional use case of setting a {@link Message.Builder}
  38. * as the field and deferring conversion of that <code>Builder</code>
  39. * to an immutable <code>Message</code>. In this way, it's possible to maintain
  40. * a tree of <code>Builder</code>'s that acts as a fully read/write data
  41. * structure.
  42. * <br>
  43. * Logically, one can think of a tree of builders as converting the entire tree
  44. * to messages when build is called on the root or when any method is called
  45. * that desires a Message instead of a Builder. In terms of the implementation,
  46. * the <code>SingleFieldBuilder</code> and <code>RepeatedFieldBuilder</code>
  47. * classes cache messages that were created so that messages only need to be
  48. * created when some change occured in its builder or a builder for one of its
  49. * descendants.
  50. *
  51. * @param <MType> the type of message for the field
  52. * @param <BType> the type of builder for the field
  53. * @param <IType> the common interface for the message and the builder
  54. *
  55. * @author jonp@google.com (Jon Perlow)
  56. */
  57. public class SingleFieldBuilder
  58. <MType extends GeneratedMessage,
  59. BType extends GeneratedMessage.Builder,
  60. IType extends MessageOrBuilder>
  61. implements GeneratedMessage.BuilderParent {
  62. // Parent to send changes to.
  63. private GeneratedMessage.BuilderParent parent;
  64. // Invariant: one of builder or message fields must be non-null.
  65. // If set, this is the case where we are backed by a builder. In this case,
  66. // message field represents a cached message for the builder (or null if
  67. // there is no cached message).
  68. private BType builder;
  69. // If builder is non-null, this represents a cached message from the builder.
  70. // If builder is null, this is the authoritative message for the field.
  71. private MType message;
  72. // Indicates that we've built a message and so we are now obligated
  73. // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
  74. private boolean isClean;
  75. public SingleFieldBuilder(
  76. MType message,
  77. GeneratedMessage.BuilderParent parent,
  78. boolean isClean) {
  79. if (message == null) {
  80. throw new NullPointerException();
  81. }
  82. this.message = message;
  83. this.parent = parent;
  84. this.isClean = isClean;
  85. }
  86. public void dispose() {
  87. // Null out parent so we stop sending it invalidations.
  88. parent = null;
  89. }
  90. /**
  91. * Get the message for the field. If the message is currently stored
  92. * as a <code>Builder</code>, it is converted to a <code>Message</code> by
  93. * calling {@link Message.Builder#buildPartial} on it. If no message has
  94. * been set, returns the default instance of the message.
  95. *
  96. * @return the message for the field
  97. */
  98. @SuppressWarnings("unchecked")
  99. public MType getMessage() {
  100. if (message == null) {
  101. // If message is null, the invariant is that we must be have a builder.
  102. message = (MType) builder.buildPartial();
  103. }
  104. return message;
  105. }
  106. /**
  107. * Builds the message and returns it.
  108. *
  109. * @return the message
  110. */
  111. public MType build() {
  112. // Now that build has been called, we are required to dispatch
  113. // invalidations.
  114. isClean = true;
  115. return getMessage();
  116. }
  117. /**
  118. * Gets a builder for the field. If no builder has been created yet, a
  119. * builder is created on demand by calling {@link Message#toBuilder}.
  120. *
  121. * @return The builder for the field
  122. */
  123. @SuppressWarnings("unchecked")
  124. public BType getBuilder() {
  125. if (builder == null) {
  126. // builder.mergeFrom() on a fresh builder
  127. // does not create any sub-objects with independent clean/dirty states,
  128. // therefore setting the builder itself to clean without actually calling
  129. // build() cannot break any invariants.
  130. builder = (BType) message.newBuilderForType(this);
  131. builder.mergeFrom(message); // no-op if message is the default message
  132. builder.markClean();
  133. }
  134. return builder;
  135. }
  136. /**
  137. * Gets the base class interface for the field. This may either be a builder
  138. * or a message. It will return whatever is more efficient.
  139. *
  140. * @return the message or builder for the field as the base class interface
  141. */
  142. @SuppressWarnings("unchecked")
  143. public IType getMessageOrBuilder() {
  144. if (builder != null) {
  145. return (IType) builder;
  146. } else {
  147. return (IType) message;
  148. }
  149. }
  150. /**
  151. * Sets a message for the field replacing any existing value.
  152. *
  153. * @param message the message to set
  154. * @return the builder
  155. */
  156. public SingleFieldBuilder<MType, BType, IType> setMessage(
  157. MType message) {
  158. if (message == null) {
  159. throw new NullPointerException();
  160. }
  161. this.message = message;
  162. if (builder != null) {
  163. builder.dispose();
  164. builder = null;
  165. }
  166. onChanged();
  167. return this;
  168. }
  169. /**
  170. * Merges the field from another field.
  171. *
  172. * @param value the value to merge from
  173. * @return the builder
  174. */
  175. public SingleFieldBuilder<MType, BType, IType> mergeFrom(
  176. MType value) {
  177. if (builder == null && message == message.getDefaultInstanceForType()) {
  178. message = value;
  179. } else {
  180. getBuilder().mergeFrom(value);
  181. }
  182. onChanged();
  183. return this;
  184. }
  185. /**
  186. * Clears the value of the field.
  187. *
  188. * @return the builder
  189. */
  190. @SuppressWarnings("unchecked")
  191. public SingleFieldBuilder<MType, BType, IType> clear() {
  192. message = (MType) (message != null ?
  193. message.getDefaultInstanceForType() :
  194. builder.getDefaultInstanceForType());
  195. if (builder != null) {
  196. builder.dispose();
  197. builder = null;
  198. }
  199. onChanged();
  200. return this;
  201. }
  202. /**
  203. * Called when a the builder or one of its nested children has changed
  204. * and any parent should be notified of its invalidation.
  205. */
  206. private void onChanged() {
  207. // If builder is null, this is the case where onChanged is being called
  208. // from setMessage or clear.
  209. if (builder != null) {
  210. message = null;
  211. }
  212. if (isClean && parent != null) {
  213. parent.markDirty();
  214. // Don't keep dispatching invalidations until build is called again.
  215. isClean = false;
  216. }
  217. }
  218. //@Override (Java 1.6 override semantics, but we must support 1.5)
  219. public void markDirty() {
  220. onChanged();
  221. }
  222. }