Skip to content

Commit 9bb82d9

Browse files
Pavle AndricPavle Andric
authored andcommitted
Merge pull request #54 in MML/infobip-mobile-messaging-android from tjuric-MM-1076-Custom_user_data to master
Squashed commit of the following: commit 128b0ce40819c28c72da2399c25dcf7e748e5f49 Author: pandric <pavle.andric@infobip.com> Date: Tue Nov 8 16:15:28 2016 +0100 - javadoc updated - tests fixed commit 8845d7ebba81b65372ae453180df80a9103d28b2 Merge: 6038d53 747c7e0 Author: pandric <pavle.andric@infobip.com> Date: Tue Nov 8 15:21:18 2016 +0100 Merge branch 'tjuric-MM-1076-Custom_user_data' of http://git.ib-ci.com/scm/mml/infobip-mobile-messaging-android into tjuric-MM-1076-Custom_user_data commit 6038d53f04e290e1c9afe2a190658f93722c2aaf Author: pandric <pavle.andric@infobip.com> Date: Tue Nov 8 15:21:00 2016 +0100 - CustomUserDataValue api model separated from domain model - UserDataMapper added to map CustomUserDataValue api model to/from domain model commit 747c7e0445a5bdaecb8a4cb2661b9858942af7f5 Author: tjuric <tereza.juric@infobip.com> Date: Mon Nov 7 17:03:28 2016 +0100 MM-1076 Optimized imports commit cfa84cd5672b27bbdee7f5347da751fd26df6cce Author: pandric <pavle.andric@infobip.com> Date: Mon Nov 7 16:17:21 2016 +0100 - ISO8601DateParseException added - syncUserData test added commit 430c7e3b50b880aae3dbf4861fcc2ae55cec0d9b Author: pandric <pavle.andric@infobip.com> Date: Mon Nov 7 13:23:57 2016 +0100 MobileApiDataTest removed hardcoded date formats commit 75a604b770709c8c0cc7cc5ea168dcc5937b3be3 Author: pandric <pavle.andric@infobip.com> Date: Mon Nov 7 13:15:30 2016 +0100 MobileApiDataTest added hardcoded date formats for better readability commit 04c955fa546f3dc01c2a30573f16418af15b45d9 Author: pandric <pavle.andric@infobip.com> Date: Mon Nov 7 13:08:47 2016 +0100 MobileApiDataTest fixed commit 31ddbb700516bccbebcacdbea1a089f33a4b3c26 Author: pandric <pavle.andric@infobip.com> Date: Mon Nov 7 12:46:58 2016 +0100 MobileApiDataTest fixed commit 92fd96c86bde7144fbb542bd7deca301996431d0 Author: pandric <pavle.andric@infobip.com> Date: Mon Nov 7 11:27:49 2016 +0100 Code cleanup commit a651bf5c846e75c9a0dca31e869e515d2776b5cc Author: pandric <pavle.andric@infobip.com> Date: Mon Nov 7 11:23:58 2016 +0100 Tests fixed commit 880903379d150475a28c4cd5cee97ac85399e93e Author: pandric <pavle.andric@infobip.com> Date: Fri Nov 4 19:21:56 2016 +0100 - CustomUserDataValue implemented - tests created - minor fixes commit 88a060c6f4b5fce7eebb615c18b9adf33a2c33b3 Author: tjuric <tereza.juric@infobip.com> Date: Thu Nov 3 10:38:49 2016 +0100 MM-1076 Custom user data commit ccb437dca00b2f0caed6228f6cac6b6786df0569 Author: tjuric <tereza.juric@infobip.com> Date: Thu Nov 3 10:38:25 2016 +0100 MM-1076 Custom user data commit 6997cd08e130713ac687c75431f3cef10acbdeb5 Merge: 68c5f3e fb7d535 Author: tjuric <tereza.juric@infobip.com> Date: Wed Nov 2 14:55:28 2016 +0100 Merge branch 'master' into tjuric-MM-1076-Custom_user_data commit 68c5f3ec57a01273847caf6c092494f3d5ed6110 Author: tjuric <tereza.juric@infobip.com> Date: Fri Oct 21 13:45:30 2016 +0200 MM-1076 Custom user data started implementation
1 parent fb7d535 commit 9bb82d9

16 files changed

Lines changed: 488 additions & 56 deletions

File tree

infobip-mobile-messaging-android-demo/src/main/java/org/infobip/mobile/messaging/demo/MainActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@
3030

