/** Like {@link #writeTo} but uses MessageSet wire format. */ public void writeMessageSetTo(final CodedOutputStream output) throws IOException { for (int i = 0; i < fields.getNumArrayEntries(); i++) { writeMessageSetTo(fields.getArrayEntryAt(i), output); } for (final Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) { writeMessageSetTo(entry, output); } }
/** See {@link Message#writeTo(CodedOutputStream)}. */ public void writeTo(final CodedOutputStream output) throws IOException { for (int i = 0; i < fields.getNumArrayEntries(); i++) { final Map.Entry<FieldDescriptorType, Object> entry = fields.getArrayEntryAt(i); writeField(entry.getKey(), entry.getValue(), output); } for (final Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) { writeField(entry.getKey(), entry.getValue(), output); } }
/** Like {@link #getSerializedSize} but uses MessageSet wire format. */ public int getMessageSetSerializedSize() { int size = 0; for (int i = 0; i < fields.getNumArrayEntries(); i++) { size += getMessageSetSerializedSize(fields.getArrayEntryAt(i)); } for (final Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) { size += getMessageSetSerializedSize(entry); } return size; }
/** * See {@link Message#getSerializedSize()}. It's up to the caller to cache the resulting size if * desired. */ public int getSerializedSize() { int size = 0; for (int i = 0; i < fields.getNumArrayEntries(); i++) { final Map.Entry<FieldDescriptorType, Object> entry = fields.getArrayEntryAt(i); size += computeFieldSize(entry.getKey(), entry.getValue()); } for (final Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) { size += computeFieldSize(entry.getKey(), entry.getValue()); } return size; }
/** * See {@link Message#isInitialized()}. Note: Since {@code FieldSet} itself does not have any way * of knowing about required fields that aren't actually present in the set, it is up to the * caller to check that all required fields are present. */ public boolean isInitialized() { for (int i = 0; i < fields.getNumArrayEntries(); i++) { if (!isInitialized(fields.getArrayEntryAt(i))) { return false; } } for (final Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) { if (!isInitialized(entry)) { return false; } } return true; }
/** * Clones the FieldSet. The returned FieldSet will be mutable even if the original FieldSet was * immutable. * * @return the newly cloned FieldSet */ @Override public FieldSet<FieldDescriptorType> clone() { // We can't just call fields.clone because List objects in the map // should not be shared. FieldSet<FieldDescriptorType> clone = FieldSet.newFieldSet(); for (int i = 0; i < fields.getNumArrayEntries(); i++) { Map.Entry<FieldDescriptorType, Object> entry = fields.getArrayEntryAt(i); FieldDescriptorType descriptor = entry.getKey(); clone.setField(descriptor, entry.getValue()); } for (Map.Entry<FieldDescriptorType, Object> entry : fields.getOverflowEntries()) { FieldDescriptorType descriptor = entry.getKey(); clone.setField(descriptor, entry.getValue()); } return clone; }
/** Useful for implementing {@link Message#hasField(Descriptors.FieldDescriptor)}. */ public boolean hasField(final FieldDescriptorType descriptor) { if (descriptor.isRepeated()) { throw new IllegalArgumentException("hasField() can only be called on non-repeated fields."); } return fields.get(descriptor) != null; }
/** Make this FieldSet immutable from this point forward. */ @SuppressWarnings("unchecked") public void makeImmutable() { if (isImmutable) { return; } fields.makeImmutable(); isImmutable = true; }
/** * Useful for implementing {@link * Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}. */ @SuppressWarnings("unchecked") public void addRepeatedField(final FieldDescriptorType descriptor, final Object value) { if (!descriptor.isRepeated()) { throw new IllegalArgumentException( "addRepeatedField() can only be called on repeated fields."); } verifyType(descriptor.getLiteType(), value); final Object existingValue = fields.get(descriptor); List list; if (existingValue == null) { list = new ArrayList(); fields.put(descriptor, list); } else { list = (List) existingValue; } list.add(value); }
@SuppressWarnings("unchecked") private void mergeFromField(final Map.Entry<FieldDescriptorType, Object> entry) { final FieldDescriptorType descriptor = entry.getKey(); final Object otherValue = entry.getValue(); if (descriptor.isRepeated()) { Object value = fields.get(descriptor); if (value == null) { // Our list is empty, but we still need to make a defensive copy of // the other list since we don't know if the other FieldSet is still // mutable. fields.put(descriptor, new ArrayList((List) otherValue)); } else { // Concatenate the lists. ((List) value).addAll((List) otherValue); } } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { Object value = fields.get(descriptor); if (value == null) { fields.put(descriptor, otherValue); } else { // Merge the messages. fields.put( descriptor, descriptor .internalMergeFrom(((MessageLite) value).toBuilder(), (MessageLite) otherValue) .build()); } } else { fields.put(descriptor, otherValue); } }
/** Useful for implementing {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}. */ public int getRepeatedFieldCount(final FieldDescriptorType descriptor) { if (!descriptor.isRepeated()) { throw new IllegalArgumentException( "getRepeatedField() can only be called on repeated fields."); } final Object value = fields.get(descriptor); if (value == null) { return 0; } else { return ((List<?>) value).size(); } }
/** Useful for implementing {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}. */ public Object getRepeatedField(final FieldDescriptorType descriptor, final int index) { if (!descriptor.isRepeated()) { throw new IllegalArgumentException( "getRepeatedField() can only be called on repeated fields."); } final Object value = fields.get(descriptor); if (value == null) { throw new IndexOutOfBoundsException(); } else { return ((List<?>) value).get(index); } }
/** * Useful for implementing {@link * Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}. */ @SuppressWarnings("unchecked") public void setRepeatedField( final FieldDescriptorType descriptor, final int index, final Object value) { if (!descriptor.isRepeated()) { throw new IllegalArgumentException( "getRepeatedField() can only be called on repeated fields."); } final Object list = fields.get(descriptor); if (list == null) { throw new IndexOutOfBoundsException(); } verifyType(descriptor.getLiteType(), value); ((List) list).set(index, value); }
/** * Useful for implementing {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. */ @SuppressWarnings("unchecked") public void setField(final FieldDescriptorType descriptor, Object value) { if (descriptor.isRepeated()) { if (!(value instanceof List)) { throw new IllegalArgumentException( "Wrong object type used with protocol message reflection."); } // Wrap the contents in a new list so that the caller cannot change // the list's contents after setting it. final List newList = new ArrayList(); newList.addAll((List) value); for (final Object element : newList) { verifyType(descriptor.getLiteType(), element); } value = newList; } else { verifyType(descriptor.getLiteType(), value); } fields.put(descriptor, value); }
/** Construct an empty FieldSet. This is only used to initialize DEFAULT_INSTANCE. */ private FieldSet(final boolean dummy) { this.fields = SmallSortedMap.newFieldMap(0); makeImmutable(); }
/** Construct a new FieldSet. */ private FieldSet() { this.fields = SmallSortedMap.newFieldMap(16); }
/** See {@link Message.Builder#clear()}. */ public void clear() { fields.clear(); }
/** Get a simple map containing all the fields. */ public Map<FieldDescriptorType, Object> getAllFields() { return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields); }
/** * Get an iterator to the field map. This iterator should not be leaked out of the protobuf * library as it is not protected from mutation when fields is not immutable. */ public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() { return fields.entrySet().iterator(); }
/** * Useful for implementing {@link Message#getField(Descriptors.FieldDescriptor)}. This method * returns {@code null} if the field is not set; in this case it is up to the caller to fetch the * field's default value. */ public Object getField(final FieldDescriptorType descriptor) { return fields.get(descriptor); }
/** Useful for implementing {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. */ public void clearField(final FieldDescriptorType descriptor) { fields.remove(descriptor); }