31 package com.google.protobuf;
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.Collections;
39 import java.util.Iterator;
40 import java.util.List;
52 FieldDescriptorType
extends FieldSet.FieldDescriptorLite<FieldDescriptorType>> {
75 private final SmallSortedMap<FieldDescriptorType, Object>
fields;
76 private boolean isImmutable;
77 private boolean hasLazyField =
false;
81 this.fields = SmallSortedMap.newFieldMap(16);
85 private FieldSet(
final boolean dummy) {
86 this.fields = SmallSortedMap.newFieldMap(0);
91 public static <
T extends FieldSet.FieldDescriptorLite<
T>> FieldSet<T> newFieldSet() {
92 return new FieldSet<T>();
96 @SuppressWarnings(
"unchecked")
97 public static <
T extends FieldSet.FieldDescriptorLite<
T>> FieldSet<
T> emptySet() {
98 return DEFAULT_INSTANCE;
101 @SuppressWarnings(
"rawtypes")
102 private static final FieldSet DEFAULT_INSTANCE = new FieldSet(
true);
110 @SuppressWarnings(
"unchecked")
111 public
void makeImmutable() {
125 public boolean isImmutable() {
130 public boolean equals(Object o) {
135 if (!(o instanceof FieldSet)) {
139 FieldSet<?> other = (FieldSet<?>) o;
140 return fields.equals(other.fields);
144 public int hashCode() {
155 public FieldSet<FieldDescriptorType> clone() {
158 FieldSet<FieldDescriptorType> clone = FieldSet.newFieldSet();
159 for (
int i = 0;
i <
fields.getNumArrayEntries();
i++) {
160 Map.Entry<FieldDescriptorType, Object> entry =
fields.getArrayEntryAt(
i);
161 FieldDescriptorType
descriptor = entry.getKey();
164 for (
Map.Entry<FieldDescriptorType, Object> entry :
fields.getOverflowEntries()) {
165 FieldDescriptorType
descriptor = entry.getKey();
168 clone.hasLazyField = hasLazyField;
176 public void clear() {
178 hasLazyField =
false;
184 SmallSortedMap<FieldDescriptorType, Object> result = SmallSortedMap.newFieldMap(16);
185 for (
int i = 0;
i <
fields.getNumArrayEntries();
i++) {
186 cloneFieldEntry(result,
fields.getArrayEntryAt(
i));
188 for (
Map.Entry<FieldDescriptorType, Object> entry :
fields.getOverflowEntries()) {
189 cloneFieldEntry(result, entry);
191 if (
fields.isImmutable()) {
192 result.makeImmutable();
199 private void cloneFieldEntry(
201 FieldDescriptorType
key = entry.getKey();
202 Object
value = entry.getValue();
203 if (
value instanceof LazyField) {
214 public Iterator<
Map.Entry<FieldDescriptorType, Object>> iterator() {
216 return new LazyIterator<FieldDescriptorType>(
fields.entrySet().iterator());
218 return fields.entrySet().iterator();
226 Iterator<
Map.Entry<FieldDescriptorType, Object>> descendingIterator() {
228 return new LazyIterator<FieldDescriptorType>(
fields.descendingEntrySet().iterator());
230 return fields.descendingEntrySet().iterator();
234 public boolean hasField(
final FieldDescriptorType
descriptor) {
236 throw new IllegalArgumentException(
"hasField() can only be called on non-repeated fields.");
247 public Object getField(
final FieldDescriptorType
descriptor) {
249 if (o instanceof LazyField) {
250 return ((LazyField) o).getValue();
258 @SuppressWarnings({
"unchecked",
"rawtypes"})
259 public void setField(
final FieldDescriptorType
descriptor, Object
value) {
261 if (!(
value instanceof List)) {
262 throw new IllegalArgumentException(
263 "Wrong object type used with protocol message reflection.");
268 final List newList =
new ArrayList();
269 newList.addAll((List)
value);
270 for (
final Object element : newList) {
271 verifyType(
descriptor.getLiteType(), element);
278 if (
value instanceof LazyField) {
285 public void clearField(
final FieldDescriptorType
descriptor) {
288 hasLazyField =
false;
293 public int getRepeatedFieldCount(
final FieldDescriptorType
descriptor) {
295 throw new IllegalArgumentException(
296 "getRepeatedField() can only be called on repeated fields.");
303 return ((List<?>)
value).size();
308 public Object getRepeatedField(
final FieldDescriptorType
descriptor,
final int index) {
310 throw new IllegalArgumentException(
311 "getRepeatedField() can only be called on repeated fields.");
317 throw new IndexOutOfBoundsException();
327 @SuppressWarnings(
"unchecked")
328 public
void setRepeatedField(
331 throw new IllegalArgumentException(
332 "getRepeatedField() can only be called on repeated fields.");
337 throw new IndexOutOfBoundsException();
348 @SuppressWarnings(
"unchecked")
349 public
void addRepeatedField(final FieldDescriptorType
descriptor, final Object
value) {
351 throw new IllegalArgumentException(
352 "addRepeatedField() can only be called on repeated fields.");
357 final Object existingValue = getField(
descriptor);
359 if (existingValue ==
null) {
360 list =
new ArrayList<Object>();
363 list = (List<Object>) existingValue;
376 private static void verifyType(
final WireFormat.FieldType
type,
final Object
value) {
379 boolean isValid =
false;
380 switch (
type.getJavaType()) {
382 isValid =
value instanceof Integer;
385 isValid =
value instanceof Long;
394 isValid =
value instanceof Boolean;
397 isValid =
value instanceof String;
400 isValid =
value instanceof ByteString ||
value instanceof
byte[];
404 isValid = (
value instanceof Integer ||
value instanceof Internal.EnumLite);
408 isValid = (
value instanceof MessageLite) || (
value instanceof LazyField);
420 throw new IllegalArgumentException(
421 "Wrong object type used with protocol message reflection.");
434 for (
int i = 0;
i <
fields.getNumArrayEntries();
i++) {
439 for (
final Map.Entry<FieldDescriptorType, Object> entry :
fields.getOverflowEntries()) {
447 @SuppressWarnings(
"unchecked")
448 private
boolean isInitialized(final
Map.Entry<FieldDescriptorType, Object> entry) {
449 final FieldDescriptorType
descriptor = entry.getKey();
450 if (
descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
452 for (
final MessageLite element : (List<MessageLite>) entry.getValue()) {
453 if (!element.isInitialized()) {
458 Object
value = entry.getValue();
459 if (
value instanceof MessageLite) {
463 }
else if (
value instanceof LazyField) {
466 throw new IllegalArgumentException(
467 "Wrong object type used with protocol message reflection.");
479 static int getWireFormatForFieldType(
final WireFormat.FieldType
type,
boolean isPacked) {
481 return WireFormat.WIRETYPE_LENGTH_DELIMITED;
483 return type.getWireType();
488 public void mergeFrom(
final FieldSet<FieldDescriptorType> other) {
489 for (
int i = 0;
i < other.fields.getNumArrayEntries();
i++) {
490 mergeFromField(other.fields.getArrayEntryAt(
i));
492 for (
final Map.Entry<FieldDescriptorType, Object> entry : other.fields.getOverflowEntries()) {
493 mergeFromField(entry);
497 private Object cloneIfMutable(Object
value) {
498 if (
value instanceof
byte[]) {
500 byte[] copy =
new byte[
bytes.length];
501 System.arraycopy(
bytes, 0, copy, 0,
bytes.length);
508 @SuppressWarnings({
"unchecked",
"rawtypes"})
509 private void mergeFromField(
final Map.Entry<FieldDescriptorType, Object> entry) {
510 final FieldDescriptorType
descriptor = entry.getKey();
511 Object otherValue = entry.getValue();
512 if (otherValue instanceof LazyField) {
513 otherValue = ((LazyField) otherValue).getValue();
519 value =
new ArrayList();
521 for (Object element : (List) otherValue) {
522 ((List)
value).add(cloneIfMutable(element));
525 }
else if (
descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
533 .internalMergeFrom(((MessageLite)
value).toBuilder(), (MessageLite) otherValue)
556 public static Object readPrimitiveField(
557 CodedInputStream
input,
final WireFormat.FieldType
type,
boolean checkUtf8)
560 return WireFormat.readPrimitiveField(
input,
type, WireFormat.Utf8Validation.STRICT);
562 return WireFormat.readPrimitiveField(
input,
type, WireFormat.Utf8Validation.LOOSE);
568 public void writeTo(
final CodedOutputStream
output)
throws IOException {
569 for (
int i = 0;
i <
fields.getNumArrayEntries();
i++) {
570 final Map.Entry<FieldDescriptorType, Object> entry =
fields.getArrayEntryAt(
i);
571 writeField(entry.getKey(), entry.getValue(),
output);
573 for (
final Map.Entry<FieldDescriptorType, Object> entry :
fields.getOverflowEntries()) {
574 writeField(entry.getKey(), entry.getValue(),
output);
579 public void writeMessageSetTo(
final CodedOutputStream
output)
throws IOException {
580 for (
int i = 0;
i <
fields.getNumArrayEntries();
i++) {
583 for (
final Map.Entry<FieldDescriptorType, Object> entry :
fields.getOverflowEntries()) {
584 writeMessageSetTo(entry,
output);
588 private void writeMessageSetTo(
589 final Map.Entry<FieldDescriptorType, Object> entry,
final CodedOutputStream
output)
591 final FieldDescriptorType
descriptor = entry.getKey();
592 if (
descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
595 Object
value = entry.getValue();
596 if (
value instanceof LazyField) {
599 output.writeMessageSetExtension(entry.getKey().getNumber(), (MessageLite)
value);
614 static void writeElement(
615 final CodedOutputStream
output,
616 final WireFormat.FieldType
type,
622 if (
type == WireFormat.FieldType.GROUP) {
638 static void writeElementNoTag(
639 final CodedOutputStream
output,
final WireFormat.FieldType
type,
final Object
value)
673 if (
value instanceof ByteString) {
680 if (
value instanceof ByteString) {
703 if (
value instanceof Internal.EnumLite) {
704 output.writeEnumNoTag(((Internal.EnumLite)
value).getNumber());
713 public static void writeField(
719 final List<?> valueList = (List<?>)
value;
721 output.writeTag(
number, WireFormat.WIRETYPE_LENGTH_DELIMITED);
724 for (
final Object element : valueList) {
725 dataSize += computeElementSizeNoTag(
type, element);
727 output.writeRawVarint32(dataSize);
729 for (
final Object element : valueList) {
733 for (
final Object element : valueList) {
738 if (
value instanceof LazyField) {
750 public int getSerializedSize() {
752 for (
int i = 0;
i <
fields.getNumArrayEntries();
i++) {
753 final Map.Entry<FieldDescriptorType, Object> entry =
fields.getArrayEntryAt(
i);
754 size += computeFieldSize(entry.getKey(), entry.getValue());
756 for (
final Map.Entry<FieldDescriptorType, Object> entry :
fields.getOverflowEntries()) {
757 size += computeFieldSize(entry.getKey(), entry.getValue());
763 public int getMessageSetSerializedSize() {
765 for (
int i = 0;
i <
fields.getNumArrayEntries();
i++) {
766 size += getMessageSetSerializedSize(
fields.getArrayEntryAt(
i));
768 for (
final Map.Entry<FieldDescriptorType, Object> entry :
fields.getOverflowEntries()) {
769 size += getMessageSetSerializedSize(entry);
774 private int getMessageSetSerializedSize(
final Map.Entry<FieldDescriptorType, Object> entry) {
775 final FieldDescriptorType
descriptor = entry.getKey();
776 Object
value = entry.getValue();
777 if (
descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
780 if (
value instanceof LazyField) {
781 return CodedOutputStream.computeLazyFieldMessageSetExtensionSize(
782 entry.getKey().getNumber(), (LazyField)
value);
784 return CodedOutputStream.computeMessageSetExtensionSize(
785 entry.getKey().getNumber(), (MessageLite)
value);
801 static int computeElementSize(
802 final WireFormat.FieldType
type,
final int number,
final Object
value) {
803 int tagSize = CodedOutputStream.computeTagSize(
number);
804 if (
type == WireFormat.FieldType.GROUP) {
809 return tagSize + computeElementSizeNoTag(
type,
value);
820 static int computeElementSizeNoTag(
final WireFormat.FieldType
type,
final Object
value) {
825 return CodedOutputStream.computeDoubleSizeNoTag((
Double)
value);
827 return CodedOutputStream.computeFloatSizeNoTag((
Float)
value);
829 return CodedOutputStream.computeInt64SizeNoTag((Long)
value);
831 return CodedOutputStream.computeUInt64SizeNoTag((Long)
value);
833 return CodedOutputStream.computeInt32SizeNoTag((Integer)
value);
835 return CodedOutputStream.computeFixed64SizeNoTag((Long)
value);
837 return CodedOutputStream.computeFixed32SizeNoTag((Integer)
value);
839 return CodedOutputStream.computeBoolSizeNoTag((Boolean)
value);
841 return CodedOutputStream.computeGroupSizeNoTag((MessageLite)
value);
843 if (
value instanceof ByteString) {
844 return CodedOutputStream.computeBytesSizeNoTag((ByteString)
value);
846 return CodedOutputStream.computeByteArraySizeNoTag((
byte[])
value);
849 if (
value instanceof ByteString) {
850 return CodedOutputStream.computeBytesSizeNoTag((ByteString)
value);
852 return CodedOutputStream.computeStringSizeNoTag((String)
value);
855 return CodedOutputStream.computeUInt32SizeNoTag((Integer)
value);
857 return CodedOutputStream.computeSFixed32SizeNoTag((Integer)
value);
859 return CodedOutputStream.computeSFixed64SizeNoTag((Long)
value);
861 return CodedOutputStream.computeSInt32SizeNoTag((Integer)
value);
863 return CodedOutputStream.computeSInt64SizeNoTag((Long)
value);
866 if (
value instanceof LazyField) {
867 return CodedOutputStream.computeLazyFieldSizeNoTag((LazyField)
value);
869 return CodedOutputStream.computeMessageSizeNoTag((MessageLite)
value);
873 if (
value instanceof Internal.EnumLite) {
874 return CodedOutputStream.computeEnumSizeNoTag(((Internal.EnumLite)
value).getNumber());
876 return CodedOutputStream.computeEnumSizeNoTag((Integer)
value);
880 throw new RuntimeException(
"There is no way to get here, but the compiler thinks otherwise.");
884 public static int computeFieldSize(
final FieldDescriptorLite<?>
descriptor,
final Object
value) {
890 for (
final Object element : (List<?>)
value) {
891 dataSize += computeElementSizeNoTag(
type, element);
894 + CodedOutputStream.computeTagSize(
number)
895 + CodedOutputStream.computeRawVarint32Size(dataSize);
898 for (
final Object element : (List<?>)
value) {