3131
import org.infobip.mobile.messaging.BroadcastParameter;
3232
import org.infobip.mobile.messaging.Event;
33-
import org.infobip.mobile.messaging.geo.Geo;
3433
import org.infobip.mobile.messaging.Message;
3534
import org.infobip.mobile.messaging.MobileMessaging;
3635
import org.infobip.mobile.messaging.NotificationSettings;
3736
import org.infobip.mobile.messaging.UserData;
3837
import org.infobip.mobile.messaging.gcm.PlayServicesSupport;
38+
import org.infobip.mobile.messaging.geo.Geo;
3939
import org.infobip.mobile.messaging.storage.SharedPreferencesMessageStore;
4040
import org.infobip.mobile.messaging.util.StringUtils;
4141

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package org.infobip.mobile.messaging;
2+
3+
import android.content.BroadcastReceiver;
4+
import android.content.Context;
5+
import android.content.Intent;
6+
import android.content.IntentFilter;
7+
import android.test.InstrumentationTestCase;
8+
9+
import org.infobip.mobile.messaging.tools.DebugServer;
10+
import org.infobip.mobile.messaging.util.PreferenceHelper;
11+
import org.mockito.ArgumentCaptor;
12+
import org.mockito.Mockito;
13+
14+
import java.text.ParseException;
15+
import java.text.SimpleDateFormat;
16+
import java.util.Date;
17+
import java.util.HashMap;
18+
import java.util.Locale;
19+
import java.util.Map;
20+
21+
import fi.iki.elonen.NanoHTTPD;
22+
23+
public class CustomUserDataTypeTest extends InstrumentationTestCase {
24+
25+
private Context context;
26+
DebugServer debugServer;
27+
BroadcastReceiver receiver;
28+
ArgumentCaptor<Intent> captor;
29+
MobileMessaging mobileMessaging;
30+
31+
private static final String KEY_FOR_STRING = "keyForString";
32+
private static final String KEY_FOR_NUMBER = "keyForNumber";
33+
private static final String KEY_FOR_DATE = "keyForDate";
34+
35+
private final String SOME_STRING_VALUE = "bla";
36+
private final int SOME_NUMBER_VALUE = 1111;
37+
private final Date SOME_DATE_VALUE = new Date();
38+
39+
private String serverResponse = "{\n" +
40+
" \"customUserData\": {\n" +
41+
" \"" + KEY_FOR_DATE + "\": {\n" +
42+
" \"type\": \"Date\",\n" +
43+
" \"value\": \"" + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault()).format(SOME_DATE_VALUE) + "\"\n" +
44+
" },\n" +
45+
" \"" + KEY_FOR_NUMBER + "\": {\n" +
46+
" \"type\": \"Number\",\n" +
47+
" \"value\": 1111\n" +
48+
" },\n" +
49+
" \"" + KEY_FOR_STRING + "\": {\n" +
50+
" \"type\": \"String\",\n" +
51+
" \"value\": \"bla\"\n" +
52+
" }\n" +
53+
" },\n" +
54+
" \"externalUserId\": null,\n" +
55+
" \"predefinedUserData\": {}\n" +
56+
"}";
57+
58+
@Override
59+
protected void setUp() throws Exception {
60+
super.setUp();
61+
context = getInstrumentation().getContext();
62+
mobileMessaging = MobileMessaging.getInstance(context);
63+
64+
debugServer = new DebugServer();
65+
debugServer.start();
66+
67+
PreferenceHelper.saveString(getInstrumentation().getContext(), MobileMessagingProperty.API_URI, "http://127.0.0.1:" + debugServer.getListeningPort() + "/");
68+
PreferenceHelper.saveString(getInstrumentation().getContext(), MobileMessagingProperty.APPLICATION_CODE, "TestApplicationCode");
69+
PreferenceHelper.saveString(getInstrumentation().getContext(), MobileMessagingProperty.INFOBIP_REGISTRATION_ID, "TestDeviceInstanceId");
70+
71+
captor = ArgumentCaptor.forClass(Intent.class);
72+
receiver = Mockito.mock(BroadcastReceiver.class);
73+
context.registerReceiver(receiver, new IntentFilter(Event.USER_DATA_REPORTED.getKey()));
74+
}
75+
76+
@Override
77+
protected void tearDown() throws Exception {
78+
context.unregisterReceiver(receiver);
79+
80+
if (null != debugServer) {
81+
try {
82+
debugServer.stop();
83+
} catch (Exception e) {
84+
//ignore
85+
}
86+
}
87+
PreferenceHelper.remove(context, MobileMessagingProperty.USER_DATA);
88+
89+
super.tearDown();
90+
}
91+
92+
public void test_sync_user_data() {
93+
debugServer.respondWith(NanoHTTPD.Response.Status.OK, serverResponse);
94+
95+
UserData userData = new UserData();
96+
userData.setCustomUserDataElement(KEY_FOR_STRING, new CustomUserDataValue(SOME_STRING_VALUE));
97+
userData.setCustomUserDataElement(KEY_FOR_NUMBER, new CustomUserDataValue(SOME_NUMBER_VALUE));
98+
userData.setCustomUserDataElement(KEY_FOR_DATE, new CustomUserDataValue(SOME_DATE_VALUE));
99+
MobileMessaging.getInstance(context).syncUserData(userData);
100+
101+
Mockito.verify(receiver, Mockito.after(1000).atLeastOnce()).onReceive(Mockito.any(Context.class), captor.capture());
102+
assertTrue(captor.getValue().hasExtra(BroadcastParameter.EXTRA_USER_DATA));
103+
104+
UserData userDataResponse = UserData.createFrom(captor.getValue().getExtras());
105+
assertEquals(SOME_STRING_VALUE, userDataResponse.getCustomUserDataValue(KEY_FOR_STRING).stringValue());
106+
assertEquals(SOME_NUMBER_VALUE, userDataResponse.getCustomUserDataValue(KEY_FOR_NUMBER).numberValue().intValue());
107+
assertEquals(SOME_DATE_VALUE.toString(), userDataResponse.getCustomUserDataValue(KEY_FOR_DATE).dateValue().toString());
108+
}
109+
110+
public void test_get_custom_user_data_value_from_json_string() throws ParseException {
111+
UserData userData = new UserData(serverResponse);
112+
String keyForString = userData.getCustomUserDataValue(KEY_FOR_STRING).stringValue();
113+
Number keyForNumber = userData.getCustomUserDataValue(KEY_FOR_NUMBER).numberValue();
114+
Date keyForDate = userData.getCustomUserDataValue(KEY_FOR_DATE).dateValue();
115+
116+
assertEquals(SOME_STRING_VALUE, keyForString);
117+
assertEquals(SOME_NUMBER_VALUE, keyForNumber.intValue());
118+
assertEquals(SOME_DATE_VALUE.toString(), keyForDate.toString());
119+
120+
Map<String, CustomUserDataValue> customUserData = userData.getCustomUserData();
121+
assertEquals(3, customUserData.size());
122+
}
123+
124+
public void test_set_multi_custom_user_data() throws ParseException {
125+
Date date = new Date();
126+
HashMap<String, CustomUserDataValue> userDataValueHashMap = new HashMap<>();
127+
userDataValueHashMap.put(KEY_FOR_STRING, new CustomUserDataValue(SOME_STRING_VALUE));
128+
userDataValueHashMap.put(KEY_FOR_NUMBER, new CustomUserDataValue(SOME_NUMBER_VALUE));
129+
userDataValueHashMap.put(KEY_FOR_DATE, new CustomUserDataValue(date));
130+
131+
UserData userData = new UserData();
132+
userData.setCustomUserData(userDataValueHashMap);
133+
134+
String keyForString = userData.getCustomUserDataValue(KEY_FOR_STRING).stringValue();
135+
Number keyForNumber = userData.getCustomUserDataValue(KEY_FOR_NUMBER).numberValue();
136+
Date keyForDate = userData.getCustomUserDataValue(KEY_FOR_DATE).dateValue();
137+
138+
assertEquals(SOME_STRING_VALUE, keyForString);
139+
assertEquals(SOME_NUMBER_VALUE, keyForNumber.intValue());
140+
assertEquals(date.toString(), keyForDate.toString());
141+
142+
Map<String, CustomUserDataValue> customUserData = userData.getCustomUserData();
143+
assertEquals(3, customUserData.size());
144+
}
145+
}

