1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// https://developers.google.com/protocol-buffers/
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
33import java.util.Iterator;
34import java.util.Map.Entry;
35
36/**
37 * LazyField encapsulates the logic of lazily parsing message fields. It stores
38 * the message in a ByteString initially and then parse it on-demand.
39 *
40 * Most of key methods are implemented in {@link LazyFieldLite} but this class
41 * can contain default instance of the message to provide {@code hashCode()},
42 * {@code euqals()} and {@code toString()}.
43 *
44 * @author xiangl@google.com (Xiang Li)
45 */
46public class LazyField extends LazyFieldLite {
47
48  /**
49   * Carry a message's default instance which is used by {@code hashCode()}, {@code euqals()} and
50   * {@code toString()}.
51   */
52  private final MessageLite defaultInstance;
53
54  public LazyField(MessageLite defaultInstance,
55      ExtensionRegistryLite extensionRegistry, ByteString bytes) {
56    super(extensionRegistry, bytes);
57
58    this.defaultInstance = defaultInstance;
59  }
60
61  @Override
62  public boolean containsDefaultInstance() {
63    return super.containsDefaultInstance() || value == defaultInstance;
64  }
65
66  public MessageLite getValue() {
67    return getValue(defaultInstance);
68  }
69
70  @Override
71  public int hashCode() {
72    return getValue().hashCode();
73  }
74
75  @Override
76  public boolean equals(Object obj) {
77    return getValue().equals(obj);
78  }
79
80  @Override
81  public String toString() {
82    return getValue().toString();
83  }
84
85  // ====================================================
86
87  /**
88   * LazyEntry and LazyIterator are used to encapsulate the LazyField, when
89   * users iterate all fields from FieldSet.
90   */
91  static class LazyEntry<K> implements Entry<K, Object> {
92    private Entry<K, LazyField> entry;
93
94    private LazyEntry(Entry<K, LazyField> entry) {
95      this.entry = entry;
96    }
97
98    @Override
99    public K getKey() {
100      return entry.getKey();
101    }
102
103    @Override
104    public Object getValue() {
105      LazyField field = entry.getValue();
106      if (field == null) {
107        return null;
108      }
109      return field.getValue();
110    }
111
112    public LazyField getField() {
113      return entry.getValue();
114    }
115
116    @Override
117    public Object setValue(Object value) {
118      if (!(value instanceof MessageLite)) {
119        throw new IllegalArgumentException(
120            "LazyField now only used for MessageSet, "
121            + "and the value of MessageSet must be an instance of MessageLite");
122      }
123      return entry.getValue().setValue((MessageLite) value);
124    }
125  }
126
127  static class LazyIterator<K> implements Iterator<Entry<K, Object>> {
128    private Iterator<Entry<K, Object>> iterator;
129
130    public LazyIterator(Iterator<Entry<K, Object>> iterator) {
131      this.iterator = iterator;
132    }
133
134    @Override
135    public boolean hasNext() {
136      return iterator.hasNext();
137    }
138
139    @Override
140    @SuppressWarnings("unchecked")
141    public Entry<K, Object> next() {
142      Entry<K, ?> entry = iterator.next();
143      if (entry.getValue() instanceof LazyField) {
144        return new LazyEntry<K>((Entry<K, LazyField>) entry);
145      }
146      return (Entry<K, Object>) entry;
147    }
148
149    @Override
150    public void remove() {
151      iterator.remove();
152    }
153  }
154}
155