/* * Copyright 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.samsung.appengine.web.server; import com.samsung.appengine.allshared.Model; import com.samsung.appengine.javashared.JsonSerializable; import com.samsung.appengine.javashared.Util; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import com.google.appengine.api.datastore.Text; import com.google.appengine.api.users.User; import org.json.JSONException; import org.json.JSONObject; import java.text.ParseException; import java.util.Arrays; import java.util.Date; import java.util.HashSet; import java.util.Set; import javax.jdo.annotations.Extension; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.NotPersistent; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; /** * Data model implementation for the JumpNote App Engine server. ModelImpl serves more as a * namespace than a class, for convenience. The base interfaces are defined in * the {@link Model} class. */ public class ModelImpl { @PersistenceCapable public static final class Alert implements Model.Alert, JsonSerializable { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent @Extension(vendorName = "datanucleus", key = "gae.parent-pk", value = "true") private Key ownerKey; // only set this when creating a note @Persistent private String targetId; @Persistent private Text body; @Persistent private Date createdDate; @Persistent private Date modifiedDate; @Persistent private boolean pendingDelete; /** * Used only during sync; when clients upload new entries, the server's * sync response will include a local ID and server-side ID so the * client can match them up. */ @NotPersistent private String localId; public Alert(String ownerId) { this.ownerKey = UserInfo.makeKey(ownerId); this.createdDate = new Date(); this.modifiedDate = new Date(); touch(); } public Alert(JSONObject json) throws JSONException { this.createdDate = new Date(); this.modifiedDate = new Date(); this.fromJSON(json); } public void fromJSON(Object object) throws JSONException { JSONObject json = (JSONObject) object; if (json.has("id")) this.key = Alert.makeKey(json.getString("owner_id"), json.getString("id")); else this.ownerKey = UserInfo.makeKey(json.getString("owner_id")); this.localId = json.optString("local_id", this.localId); this.targetId = json.optString("targetId", this.targetId); if (json.has("body")) this.body = new Text(json.getString("body")); if (json.optBoolean("delete", false)) markForDeletion(); touch(); try { if (json.has("date_created")) this.createdDate = Util.parseDateISO8601(json.getString("date_created")); if (json.has("date_modified")) this.modifiedDate = Util.parseDateISO8601(json.getString("date_modified")); } catch (ParseException e) { throw new JSONException("Invalid date."); } } public Object toJSON() throws JSONException { JSONObject json = new JSONObject(); json.put("id", getId()); json.put("owner_id", getOwnerId()); json.put("targetId", getTargetId()); json.put("body", getBody()); json.put("date_created", Util.formatDateISO8601(getCreatedDate())); json.put("date_modified", Util.formatDateISO8601(getModifiedDate())); if (isPendingDelete()) json.put("delete", true); if (getLocalId() != null) json.put("local_id", getLocalId()); return json; } @Override public boolean equals(Object obj) { if (getKey() == null ||( (Alert) obj).getKey() == null) return false; if (obj instanceof Alert) return ((Alert) obj).getKey().equals(getKey()); return false; } @Override public int hashCode() { return (getKey() == null) ? 0 : getKey().hashCode(); } public Key getKey() { return key; } public String getLocalId() { return localId; } public static Key makeKey(String ownerId, String id) { return KeyFactory.createKey(UserInfo.makeKey(ownerId), "ModelImpl$Note", Long.parseLong(id)); } public String getId() { return Long.toString(key.getId()); } public String getTargetId() { return targetId; } public void setTargetId(String targetId) { this.targetId = targetId; touch(); } public String getBody() { return (body == null) ? null : body.getValue(); } public void setBody(String body) { this.body = new Text(body); } public String getOwnerId() { return (this.ownerKey != null) ? this.ownerKey.getName() : (this.key != null ? this.key.getParent().getName() : null); } public Date getCreatedDate() { return createdDate; } public Date getModifiedDate() { return modifiedDate; } public boolean isPendingDelete() { return pendingDelete; } public void markForDeletion() { targetId = ""; body = new Text(""); pendingDelete = true; touch(); } public void touch() { modifiedDate = new Date(); } } @PersistenceCapable public static final class UserInfo implements Model.UserInfo, JsonSerializable { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private String id; @Persistent private String email; public UserInfo(User user) { this.id = user.getUserId(); this.email = user.getEmail(); } public UserInfo(String userId, String email) { this.id = userId; this.email = email; } public UserInfo(JSONObject json) throws JSONException { this.fromJSON(json); } public void fromJSON(Object object) throws JSONException { JSONObject json = (JSONObject) object; this.id = json.getString("id"); this.email = json.getString("email"); } public JSONObject toJSON() throws JSONException { JSONObject json = new JSONObject(); json.put("id", getId()); json.put("email", getEmail()); return json; } public String getId() { return id; } @Override public boolean equals(Object obj) { if (obj instanceof UserInfo) return ((UserInfo) obj).getKey().equals(getKey()); return false; } public Key getKey() { return UserInfo.makeKey(this.id); } public static Key makeKey(String id) { return KeyFactory.createKey("ModelImpl$UserInfo", id); } public String getEmail() { return email; } } @PersistenceCapable public static final class DeviceRegistration implements Model.DeviceRegistration, JsonSerializable { public static final Set<String> KNOWN_DEVICE_TYPES = new HashSet<String>( Arrays.asList(new String[] { "android" })); @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent @Extension(vendorName = "datanucleus", key = "gae.parent-pk", value = "true") private Key ownerKey; // only set this when creating a registration @Persistent private String deviceId; @Persistent private String deviceType; @Persistent private String registrationToken; public DeviceRegistration(String ownerId, String deviceId, String deviceType, String registrationToken) { this.ownerKey = UserInfo.makeKey(ownerId); this.deviceId = deviceId; this.deviceType = deviceType; this.registrationToken = registrationToken; } public DeviceRegistration(JSONObject json) throws JSONException { this.fromJSON(json); } public void fromJSON(Object object) throws JSONException { JSONObject json = (JSONObject) object; this.ownerKey = UserInfo.makeKey(json.getString("owner_id")); this.deviceId = json.getString("device_id"); try { setDeviceType(json.getString("device_type")); } catch (IllegalArgumentException e) { throw new JSONException("Unknown device type."); } if (json.has("registration_token")) this.registrationToken = json.getString("registration_token"); } public JSONObject toJSON() throws JSONException { JSONObject json = new JSONObject(); json.put("owner_id", getOwnerId()); json.put("device_id", getDeviceId()); json.put("device_type", getDeviceType()); if (getRegistrationToken() != null) json.put("registration_token", getRegistrationToken()); return json; } public Key getKey() { return key; } public String getOwnerId() { return (this.ownerKey != null) ? this.ownerKey.getName() : (this.key != null ? this.key.getParent().getName() : null); } public String getDeviceId() { return deviceId; } public void setDeviceId(String deviceId) { this.deviceId = deviceId; } public String getDeviceType() { return deviceType; } public void setDeviceType(String deviceType) throws IllegalArgumentException { if (!KNOWN_DEVICE_TYPES.contains(deviceType)) throw new IllegalArgumentException("Unknown device type."); this.deviceType = deviceType; } public String getRegistrationToken() { return registrationToken; } public void setRegistrationToken(String registrationToken) { this.registrationToken = registrationToken; } } }