Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / api / datastore / RawValue.java
blob99fad337b1e7f8970540167e4537f7fe21c9ace3
1 // Copyright 2012 Google Inc. All Rights Reserved.
3 package com.google.appengine.api.datastore;
5 import static com.google.common.base.Preconditions.checkArgument;
6 import static com.google.common.base.Preconditions.checkNotNull;
8 import com.google.appengine.api.blobstore.BlobKey;
9 import com.google.appengine.api.datastore.DataTypeTranslator.Type;
10 import com.google.appengine.api.users.User;
11 import com.google.apphosting.datastore.EntityV4;
12 import com.google.storage.onestore.v3.OnestoreEntity.PropertyValue;
14 import java.io.IOException;
15 import java.io.Serializable;
16 import java.util.Arrays;
18 /**
19 * A raw datastore value.
21 * These are returned by projection queries when a {@link PropertyProjection} does not
22 * specify a type.
24 * @see Query#getProjections()
26 public final class RawValue implements Serializable {
27 private static final long serialVersionUID = 8176992854378814427L;
28 private transient PropertyValue valueV3 = null;
29 private transient EntityV4.Value valueV4 = null;
31 RawValue(PropertyValue propertyValue) {
32 this.valueV3 = checkNotNull(propertyValue);
35 RawValue(EntityV4.Value propertyValue) {
36 this.valueV4 = checkNotNull(propertyValue);
39 /**
40 * Returns an object of the exact type passed in.
42 * @param type the class object for the desired type
43 * @return an object of type T or {@code null}
44 * @throws IllegalArgumentException if the raw value cannot be converted into the given type
46 @SuppressWarnings("unchecked")
47 public <T> T asStrictType(Class<T> type) {
48 Object value = asType(type);
49 if (value != null) {
50 checkArgument(type.isAssignableFrom(value.getClass()), "Unsupported type: " + type);
52 return (T) value;
55 /**
56 * Returns the object normally returned by the datastore if given type is passed in.
58 * All integer values are returned as {@link Long}.
59 * All floating point values are returned as {@link Double}.
61 * @param type the class object for the desired type
62 * @return an object of type T or {@code null}
63 * @throws IllegalArgumentException if the raw value cannot be converted into the given type
65 public Object asType(Class<?> type) {
66 Type<?> typeAdapter = DataTypeTranslator.getTypeMap().get(type);
67 checkArgument(typeAdapter != null, "Unsupported type: " + type);
69 if (valueV3 != null) {
70 if (typeAdapter.hasValue(valueV3)) {
71 return typeAdapter.getValue(valueV3);
73 } else if (valueV4 != null) {
74 if (typeAdapter.hasValue(valueV4)) {
75 return typeAdapter.getValue(valueV4);
79 checkArgument(getValue() == null, "Type mismatch.");
80 return null;
83 /**
84 * Returns the raw value.
86 * @return An object of type {@link Boolean}, {@link Double}, {@link GeoPt}, {@link Key},
87 * {@code byte[]}, {@link User} or {@code null}.
89 public Object getValue() {
90 if (valueV3 != null) {
91 if (valueV3.hasBooleanValue()) {
92 return valueV3.isBooleanValue();
93 } else if (valueV3.hasDoubleValue()) {
94 return valueV3.getDoubleValue();
95 } else if (valueV3.hasInt64Value()) {
96 return valueV3.getInt64Value();
97 } else if (valueV3.hasPointValue()) {
98 return asType(GeoPt.class);
99 } else if (valueV3.hasReferenceValue()) {
100 return asType(Key.class);
101 } else if (valueV3.hasStringValue()) {
102 return valueV3.getStringValueAsBytes();
103 } else if (valueV3.hasUserValue()) {
104 return asType(User.class);
106 } else if (valueV4 != null) {
107 if (valueV4.hasBooleanValue()) {
108 return valueV4.getBooleanValue();
109 } else if (valueV4.hasDoubleValue()) {
110 return valueV4.getDoubleValue();
111 } else if (valueV4.hasIntegerValue()) {
112 return valueV4.getIntegerValue();
113 } else if (valueV4.hasEntityValue()) {
114 if (valueV4.getMeaning() == 20) {
115 return asType(User.class);
117 return asType(GeoPt.class);
118 } else if (valueV4.hasKeyValue()) {
119 return asType(Key.class);
120 } else if (valueV4.hasStringValue()) {
121 return valueV4.getStringValueBytes().toByteArray();
122 } else if (valueV4.hasBlobKeyValue()) {
123 return asType(BlobKey.class);
124 } else if (valueV4.hasBlobValue()) {
125 return valueV4.getBlobValue().toByteArray();
126 } else if (valueV4.hasTimestampMicrosecondsValue()) {
127 return valueV4.getTimestampMicrosecondsValue();
128 } else if (valueV4.hasGeoPointValue()) {
129 return asType(GeoPt.class);
132 return null;
135 private void writeObject(java.io.ObjectOutputStream out) throws IOException {
136 if (valueV3 != null) {
137 out.write(1);
138 valueV3.writeTo(out);
139 } else {
140 out.write(2);
141 valueV4.writeTo(out);
143 out.defaultWriteObject();
146 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
147 int version = in.read();
148 if (version == 1) {
149 valueV3 = new PropertyValue();
150 valueV3.parseFrom(in);
151 } else if (version == 2) {
152 valueV4 = EntityV4.Value.PARSER.parseFrom(in);
153 } else {
154 checkArgument(false, "unknown RawValue format");
156 in.defaultReadObject();
159 @Override
160 public int hashCode() {
161 Object value = getValue();
162 return value == null ? 0 : value.hashCode();
165 @Override
166 public boolean equals(Object obj) {
167 if (this == obj) return true;
168 if (obj == null) return false;
169 if (getClass() != obj.getClass()) return false;
170 RawValue other = (RawValue) obj;
171 Object value = getValue();
172 Object otherValue = other.getValue();
173 if (value != null) {
174 if (otherValue != null) {
175 if (value instanceof byte[]) {
176 if (otherValue instanceof byte[]) {
177 return Arrays.equals((byte[]) value, (byte[]) otherValue);
179 } else {
180 return value.equals(otherValue);
183 } else if (otherValue == null) {
184 return true;
186 return false;
189 @Override
190 public String toString() {
191 return "RawValue [value=" + getValue() + "]";