1 /* 2 * Copyright (C) 2015 The Android Open Source Project 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.android.auto.mapservice; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 22 import java.util.Calendar; 23 import java.util.Date; 24 import java.util.List; 25 import java.util.Locale; 26 import java.util.TimeZone; 27 import java.util.regex.Matcher; 28 import java.util.regex.Pattern; 29 30 import org.json.JSONException; 31 import org.json.JSONObject; 32 33 public class BluetoothMapMessagesListing implements Parcelable { 34 35 // Fields for Messages Listing object as defined in MAPv12 Spec. 36 private String mHandle; 37 private String mSubject; 38 private Date mDateTime; 39 private String mSender; 40 private String mSenderAddress; 41 private String mReplyAddress; 42 private String mRecipient; 43 private String mRecipientAddress; 44 private int mType; 45 private int mSize; 46 private boolean mText; 47 private int mReceptionStatus; 48 private int mAttachmentSize; 49 private boolean mPriority; 50 private boolean mRead; 51 private boolean mSent; 52 private boolean mProtected; 53 54 public BluetoothMapMessagesListing() { } 55 56 public static final Parcelable.Creator<BluetoothMapMessagesListing> CREATOR = 57 new Parcelable.Creator<BluetoothMapMessagesListing>() { 58 public BluetoothMapMessagesListing createFromParcel(Parcel in) { 59 return new BluetoothMapMessagesListing(in); 60 } 61 62 public BluetoothMapMessagesListing[] newArray(int size) { 63 return new BluetoothMapMessagesListing[size]; 64 } 65 }; 66 67 private BluetoothMapMessagesListing(Parcel in) { 68 readFromParcel(in); 69 } 70 71 public void writeToParcel(Parcel out, int flags) { 72 out.writeString(mHandle); 73 out.writeString(mSubject); 74 out.writeString(dateToString(mDateTime)); 75 out.writeString(mSender); 76 out.writeString(mSenderAddress); 77 out.writeString(mReplyAddress); 78 out.writeString(mRecipient); 79 out.writeString(mRecipientAddress); 80 out.writeInt(mType); 81 out.writeInt(mSize); 82 out.writeByte((byte) (mText ? 1 : 0)); 83 out.writeInt(mReceptionStatus); 84 out.writeInt(mAttachmentSize); 85 out.writeByte((byte) (mPriority ? 1 : 0)); 86 out.writeByte((byte) (mRead ? 1 : 0)); 87 out.writeByte((byte) (mSent ? 1 : 0)); 88 out.writeByte((byte) (mProtected ? 1 : 0)); 89 } 90 91 public int describeContents() { 92 return 0; 93 } 94 95 public void readFromParcel(Parcel in) { 96 mHandle = in.readString(); 97 mSubject = in.readString(); 98 mDateTime = stringToDate(in.readString()); 99 mSender = in.readString(); 100 mSenderAddress = in.readString(); 101 mReplyAddress = in.readString(); 102 mRecipient = in.readString(); 103 mRecipientAddress = in.readString(); 104 mType = in.readInt(); 105 mSize = in.readInt(); 106 mText = in.readByte() != 0; 107 mReceptionStatus = in.readInt(); 108 mAttachmentSize = in.readInt(); 109 mPriority = in.readByte() != 0; 110 mRead = in.readByte() != 0; 111 mSent = in.readByte() != 0; 112 mProtected = in.readByte() != 0; 113 } 114 115 public String getHandle() { 116 return mHandle; 117 } 118 119 public void setHandle(String handle) { 120 mHandle = handle; 121 } 122 123 public String getSubject() { 124 return mSubject; 125 } 126 127 public void setSubject(String subject) { 128 mSubject = subject; 129 } 130 131 public Date getDate() { 132 return mDateTime; 133 } 134 135 public void setDate(Date date) { 136 mDateTime = date; 137 } 138 139 public String getSender() { 140 return mSender; 141 } 142 143 public void setSender(String sender) { 144 mSender = sender; 145 } 146 147 @Override 148 public String toString() { 149 JSONObject json = new JSONObject(); 150 try { 151 json.put("handle", mHandle); 152 json.put("subject", mSubject); 153 json.put("datetime", mDateTime); 154 json.put("sender_name", mSender); 155 json.put("sender_addressing", mSenderAddress); 156 json.put("replyto_addressing", mReplyAddress); 157 json.put("recipient_name", mRecipient); 158 json.put("recipient_addressing", mRecipientAddress); 159 json.put("type", mType); 160 json.put("size", mSize); 161 json.put("text", mText); 162 json.put("reception_status", mReceptionStatus); 163 json.put("attachment_size", mAttachmentSize); 164 json.put("priority", mPriority); 165 json.put("read", mRead); 166 json.put("sent", mSent); 167 json.put("protected", mProtected); 168 } catch (JSONException ex) { 169 // do nothing. 170 } 171 172 return json.toString(); 173 } 174 175 private String dateToString(Date date) { 176 // Convert to MAPv12 acceptable format. 177 Calendar cal = Calendar.getInstance(); 178 cal.setTime(date); 179 return String.format(Locale.US, "%04d%02d%02dT%02d%02d%02d", 180 cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, 181 cal.get(Calendar.DATE), cal.get(Calendar.HOUR_OF_DAY), 182 cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND)); 183 } 184 185 private Date stringToDate(String time) { 186 // match OBEX time string: YYYYMMDDTHHMMSS with optional UTF offset 187 // +/-hhmm. 188 Pattern p = Pattern.compile( 189 "(\\d{4})(\\d{2})(\\d{2})T(\\d{2})(\\d{2})(\\d{2})(([+-])(\\d{2})(\\d{2}))?"); 190 Matcher m = p.matcher(time); 191 192 if (m.matches()) { 193 /* 194 * matched groups are numberes as follows: YYYY MM DD T HH MM SS + 195 * hh mm ^^^^ ^^ ^^ ^^ ^^ ^^ ^ ^^ ^^ 1 2 3 4 5 6 8 9 10 all groups 196 * are guaranteed to be numeric so conversion will always succeed 197 * (except group 8 which is either + or -) 198 */ 199 200 Calendar cal = Calendar.getInstance(); 201 cal.set(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)) - 1, 202 Integer.parseInt(m.group(3)), Integer.parseInt(m.group(4)), 203 Integer.parseInt(m.group(5)), Integer.parseInt(m.group(6))); 204 205 /* 206 * if 7th group is matched then we have UTC offset information 207 * included 208 */ 209 if (m.group(7) != null) { 210 int ohh = Integer.parseInt(m.group(9)); 211 int omm = Integer.parseInt(m.group(10)); 212 213 /* time zone offset is specified in miliseconds */ 214 int offset = (ohh * 60 + omm) * 60 * 1000; 215 216 if (m.group(8).equals("-")) { 217 offset = -offset; 218 } 219 220 TimeZone tz = TimeZone.getTimeZone("UTC"); 221 tz.setRawOffset(offset); 222 223 cal.setTimeZone(tz); 224 } 225 return cal.getTime(); 226 } else { 227 throw new IllegalStateException("Incorrect datetime format: " + mDateTime); 228 } 229 } 230 231 // TODO: Finish the getters and setters. 232 } 233