Skip to content

Commit 27f4d0d

Browse files
committed
Add InsertAllRequest and InsertAllResponse. Add model classes for table data
1 parent 722e4a7 commit 27f4d0d

File tree

9 files changed

+1340
-1
lines changed

9 files changed

+1340
-1
lines changed
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/*
2+
* Copyright 2015 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.gcloud.bigquery;
18+
19+
import static com.google.common.base.Preconditions.checkState;
20+
21+
import com.google.api.client.util.Data;
22+
import com.google.api.client.util.Lists;
23+
import com.google.common.base.MoreObjects;
24+
25+
import java.io.Serializable;
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.Objects;
29+
30+
/**
31+
* Google BigQuery Table Field Value class. Objects of this class represent values of a BigQuery
32+
* Table Field. A list of values forms a {@link TableRow}. Tables rows can be gotten as the result
33+
* of a query or when listing table data.
34+
*/
35+
public class FieldValue implements Serializable {
36+
37+
private static final int MICROSECONDS = 1000000;
38+
private static final long serialVersionUID = 469098630191710061L;
39+
40+
private final Kind kind;
41+
private final Object value;
42+
43+
/**
44+
* The field value's kind, giving information on the field's content type.
45+
*/
46+
public enum Kind {
47+
/**
48+
* A primitive field value. A {@code FieldValue} has type {@link #PRIMITIVE} when the
49+
* corresponding field has type {@link Field.Type#bool()}, {@link Field.Type#string()}
50+
* {@link Field.Type#floatingPoint()}, {@link Field.Type#integer()},
51+
* {@link Field.Type#timestamp()} or the value is set to {@code null}.
52+
*/
53+
PRIMITIVE,
54+
55+
/**
56+
* A {@code FieldValue} for a field with {@link Field.Mode#REPEATED} mode.
57+
*/
58+
REPEATED,
59+
60+
/**
61+
* A {@code FieldValue} for a field of type {@link Field.Type#record(Field...)}.
62+
*/
63+
RECORD
64+
}
65+
66+
FieldValue(Kind kind, Object value) {
67+
this.kind = kind;
68+
this.value = value;
69+
}
70+
71+
/**
72+
* Returns the kind of this Field Value.
73+
*
74+
* @return {@link Kind#PRIMITIVE} if the value is of primitive type ({@link Field.Type#bool()},
75+
* {@link Field.Type#string()}, {@link Field.Type#floatingPoint()},
76+
* {@link Field.Type#integer()}, {@link Field.Type#timestamp()}) or is {@code null}. Returns
77+
* {@link Kind#REPEATED} if the corresponding field has ({@link Field.Mode#REPEATED}) mode.
78+
* Returns {@link Kind#RECORD} if the corresponding field has
79+
* {@link Field.Type#record(Field...)} type.
80+
*/
81+
public Kind kind() {
82+
return kind;
83+
}
84+
85+
/**
86+
* Return this field's value as an {@link Object}.
87+
*/
88+
public Object value() {
89+
return value;
90+
}
91+
92+
/**
93+
* Return this field's value as a {@link String}. This method should only be used if the
94+
* corresponding field has primitive type ({@link Field.Type#bool()}, {@link Field.Type#string()},
95+
* {@link Field.Type#floatingPoint()}, {@link Field.Type#integer()},
96+
* {@link Field.Type#timestamp()}).
97+
*
98+
* @throws ClassCastException if the field has not primitive type
99+
*/
100+
@SuppressWarnings("unchecked")
101+
public String stringValue() {
102+
return (String) value;
103+
}
104+
105+
/**
106+
* Returns this field's value as a {@link Long}. This method should only be used if the
107+
* corresponding field has {@link Field.Type#integer()} type.
108+
*
109+
* @throws NumberFormatException if the field's value could not be converted to {@link Integer}
110+
*/
111+
@SuppressWarnings("unchecked")
112+
public long longValue() {
113+
return Long.valueOf(stringValue());
114+
}
115+
116+
/**
117+
* Returns this field's value as a {@link Double}. This method should only be used if the
118+
* corresponding field has {@link Field.Type#floatingPoint()} type.
119+
*
120+
* @throws NumberFormatException if the field's value could not be converted to {@link Double}
121+
*/
122+
@SuppressWarnings("unchecked")
123+
public double doubleValue() {
124+
return Double.valueOf(stringValue());
125+
}
126+
127+
/**
128+
* Returns this field's value as a {@link Boolean}. This method should only be used if the
129+
* corresponding field has {@link Field.Type#bool()} type.
130+
*
131+
* @throws IllegalStateException if the field's value could not be converted to {@link Boolean}
132+
*/
133+
@SuppressWarnings("unchecked")
134+
public boolean booleanValue() {
135+
String stringValue = stringValue();
136+
checkState(stringValue.equalsIgnoreCase("true") || stringValue.equalsIgnoreCase("false"),
137+
"Field value is not of boolean type");
138+
return Boolean.parseBoolean(stringValue);
139+
}
140+
141+
/**
142+
* Returns this field's value as a {@link Long}, representing a timestamp in microseconds. This
143+
* method should only be used if the corresponding field has {@link Field.Type#timestamp()} type.
144+
*
145+
* @throws NumberFormatException if the field's value could not be converted to {@link Long}
146+
*/
147+
@SuppressWarnings("unchecked")
148+
public long timestampValue() {
149+
return new Double(((Double.valueOf(stringValue())) * MICROSECONDS)).longValue();
150+
}
151+
152+
/**
153+
* Returns this field's value as a list of {@link FieldValue}. This method should only be used if
154+
* the corresponding field has {@link Field.Mode#REPEATED} mode (i.e. {@link #kind()} is
155+
* {@link Kind#REPEATED}).
156+
*
157+
* @throws ClassCastException if the field has not {@link Field.Mode#REPEATED} mode
158+
*/
159+
@SuppressWarnings("unchecked")
160+
public List<FieldValue> repeatedValue() {
161+
return (List<FieldValue>) value;
162+
}
163+
164+
/**
165+
* Returns this field's value as a list of {@link FieldValue}. This method should only be used if
166+
* the corresponding field has {@link Field.Type#record(Field...)} type (i.e. {@link #kind()} is
167+
* {@link Kind#RECORD}).
168+
*
169+
* @throws ClassCastException if the field has not {@link Field.Type#record(Field...)} type
170+
*/
171+
@SuppressWarnings("unchecked")
172+
public List<FieldValue> recordValue() {
173+
return (List<FieldValue>) value;
174+
}
175+
176+
@Override
177+
public String toString() {
178+
return MoreObjects.toStringHelper(this)
179+
.add("kind", kind)
180+
.add("value", value)
181+
.toString();
182+
}
183+
184+
@Override
185+
public int hashCode() {
186+
return Objects.hash(kind, value);
187+
}
188+
189+
@Override
190+
public boolean equals(Object obj) {
191+
if (!(obj instanceof FieldValue)) {
192+
return false;
193+
}
194+
FieldValue other = (FieldValue) obj;
195+
return kind == other.kind && Objects.equals(value, other.value);
196+
}
197+
198+
@SuppressWarnings("unchecked")
199+
static FieldValue fromPb(Object cellPb) {
200+
if (Data.isNull(cellPb)) {
201+
return new FieldValue(Kind.PRIMITIVE, null);
202+
}
203+
if (cellPb instanceof String) {
204+
return new FieldValue(Kind.PRIMITIVE, cellPb);
205+
}
206+
if (cellPb instanceof List) {
207+
List<Object> cellsListPb = (List<Object>) cellPb;
208+
List<FieldValue> repeatedCells = Lists.newArrayListWithCapacity(cellsListPb.size());
209+
for (Object repeatedCellPb : cellsListPb) {
210+
repeatedCells.add(FieldValue.fromPb(repeatedCellPb));
211+
}
212+
return new FieldValue(Kind.REPEATED, repeatedCells);
213+
}
214+
if (cellPb instanceof Map) {
215+
Map<String, Object> cellMapPb = (Map<String, Object>) cellPb;
216+
if (cellMapPb.containsKey("f")) {
217+
List<Object> cellsListPb = (List<Object>) cellMapPb.get("f");
218+
List<FieldValue> recordCells = Lists.newArrayListWithCapacity(cellsListPb.size());
219+
for (Object repeatedCellPb : cellsListPb) {
220+
recordCells.add(FieldValue.fromPb(repeatedCellPb));
221+
}
222+
return new FieldValue(Kind.RECORD, recordCells);
223+
}
224+
// This should never be the case when we are processing a first level table field (i.e. a
225+
// row's field, not a record sub-field)
226+
if (cellMapPb.containsKey("v")) {
227+
return FieldValue.fromPb(cellMapPb.get("v"));
228+
}
229+
}
230+
throw new AssertionError("Unexpected table cell format");
231+
}
232+
}

0 commit comments

Comments
 (0)