PageRenderTime 34ms CodeModel.GetById 18ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 31package com.google.protobuf;
 32
 33/**
 34 * <code>SingleFieldBuilder</code> implements a structure that a protocol
 35 * message uses to hold a single field of another protocol message. It supports
 36 * the classical use case of setting an immutable {@link Message} as the value
 37 * of the field and is highly optimized around this.
 38 * <br>
 39 * It also supports the additional use case of setting a {@link Message.Builder}
 40 * as the field and deferring conversion of that <code>Builder</code>
 41 * to an immutable <code>Message</code>. In this way, it's possible to maintain
 42 * a tree of <code>Builder</code>'s that acts as a fully read/write data
 43 * structure.
 44 * <br>
 45 * Logically, one can think of a tree of builders as converting the entire tree
 46 * to messages when build is called on the root or when any method is called
 47 * that desires a Message instead of a Builder. In terms of the implementation,
 48 * the <code>SingleFieldBuilder</code> and <code>RepeatedFieldBuilder</code>
 49 * classes cache messages that were created so that messages only need to be
 50 * created when some change occured in its builder or a builder for one of its
 51 * descendants.
 52 *
 53 * @param <MType> the type of message for the field
 54 * @param <BType> the type of builder for the field
 55 * @param <IType> the common interface for the message and the builder
 56 *
 57 * @author jonp@google.com (Jon Perlow)
 58 */
 59public class SingleFieldBuilder
 60    <MType extends GeneratedMessage,
 61     BType extends GeneratedMessage.Builder,
 62     IType extends MessageOrBuilder>
 63    implements GeneratedMessage.BuilderParent {
 64
 65  // Parent to send changes to.
 66  private GeneratedMessage.BuilderParent parent;
 67
 68  // Invariant: one of builder or message fields must be non-null.
 69
 70  // If set, this is the case where we are backed by a builder. In this case,
 71  // message field represents a cached message for the builder (or null if
 72  // there is no cached message).
 73  private BType builder;
 74
 75  // If builder is non-null, this represents a cached message from the builder.
 76  // If builder is null, this is the authoritative message for the field.
 77  private MType message;
 78
 79  // Indicates that we've built a message and so we are now obligated
 80  // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
 81  private boolean isClean;
 82
 83  public SingleFieldBuilder(
 84      MType message,
 85      GeneratedMessage.BuilderParent parent,
 86      boolean isClean) {
 87    if (message == null) {
 88      throw new NullPointerException();
 89    }
 90    this.message = message;
 91    this.parent = parent;
 92    this.isClean = isClean;
 93  }
 94
 95  public void dispose() {
 96    // Null out parent so we stop sending it invalidations.
 97    parent = null;
 98  }
 99
100  /**
101   * Get the message for the field. If the message is currently stored
102   * as a <code>Builder</code>, it is converted to a <code>Message</code> by
103   * calling {@link Message.Builder#buildPartial} on it. If no message has
104   * been set, returns the default instance of the message.
105   *
106   * @return the message for the field
107   */
108  @SuppressWarnings("unchecked")
109  public MType getMessage() {
110    if (message == null) {
111      // If message is null, the invariant is that we must be have a builder.
112      message = (MType) builder.buildPartial();
113    }
114    return message;
115  }
116
117  /**
118   * Builds the message and returns it.
119   *
120   * @return the message
121   */
122  public MType build() {
123    // Now that build has been called, we are required to dispatch
124    // invalidations.
125    isClean = true;
126    return getMessage();
127  }
128
129  /**
130   * Gets a builder for the field. If no builder has been created yet, a
131   * builder is created on demand by calling {@link Message#toBuilder}.
132   *
133   * @return The builder for the field
134   */
135  @SuppressWarnings("unchecked")
136  public BType getBuilder() {
137    if (builder == null) {
138      // builder.mergeFrom() on a fresh builder
139      // does not create any sub-objects with independent clean/dirty states,
140      // therefore setting the builder itself to clean without actually calling
141      // build() cannot break any invariants.
142      builder = (BType) message.newBuilderForType(this);
143      builder.mergeFrom(message); // no-op if message is the default message
144      builder.markClean();
145    }
146    return builder;
147  }
148
149  /**
150   * Gets the base class interface for the field. This may either be a builder
151   * or a message. It will return whatever is more efficient.
152   *
153   * @return the message or builder for the field as the base class interface
154   */
155  @SuppressWarnings("unchecked")
156  public IType getMessageOrBuilder() {
157    if (builder != null) {
158      return  (IType) builder;
159    } else {
160      return (IType) message;
161    }
162  }
163
164  /**
165   * Sets a  message for the field replacing any existing value.
166   *
167   * @param message the message to set
168   * @return the builder
169   */
170  public SingleFieldBuilder<MType, BType, IType> setMessage(
171      MType message) {
172    if (message == null) {
173      throw new NullPointerException();
174    }
175    this.message = message;
176    if (builder != null) {
177      builder.dispose();
178      builder = null;
179    }
180    onChanged();
181    return this;
182  }
183
184  /**
185   * Merges the field from another field.
186   *
187   * @param value the value to merge from
188   * @return the builder
189   */
190  public SingleFieldBuilder<MType, BType, IType> mergeFrom(
191      MType value) {
192    if (builder == null && message == message.getDefaultInstanceForType()) {
193      message = value;
194    } else {
195      getBuilder().mergeFrom(value);
196    }
197    onChanged();
198    return this;
199  }
200
201  /**
202   * Clears the value of the field.
203   *
204   * @return the builder
205   */
206  @SuppressWarnings("unchecked")
207  public SingleFieldBuilder<MType, BType, IType> clear() {
208    message = (MType) (message != null ?
209        message.getDefaultInstanceForType() :
210        builder.getDefaultInstanceForType());
211    if (builder != null) {
212      builder.dispose();
213      builder = null;
214    }
215    onChanged();
216    return this;
217  }
218
219  /**
220   * Called when a the builder or one of its nested children has changed
221   * and any parent should be notified of its invalidation.
222   */
223  private void onChanged() {
224    // If builder is null, this is the case where onChanged is being called
225    // from setMessage or clear.
226    if (builder != null) {
227      message = null;
228    }
229    if (isClean && parent != null) {
230      parent.markDirty();
231
232      // Don't keep dispatching invalidations until build is called again.
233      isClean = false;
234    }
235  }
236
237  //@Override (Java 1.6 override semantics, but we must support 1.5)
238  public void markDirty() {
239    onChanged();
240  }
241}