infobip-mobile-messaging-android-sdk/src/androidTest/java/org/infobip/mobile/messaging/GeoReportsTest.java

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ public void test_success() throws Exception {
7676
debugServer.respondWith(NanoHTTPD.Response.Status.OK, null);
7777

7878
List<GeoReport> reports = new ArrayList<>();
79-
reports.add(new GeoReport("campaignId1", GeoEventType.entry, new Area("areaId1", "Area1", 1.0, 1.0, 3), 1001L));
80-
reports.add(new GeoReport("campaignId2", GeoEventType.exit, new Area("areaId2", "Area2", 2.0, 2.0, 4), 1002L));
81-
reports.add(new GeoReport("campaignId3", GeoEventType.dwell, new Area("areaId3", "Area3", 3.0, 3.0, 5), 1003L));
79+
reports.add(new GeoReport("campaignId1", "messageId1", GeoEventType.entry, new Area("areaId1", "Area1", 1.0, 1.0, 3), 1001L));
80+
reports.add(new GeoReport("campaignId2", "messageId2", GeoEventType.exit, new Area("areaId2", "Area2", 2.0, 2.0, 4), 1002L));
81+
reports.add(new GeoReport("campaignId3", "messageId3", GeoEventType.dwell, new Area("areaId3", "Area3", 3.0, 3.0, 5), 1003L));
8282

8383
MobileMessagingCore.getInstance(context).addUnreportedGeoEvents(reports);
8484
geoReporter.report(context, MobileMessagingCore.getInstance(context).getStats());
@@ -93,6 +93,7 @@ public void test_success() throws Exception {
9393
GeoReport geoReport1 = broadcastedReports.get(0);
9494
assertEquals(geoReport1.getEvent(), GeoEventType.entry);
9595
assertEquals(geoReport1.getCampaignId(), "campaignId1");
96+
assertEquals(geoReport1.getMessageId(), "messageId1");
9697
assertEquals(geoReport1.getTimestampOccured(), (Long) 1001L);
9798
assertEquals(geoReport1.getArea().getId(), "areaId1");
9899
assertEquals(geoReport1.getArea().getTitle(), "Area1");
@@ -103,6 +104,7 @@ public void test_success() throws Exception {
103104
GeoReport geoReport2 = broadcastedReports.get(1);
104105
assertEquals(geoReport2.getEvent(), GeoEventType.exit);
105106
assertEquals(geoReport2.getCampaignId(), "campaignId2");
107+
assertEquals(geoReport2.getMessageId(), "messageId2");
106108
assertEquals(geoReport2.getTimestampOccured(), (Long) 1002L);
107109
assertEquals(geoReport2.getArea().getId(), "areaId2");
108110
assertEquals(geoReport2.getArea().getTitle(), "Area2");
@@ -113,6 +115,7 @@ public void test_success() throws Exception {
113115
GeoReport geoReport3 = broadcastedReports.get(2);
114116
assertEquals(geoReport3.getEvent(), GeoEventType.dwell);
115117
assertEquals(geoReport3.getCampaignId(), "campaignId3");
118+
assertEquals(geoReport3.getMessageId(), "messageId3");
116119
assertEquals(geoReport3.getTimestampOccured(), (Long) 1003L);
117120
assertEquals(geoReport3.getArea().getId(), "areaId3");
118121
assertEquals(geoReport3.getArea().getTitle(), "Area3");
@@ -129,27 +132,30 @@ public void test_success() throws Exception {
129132
assertEquals(body.getReports().length, 3);
130133
JSONAssert.assertEquals(debugServer.getBody(),
131134
"{" +
132-
"\"reports\": [" +
135+
"\"reports\": [" +
133136
"{" +
134-
"\"event\":\"entry\"," +
135-
"\"geoAreaId\":\"areaId1\"," +
136-
"\"campaignId\":\"campaignId1\"," +
137-
"\"timestampDelta\":" + body.getReports()[0].getTimestampDelta() +
137+
"\"event\":\"entry\"," +
138+
"\"geoAreaId\":\"areaId1\"," +
139+
"\"messageId\":\"messageId1\"," +
140+
"\"campaignId\":\"campaignId1\"," +
141+
"\"timestampDelta\":" + body.getReports()[0].getTimestampDelta() +
138142
"}," +
139143
"{" +
140-
"\"event\":\"exit\"," +
141-
"\"geoAreaId\":\"areaId2\"," +
142-
"\"campaignId\":\"campaignId2\"," +
143-
"\"timestampDelta\":" + body.getReports()[1].getTimestampDelta() +
144+
"\"event\":\"exit\"," +
145+
"\"geoAreaId\":\"areaId2\"," +
146+
"\"messageId\":\"messageId2\"," +
147+
"\"campaignId\":\"campaignId2\"," +
148+
"\"timestampDelta\":" + body.getReports()[1].getTimestampDelta() +
144149
"}," +
145150
"{" +
146-
"\"event\":\"dwell\"," +
147-
"\"geoAreaId\":\"areaId3\"," +
148-
"\"campaignId\":\"campaignId3\"," +
149-
"\"timestampDelta\":" + body.getReports()[2].getTimestampDelta() +
151+
"\"event\":\"dwell\"," +
152+
"\"geoAreaId\":\"areaId3\"," +
153+
"\"messageId\":\"messageId3\"," +
154+
"\"campaignId\":\"campaignId3\"," +
155+
"\"timestampDelta\":" + body.getReports()[2].getTimestampDelta() +
150156
"}" +
151-
"]" +
152-
"}"
157+
"]" +
158+
"}"
153159
, true);
154160

155161
assertNotSame(body.getReports()[0].getTimestampDelta(), body.getReports()[1].getTimestampDelta());
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package org.infobip.mobile.messaging;
2+
3+
import org.infobip.mobile.messaging.util.ISO8601DateParseException;
4+
5+
import java.text.ParseException;
6+
import java.text.SimpleDateFormat;
7+
import java.util.Date;
8+
import java.util.Locale;
9+
import java.util.Map;
10+
11+
/**
12+
* This class wraps user data types used to interact with backend services. The custom parameters may be of following types:
13+
* <ul>
14+
* <li>{@link String}</li>
15+
* <li>{@link Number}</li>
16+
* <li>{@link Date}</li>
17+
* </ul>
18+
*
19+
* @see UserData#setCustomUserData(Map)
20+
* @see UserData#setCustomUserDataElement(String, CustomUserDataValue)
21+
* @see UserData#getCustomUserData()
22+
* @see UserData#getCustomUserDataValue(String)
23+
*/
24+
public class CustomUserDataValue {
25+
26+
private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";
27+
private static final String GMT_TIME_ZONE = "+00:00";
28+
private static final String ISO8601_GMT_Z_MATCHER = "Z$";
29+
30+
private Object value;
31+
private String type;
32+
33+
public CustomUserDataValue() {
34+
}
35+
36+
public CustomUserDataValue(String someString) {
37+
set(someString);
38+
}
39+
40+
public CustomUserDataValue(Number someNumber) {
41+
set(someNumber);
42+
}
43+
44+
public CustomUserDataValue(Date someDate) {
45+
set(someDate);
46+
}
47+
48+
public void set(String someString) {
49+
this.value = someString;
50+
this.type = getTypeForValue(someString);
51+
}
52+
53+
public void set(Number someNumber) {
54+
this.value = someNumber;
55+
this.type = getTypeForValue(someNumber);
56+
}
57+
58+
public void set(Date someDate) {
59+
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.getDefault());
60+
this.value = simpleDateFormat.format(someDate);
61+
this.type = getTypeForValue(someDate);
62+
}
63+
64+
/**
65+
* Return the value of specified {@code CustomUserDataValue} as {@link String}.
66+
*
67+
* @return {@link String}
68+
* @throws ClassCastException if {@code CustomUserDataValue} is not type of {@link String}
69+
*/
70+
public String stringValue() {
71+
if (!(value instanceof String)) {
72+
throw new ClassCastException();
73+
}
74+
75+
return (String) value;
76+
}
77+
78+
/**
79+
* Return the value of specified {@code CustomUserDataValue} as {@link Number}.
80+
*
81+
* @return {@link Number}
82+
* @throws ClassCastException if {@code CustomUserDataValue} is not type of {@link Number}
83+
*/
84+
public Number numberValue() {
85+
if (!(value instanceof Number)) {
86+
throw new ClassCastException();
87+
}
88+
89+
return (Number) value;
90+
}
91+
92+
/**
93+
* Return the value of specified {@code CustomUserDataValue} as {@link Date}.
94+
*
95+
* @return {@link Date}
96+
* @throws ISO8601DateParseException if {@code CustomUserDataValue} is not type of {@link Date}.
97+
*/
98+
public Date dateValue() {
99+
String dateValue = (String) this.value;
100+
String date = dateValue.trim().replaceAll(ISO8601_GMT_Z_MATCHER, GMT_TIME_ZONE);
101+
try {
102+
return new SimpleDateFormat(DATE_FORMAT, Locale.getDefault()).parse(date);
103+
} catch (ParseException e) {
104+
throw new ISO8601DateParseException(ISO8601DateParseException.Reason.DATE_PARSE_EXCEPTION, e);
105+
}
106+
}
107+
108+
public Object getValue() {
109+
return value;
110+
}
111+
112+
public String getType() {
113+
return type;
114+
}
115+
116+
private String getTypeForValue(Object value) {
117+
if (value instanceof String) {
118+
return "String";
119+
}
120+
121+
if (value instanceof Date) {
122+
return "Date";
123+
}
124+
125+
if (value instanceof Number) {
126+
return "Number";
127+
}
128+
129+
return null;
130+
}
131+
}

0 commit comments

Comments
 (0)