1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 package com.google.protobuf; 9 10 import static com.google.protobuf.Internal.checkNotNull; 11 12 import java.util.ArrayList; 13 import java.util.Collections; 14 import java.util.List; 15 16 /** 17 * Information for the layout of a protobuf message class. This describes all of the fields 18 * contained within a message. 19 */ 20 @ExperimentalApi 21 @CheckReturnValue 22 final class StructuralMessageInfo implements MessageInfo { 23 private final ProtoSyntax syntax; 24 private final boolean messageSetWireFormat; 25 private final int[] checkInitialized; 26 private final FieldInfo[] fields; 27 private final MessageLite defaultInstance; 28 29 /** 30 * Constructor. 31 * 32 * @param checkInitialized fields to check in isInitialized(). 33 * @param fields the set of fields for the message, in field number order. 34 */ StructuralMessageInfo( ProtoSyntax syntax, boolean messageSetWireFormat, int[] checkInitialized, FieldInfo[] fields, Object defaultInstance)35 StructuralMessageInfo( 36 ProtoSyntax syntax, 37 boolean messageSetWireFormat, 38 int[] checkInitialized, 39 FieldInfo[] fields, 40 Object defaultInstance) { 41 this.syntax = syntax; 42 this.messageSetWireFormat = messageSetWireFormat; 43 this.checkInitialized = checkInitialized; 44 this.fields = fields; 45 this.defaultInstance = (MessageLite) checkNotNull(defaultInstance, "defaultInstance"); 46 } 47 48 /** Gets the syntax for the message (e.g. PROTO2, PROTO3). */ 49 @Override getSyntax()50 public ProtoSyntax getSyntax() { 51 return syntax; 52 } 53 54 /** Indicates whether or not the message should be represented with message set wire format. */ 55 @Override isMessageSetWireFormat()56 public boolean isMessageSetWireFormat() { 57 return messageSetWireFormat; 58 } 59 60 /** An array of field numbers that need to be checked for isInitialized(). */ getCheckInitialized()61 public int[] getCheckInitialized() { 62 return checkInitialized; 63 } 64 65 /** 66 * Gets the information for all fields within this message, sorted in ascending order by their 67 * field number. 68 */ getFields()69 public FieldInfo[] getFields() { 70 return fields; 71 } 72 73 @Override getDefaultInstance()74 public MessageLite getDefaultInstance() { 75 return defaultInstance; 76 } 77 78 /** Helper method for creating a new builder for {@link MessageInfo}. */ newBuilder()79 public static Builder newBuilder() { 80 return new Builder(); 81 } 82 83 /** Helper method for creating a new builder for {@link MessageInfo}. */ newBuilder(int numFields)84 public static Builder newBuilder(int numFields) { 85 return new Builder(numFields); 86 } 87 88 /** A builder of {@link MessageInfo} instances. */ 89 public static final class Builder { 90 private final List<FieldInfo> fields; 91 private ProtoSyntax syntax; 92 private boolean wasBuilt; 93 private boolean messageSetWireFormat; 94 private int[] checkInitialized = null; 95 private Object defaultInstance; 96 Builder()97 public Builder() { 98 fields = new ArrayList<FieldInfo>(); 99 } 100 Builder(int numFields)101 public Builder(int numFields) { 102 fields = new ArrayList<FieldInfo>(numFields); 103 } 104 withDefaultInstance(Object defaultInstance)105 public void withDefaultInstance(Object defaultInstance) { 106 this.defaultInstance = defaultInstance; 107 } 108 withSyntax(ProtoSyntax syntax)109 public void withSyntax(ProtoSyntax syntax) { 110 this.syntax = checkNotNull(syntax, "syntax"); 111 } 112 withMessageSetWireFormat(boolean messageSetWireFormat)113 public void withMessageSetWireFormat(boolean messageSetWireFormat) { 114 this.messageSetWireFormat = messageSetWireFormat; 115 } 116 withCheckInitialized(int[] checkInitialized)117 public void withCheckInitialized(int[] checkInitialized) { 118 this.checkInitialized = checkInitialized; 119 } 120 withField(FieldInfo field)121 public void withField(FieldInfo field) { 122 if (wasBuilt) { 123 throw new IllegalStateException("Builder can only build once"); 124 } 125 fields.add(field); 126 } 127 build()128 public StructuralMessageInfo build() { 129 if (wasBuilt) { 130 throw new IllegalStateException("Builder can only build once"); 131 } 132 if (syntax == null) { 133 throw new IllegalStateException("Must specify a proto syntax"); 134 } 135 wasBuilt = true; 136 Collections.sort(fields); 137 return new StructuralMessageInfo( 138 syntax, 139 messageSetWireFormat, 140 checkInitialized, 141 fields.toArray(new FieldInfo[0]), 142 defaultInstance); 143 } 144 } 145 } 146