Skip to content

Commit 8051cc2

Browse files
committed
androidannotations#264 - using Apache ObjectSerializer.
1 parent 518a5e2 commit 8051cc2

10 files changed

Lines changed: 290 additions & 1 deletion

File tree

‎AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/api/sharedpreferences/SharedPreferencesHelper.java‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ protected StringPrefField stringField(String key, String defaultValue) {
4141
return new StringPrefField(sharedPreferences, key, defaultValue);
4242
}
4343

44+
protected StringSetPrefField stringSetField(String key) {
45+
return new StringSetPrefField(sharedPreferences, key);
46+
}
47+
4448
protected BooleanPrefField booleanField(String key, boolean defaultValue) {
4549
return new BooleanPrefField(sharedPreferences, key, defaultValue);
4650
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* 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, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.api.sharedpreferences;
17+
18+
import java.util.Set;
19+
20+
public final class StringSetPrefEditorField<T extends EditorHelper<T>> extends AbstractPrefEditorField<T> {
21+
22+
StringSetPrefEditorField(T editorHelper, String key) {
23+
super(editorHelper, key);
24+
}
25+
26+
public T put(Set<String> value) {
27+
StringSetPrefField.setValue(editorHelper.getEditor(), key, value);
28+
29+
return editorHelper;
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* Copyright (C) 2010-2013 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* 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, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.api.sharedpreferences;
17+
18+
import java.io.IOException;
19+
import java.io.Serializable;
20+
import java.util.Set;
21+
import java.util.TreeSet;
22+
23+
import org.apache.pig.impl.util.ObjectSerializer;
24+
25+
import android.content.SharedPreferences;
26+
import android.content.SharedPreferences.Editor;
27+
28+
public final class StringSetPrefField extends AbstractPrefField {
29+
30+
StringSetPrefField(SharedPreferences sharedPreferences, String key) {
31+
super(sharedPreferences, key);
32+
}
33+
34+
public Set<String> get() {
35+
return getOr(new TreeSet<String>());
36+
}
37+
38+
@SuppressWarnings("unchecked")
39+
public Set<String> getOr(Set<String> defaultValue) {
40+
Object obj;
41+
try {
42+
obj = ObjectSerializer.deserialize(sharedPreferences.getString(key, null));
43+
} catch (IOException e) {
44+
return null;
45+
}
46+
47+
if(obj == null) {
48+
return defaultValue;
49+
}
50+
51+
if(!(obj instanceof Set<?>)) {
52+
return defaultValue;
53+
}
54+
55+
// No way to check further.
56+
57+
return (Set<String>) obj;
58+
}
59+
60+
public void put(Set<String> value) {
61+
SharedPreferences.Editor editor = sharedPreferences.edit();
62+
setValue(editor, key, value);
63+
apply(editor);
64+
}
65+
66+
static void setValue(Editor editor, String key, Set<String> value) {
67+
try {
68+
editor.putString(key, ObjectSerializer.serialize((Serializable) value));
69+
} catch (IOException e) {
70+
throw new RuntimeException("Argument for key `" + key + "` does not implement the Serializable interface");
71+
}
72+
}
73+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.pig.impl.util;
20+
21+
import java.io.ByteArrayInputStream;
22+
import java.io.ByteArrayOutputStream;
23+
import java.io.IOException;
24+
import java.io.ObjectInputStream;
25+
import java.io.ObjectOutputStream;
26+
import java.io.Serializable;
27+
28+
public class ObjectSerializer {
29+
30+
public static String serialize(Serializable obj) throws IOException {
31+
if (obj == null) return "";
32+
try {
33+
ByteArrayOutputStream serialObj = new ByteArrayOutputStream();
34+
ObjectOutputStream objStream = new ObjectOutputStream(serialObj);
35+
objStream.writeObject(obj);
36+
objStream.close();
37+
return encodeBytes(serialObj.toByteArray());
38+
} catch (Exception e) {
39+
throw WrappedIOException.wrap("Serialization error: " + e.getMessage(), e);
40+
}
41+
}
42+
43+
public static Object deserialize(String str) throws IOException {
44+
if (str == null || str.length() == 0) return null;
45+
try {
46+
ByteArrayInputStream serialObj = new ByteArrayInputStream(decodeBytes(str));
47+
ObjectInputStream objStream = new ObjectInputStream(serialObj);
48+
return objStream.readObject();
49+
} catch (Exception e) {
50+
throw WrappedIOException.wrap("Deserialization error: " + e.getMessage(), e);
51+
}
52+
}
53+
54+
public static String encodeBytes(byte[] bytes) {
55+
StringBuffer strBuf = new StringBuffer();
56+
57+
for (int i = 0; i < bytes.length; i++) {
58+
strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a')));
59+
strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a')));
60+
}
61+
62+
return strBuf.toString();
63+
}
64+
65+
public static byte[] decodeBytes(String str) {
66+
byte[] bytes = new byte[str.length() / 2];
67+
for (int i = 0; i < str.length(); i+=2) {
68+
char c = str.charAt(i);
69+
bytes[i/2] = (byte) ((c - 'a') << 4);
70+
c = str.charAt(i+1);
71+
bytes[i/2] += (c - 'a');
72+
}
73+
return bytes;
74+
}
75+
76+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.pig.impl.util;
20+
21+
import java.io.IOException;
22+
23+
/**
24+
* FIXME PIG-80 replace this code when pig will be java 6 compliant with "throw
25+
* new IOException(e);"
26+
*/
27+
public class WrappedIOException {
28+
29+
public static IOException wrap(final Throwable e) {
30+
return wrap(e.getMessage(), e);
31+
}
32+
33+
public static IOException wrap(final String message, final Throwable e) {
34+
final IOException wrappedException = new IOException(message + " [" +
35+
e.getMessage() + "]");
36+
wrappedException.setStackTrace(e.getStackTrace());
37+
wrappedException.initCause(e);
38+
return wrappedException;
39+
}
40+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/CanonicalNameConstants.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public final class CanonicalNameConstants {
2929
public static final String SET = Set.class.getCanonicalName();
3030
public static final String COLLECTIONS = Collections.class.getCanonicalName();
3131
public static final String STRING = String.class.getCanonicalName();
32+
public static final String STRING_SET = "java.util.Set<java.lang.String>";
3233
public static final String CHAR_SEQUENCE = CharSequence.class.getCanonicalName();
3334
public static final String SQL_EXCEPTION = SQLException.class.getCanonicalName();
3435
public static final String INTEGER = Integer.class.getCanonicalName();

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/ValidatorHelper.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public class ValidatorHelper {
8383

8484
private static final String METHOD_NAME_SET_ROOT_URL = "setRootUrl";
8585

86-
private static final List<String> VALID_PREF_RETURN_TYPES = Arrays.asList("int", "boolean", "float", "long", CanonicalNameConstants.STRING);
86+
private static final List<String> VALID_PREF_RETURN_TYPES = Arrays.asList("int", "boolean", "float", "long", CanonicalNameConstants.STRING, CanonicalNameConstants.STRING_SET);
8787

8888
private static final List<String> INVALID_PREF_METHOD_NAMES = Arrays.asList("edit", "getSharedPreferences", "clear", "getEditor", "apply");
8989

@@ -839,6 +839,7 @@ public boolean isPrefMethod(Element element) {
839839
} else {
840840

841841
String returnType = executableElement.getReturnType().toString();
842+
842843
if (!VALID_PREF_RETURN_TYPES.contains(returnType)) {
843844
annotationHelper.printError(element, "Method " + methodName + " should only return preference simple types in an " + annotationHelper.annotationName() + " annotated interface");
844845
} else {

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/SharedPrefProcessor.java‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@
5050
import org.androidannotations.api.sharedpreferences.SharedPreferencesHelper;
5151
import org.androidannotations.api.sharedpreferences.StringPrefEditorField;
5252
import org.androidannotations.api.sharedpreferences.StringPrefField;
53+
import org.androidannotations.api.sharedpreferences.StringSetPrefEditorField;
54+
import org.androidannotations.api.sharedpreferences.StringSetPrefField;
5355
import org.androidannotations.helper.ModelConstants;
56+
5457
import com.sun.codemodel.ClassType;
5558
import com.sun.codemodel.JBlock;
5659
import com.sun.codemodel.JClass;
@@ -82,6 +85,7 @@ public EditorFieldHolder(Class<?> fieldClass, String fieldMethodName) {
8285
put("int", new EditorFieldHolder(IntPrefEditorField.class, "intField"));
8386
put("long", new EditorFieldHolder(LongPrefEditorField.class, "longField"));
8487
put("java.lang.String", new EditorFieldHolder(StringPrefEditorField.class, "stringField"));
88+
put("java.util.Set<java.lang.String>", new EditorFieldHolder(StringSetPrefEditorField.class, "stringSetField"));
8589
}
8690
};
8791

@@ -234,11 +238,18 @@ public void process(Element element, JCodeModel codeModel, EBeansHolder eBeansHo
234238
defaultValue = JExpr.lit("");
235239
}
236240
addFieldHelperMethod(helperClass, fieldName, defaultValue, StringPrefField.class, "stringField");
241+
} else if ("java.util.Set<java.lang.String>".equals(returnType)) {
242+
addFieldHelperMethod(helperClass, fieldName, StringSetPrefField.class, "stringSetField");
237243
}
238244
}
239245

240246
}
241247

248+
private void addFieldHelperMethod(JDefinedClass helperClass, String fieldName, Class<?> prefFieldHelperClass, String fieldHelperMethodName) {
249+
JMethod fieldMethod = helperClass.method(JMod.PUBLIC, prefFieldHelperClass, fieldName);
250+
fieldMethod.body()._return(JExpr.invoke(fieldHelperMethodName).arg(fieldName));
251+
}
252+
242253
private void addFieldHelperMethod(JDefinedClass helperClass, String fieldName, JExpression defaultValue, Class<?> prefFieldHelperClass, String fieldHelperMethodName) {
243254
JMethod fieldMethod = helperClass.method(JMod.PUBLIC, prefFieldHelperClass, fieldName);
244255
fieldMethod.body()._return(JExpr.invoke(fieldHelperMethodName).arg(fieldName).arg(defaultValue));

‎AndroidAnnotations/functional-test-1-5-tests/src/test/java/org/androidannotations/test15/prefs/PrefsActivityTest.java‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
package org.androidannotations.test15.prefs;
1717

1818
import static org.fest.assertions.Assertions.assertThat;
19+
import static org.junit.Assert.fail;
20+
21+
import java.io.IOException;
22+
import java.io.Serializable;
23+
import java.util.HashSet;
24+
import java.util.Set;
25+
import java.util.TreeSet;
1926

2027
import org.junit.Before;
2128
import org.junit.Test;
@@ -24,6 +31,7 @@
2431
import android.content.SharedPreferences;
2532

2633
import org.androidannotations.test15.AndroidAnnotationsTestRunner;
34+
import org.apache.pig.impl.util.ObjectSerializer;
2735

2836
@RunWith(AndroidAnnotationsTestRunner.class)
2937
public class PrefsActivityTest {
@@ -70,6 +78,23 @@ public void putLong() {
7078
assertThat(sharedPref.getLong("lastUpdated", 0)).isEqualTo(now);
7179
}
7280

81+
@Test
82+
public void putStringSet() {
83+
Set<String> values = new TreeSet<String>();
84+
values.add("1");
85+
values.add("2");
86+
values.add("3");
87+
values.add("4");
88+
values.add("5");
89+
90+
somePrefs.types().put(values);
91+
try {
92+
assertThat(ObjectSerializer.deserialize(sharedPref.getString("types", null))).isEqualTo(values);
93+
} catch (IOException e) {
94+
fail("IO exception while deserializing the object");
95+
}
96+
}
97+
7398
@Test
7499
public void editLong() {
75100
long now = System.currentTimeMillis();
@@ -148,6 +173,30 @@ public void getLong() {
148173
assertThat(somePrefs.lastUpdated().get()).isEqualTo(now);
149174
}
150175

176+
@Test
177+
public void getStringSet() {
178+
Set<String> values = new TreeSet<String>();
179+
values.add("1");
180+
values.add("2");
181+
values.add("3");
182+
values.add("4");
183+
values.add("5");
184+
185+
try {
186+
sharedPref.edit()
187+
.putString("types", ObjectSerializer.serialize((Serializable) values))
188+
.commit();
189+
} catch (IOException e) {
190+
fail("Error while serializing string set: " + e.toString());
191+
}
192+
193+
Set<String> set = somePrefs.types().get();
194+
int i = 0;
195+
for(String v : set) {
196+
assertThat(v).isEqualTo(new Integer(++i).toString());
197+
}
198+
}
199+
151200
@Test
152201
public void defaultValue() {
153202
assertThat(somePrefs.name().get()).isEqualTo("John");

‎AndroidAnnotations/functional-test-1-5/src/main/java/org/androidannotations/test15/prefs/SomePrefs.java‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.androidannotations.test15.prefs;
1717

18+
import java.util.Set;
19+
1820
import org.androidannotations.annotations.sharedpreferences.DefaultInt;
1921
import org.androidannotations.annotations.sharedpreferences.DefaultString;
2022
import org.androidannotations.annotations.sharedpreferences.SharedPref;
@@ -31,4 +33,5 @@ public interface SomePrefs {
3133

3234
long lastUpdated();
3335

36+
Set<String> types();
3437
}

0 commit comments

Comments
 (0)