1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 package com.google.protobuf;
33 import java.io.IOException;
34 import java.util.Iterator;
35 import java.util.Map.Entry;
38 * LazyField encapsulates the logic of lazily parsing message fields. It stores
39 * the message in a ByteString initially and then parse it on-demand.
41 * LazyField is thread-compatible e.g. concurrent read are safe, however,
42 * synchronizations are needed under read/write situations.
44 * Now LazyField is only used to lazily load MessageSet.
45 * TODO(xiangl): Use LazyField to lazily load all messages.
47 * @author xiangl@google.com (Xiang Li)
51 final private MessageLite defaultInstance;
52 final private ExtensionRegistryLite extensionRegistry;
54 // Mutable because it is initialized lazily.
55 private ByteString bytes;
56 private volatile MessageLite value;
57 private volatile boolean isDirty = false;
59 public LazyField(MessageLite defaultInstance,
60 ExtensionRegistryLite extensionRegistry, ByteString bytes) {
61 this.defaultInstance = defaultInstance;
62 this.extensionRegistry = extensionRegistry;
66 public MessageLite getValue() {
72 * LazyField is not thread-safe for write access. Synchronizations are needed
73 * under read/write situations.
75 public MessageLite setValue(MessageLite value) {
76 MessageLite originalValue = this.value;
84 * Due to the optional field can be duplicated at the end of serialized
85 * bytes, which will make the serialized size changed after LazyField
86 * parsed. Be careful when using this method.
88 public int getSerializedSize() {
90 return value.getSerializedSize();
95 public ByteString toByteString() {
103 bytes = value.toByteString();
110 public int hashCode() {
112 return value.hashCode();
116 public boolean equals(Object obj) {
118 return value.equals(obj);
122 public String toString() {
124 return value.toString();
127 private void ensureInitialized() {
131 synchronized (this) {
137 value = defaultInstance.getParserForType()
138 .parseFrom(bytes, extensionRegistry);
140 } catch (IOException e) {
141 // TODO(xiangl): Refactory the API to support the exception thrown from
142 // lazily load messages.
147 // ====================================================
150 * LazyEntry and LazyIterator are used to encapsulate the LazyField, when
151 * users iterate all fields from FieldSet.
153 static class LazyEntry<K> implements Entry<K, Object> {
154 private Entry<K, LazyField> entry;
156 private LazyEntry(Entry<K, LazyField> entry) {
161 return entry.getKey();
164 public Object getValue() {
165 LazyField field = entry.getValue();
169 return field.getValue();
172 public LazyField getField() {
173 return entry.getValue();
176 public Object setValue(Object value) {
177 if (!(value instanceof MessageLite)) {
178 throw new IllegalArgumentException(
179 "LazyField now only used for MessageSet, "
180 + "and the value of MessageSet must be an instance of MessageLite");
182 return entry.getValue().setValue((MessageLite) value);
186 static class LazyIterator<K> implements Iterator<Entry<K, Object>> {
187 private Iterator<Entry<K, Object>> iterator;
189 public LazyIterator(Iterator<Entry<K, Object>> iterator) {
190 this.iterator = iterator;
193 public boolean hasNext() {
194 return iterator.hasNext();
197 @SuppressWarnings("unchecked")
198 public Entry<K, Object> next() {
199 Entry<K, ?> entry = iterator.next();
200 if (entry.getValue() instanceof LazyField) {
201 return new LazyEntry<K>((Entry<K, LazyField>) entry);
203 return (Entry<K, Object>) entry;
206 public void remove() {