Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright 2015 Martin Bella
*
* 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 net.orange_box.storebox.harness.advanced;

import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.SmallTest;

import net.orange_box.storebox.StoreBox;
import net.orange_box.storebox.harness.interfaces.advanced.FormattedKeysInterface;

public class FormattedKeysTestCase extends InstrumentationTestCase {

private FormattedKeysInterface uut;
private SharedPreferences prefs;

@Override
protected void setUp() throws Exception {
super.setUp();

uut = StoreBox.create(
getInstrumentation().getTargetContext(), FormattedKeysInterface.class);

prefs = PreferenceManager.getDefaultSharedPreferences(
getInstrumentation().getTargetContext());
}

@SuppressLint("CommitPrefEdits")
@Override
protected void tearDown() throws Exception {
uut = null;

// we are saving to the actual preferences so let's clear them
prefs.edit().clear().commit();
prefs = null;

super.tearDown();
}

@SmallTest
public void testInt() {
assertEquals(0, uut.getInt(0));
assertEquals(0, uut.getInt(1));

uut.setInt(0, 1);
uut.setInt(1, 2);

assertEquals(1, uut.getInt(0));
assertEquals(2, uut.getInt(1));
}

@SmallTest
public void testString() {
assertNull(uut.getString("index_0"));
assertNull(uut.getString("index_1"));

uut.setString("index_0", "value_1");
uut.setString("index_1", "value_2");

assertEquals("value_1", uut.getString("index_0"));
assertEquals("value_2", uut.getString("index_1"));
}

@SmallTest
public void testStringByComplexKey() {
assertNull(uut.getStringByComplexKey("prefix_0", 0));
assertNull(uut.getStringByComplexKey("prefix_0", 1));
assertNull(uut.getStringByComplexKey("prefix_1", 0));
assertNull(uut.getStringByComplexKey("prefix_1", 1));

assertEquals("string", uut.getStringByComplexKey("prefix_0", 0, "string"));
assertEquals("string", uut.getStringByComplexKey("prefix_0", 1, "string"));
assertEquals("string", uut.getStringByComplexKey("prefix_1", 0, "string"));
assertEquals("string", uut.getStringByComplexKey("prefix_1", 1, "string"));

uut.setStringByComplexKey("prefix_0", 0, "value_1");
uut.setStringByComplexKey("prefix_0", 1, "value_2");
uut.setStringByComplexKey("prefix_1", 0, "value_3");
uut.setStringByComplexKey("prefix_1", 1, "value_4");

assertEquals("value_1", uut.getStringByComplexKey("prefix_0", 0));
assertEquals("value_2", uut.getStringByComplexKey("prefix_0", 1));
assertEquals("value_3", uut.getStringByComplexKey("prefix_1", 0));
assertEquals("value_4", uut.getStringByComplexKey("prefix_1", 1));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2015 Martin Bella
*
* 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 net.orange_box.storebox.harness.interfaces.advanced;

import net.orange_box.storebox.annotations.method.KeyByFormattedString;

public interface FormattedKeysInterface {

@KeyByFormattedString("int_%d_key")
int getInt(int index);

@KeyByFormattedString("int_%d_key")
void setInt(int index, int value);

@KeyByFormattedString("string_%s_key")
String getString(String index);

@KeyByFormattedString("string_%s_key")
void setString(String index, String value);

@KeyByFormattedString("%s_string_%d")
String getStringByComplexKey(String prefix, int index);

@KeyByFormattedString("%s_string_%d")
String getStringByComplexKey(String prefix, int index, String defaultValue);

@KeyByFormattedString("%s_string_%d")
void setStringByComplexKey(String prefix, int index, String value);

}
17 changes: 9 additions & 8 deletions storebox-lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ apply plugin: 'com.jfrog.bintray'
android {
compileSdkVersion project.compileSdkVersion
buildToolsVersion project.buildToolsVersion

defaultConfig {
minSdkVersion project.minSdkVersion
targetSdkVersion project.targetSdkVersion

versionName project.versionName
}

buildTypes {
debug {
testCoverageEnabled true
Expand All @@ -24,6 +24,7 @@ android {
dependencies {
compile 'com.android.support:support-annotations:23.3.0'
compile 'net.jodah:typetools:0.4.6'
compile 'org.apache.commons:commons-lang3:3.5'
}

// FindBugs
Expand Down Expand Up @@ -71,7 +72,7 @@ install {
pom {
project {
packaging 'jar'

name 'StroreBox Android Library'
description 'Android library for streamlining SharedPreferences.'
url 'http://martino2k6.github.io/StoreBox'
Expand Down Expand Up @@ -127,24 +128,24 @@ bintray {

configurations = ['archives']
publish = true

pkg {
repo = 'maven'
name = 'storebox'
desc = 'Android library for streamlining SharedPreferences.'

websiteUrl = 'http://martino2k6.github.io/StoreBox'
issueTrackerUrl = 'https://github.com/martino2k6/StoreBox/issues'
vcsUrl = 'https://github.com/martino2k6/StoreBox.git'

licenses = ['Apache-2.0']
labels = ['android', 'preferences', 'library', 'jar']
publicDownloadNumbers = true

version {
name = project.versionName
vcsTag = project.versionName

gpg {
sign = true
passphrase = properties.getProperty('bintray.gpg.password')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import net.orange_box.storebox.annotations.method.DefaultValue;
import net.orange_box.storebox.annotations.method.KeyByResource;
import net.orange_box.storebox.annotations.method.KeyByString;
import net.orange_box.storebox.annotations.method.KeyByFormattedString;
import net.orange_box.storebox.annotations.method.RemoveMethod;
import net.orange_box.storebox.annotations.method.TypeAdapter;
import net.orange_box.storebox.annotations.method.RegisterChangeListenerMethod;
Expand All @@ -43,6 +44,8 @@
import net.orange_box.storebox.utils.PreferenceUtils;
import net.orange_box.storebox.utils.TypeUtils;

import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
Expand All @@ -65,7 +68,7 @@ class StoreBoxInvocationHandler implements InvocationHandler {
private final SharedPreferences prefs;
private final SharedPreferences.Editor editor;
private final Resources res;

private final SaveMode saveMode;

private final MethodHandler mChangesHandler;
Expand All @@ -84,20 +87,20 @@ public StoreBoxInvocationHandler(
prefs = ((Activity) context).getPreferences(
preferencesMode.value());
break;

case FILE:
prefs = context.getSharedPreferences(
openNameValue, preferencesMode.value());
break;

case DEFAULT_SHARED:
default:
prefs = PreferenceManager.getDefaultSharedPreferences(context);
}

editor = prefs.edit();
res = context.getResources();

this.saveMode = saveMode;

mChangesHandler = new ChangeListenerMethodHandler(prefs);
Expand All @@ -113,12 +116,25 @@ public Object invoke(
* the SharedPreferences or Editor implementations.
*/
final String key;
final int numberOfFormattedKeyArgs;
final boolean isRemove;
final boolean isClear;
final boolean isChange;
if (method.isAnnotationPresent(KeyByString.class)) {
key = method.getAnnotation(KeyByString.class).value();


numberOfFormattedKeyArgs = 0;
isRemove = method.isAnnotationPresent(RemoveMethod.class);
isClear = false;
isChange = MethodUtils.areAnyAnnotationsPresent(
method,
RegisterChangeListenerMethod.class,
UnregisterChangeListenerMethod.class);
} else if (method.isAnnotationPresent(KeyByFormattedString.class)) {
String keyFormat = method.getAnnotation(KeyByFormattedString.class).value();
numberOfFormattedKeyArgs = StringUtils.countMatches(keyFormat, "%");
key = String.format(keyFormat, args);

isRemove = method.isAnnotationPresent(RemoveMethod.class);
isClear = false;
isChange = MethodUtils.areAnyAnnotationsPresent(
Expand All @@ -128,7 +144,8 @@ public Object invoke(
} else if (method.isAnnotationPresent(KeyByResource.class)) {
key = res.getString(
method.getAnnotation(KeyByResource.class).value());


numberOfFormattedKeyArgs = 0;
isRemove = method.isAnnotationPresent(RemoveMethod.class);
isClear = false;
isChange = MethodUtils.areAnyAnnotationsPresent(
Expand All @@ -137,13 +154,15 @@ public Object invoke(
UnregisterChangeListenerMethod.class);
} else if (method.isAnnotationPresent(RemoveMethod.class)) {
key = MethodUtils.getKeyForRemove(res, args);


numberOfFormattedKeyArgs = 0;
isRemove = true;
isClear = false;
isChange = false;
} else if (method.isAnnotationPresent(ClearMethod.class)) {
key = null;


numberOfFormattedKeyArgs = 0;
isRemove = false;
isClear = true;
isChange = false;
Expand All @@ -167,13 +186,13 @@ public Object invoke(
} catch (NoSuchMethodException e) {
// NOP
}

// can we forward the method to the Editor?
try {
final Method editorMethod = editor.getClass().getDeclaredMethod(
method.getName(),
method.getParameterTypes());

return editorMethod.invoke(editor, args);
} catch (NoSuchMethodException e) {
// NOP
Expand All @@ -188,7 +207,7 @@ public Object invoke(
KeyByString.class.getSimpleName(),
KeyByResource.class.getSimpleName()));
}

/*
* Find out based on the method return type whether it's a get or set
* operation. We could provide a further annotation for get/set methods,
Expand Down Expand Up @@ -234,6 +253,7 @@ public Object invoke(

final Object defValue = getDefaultValueArg(
method,
numberOfFormattedKeyArgs,
args);

final Object value = PreferenceUtils.getValue(
Expand Down Expand Up @@ -292,22 +312,23 @@ private int internalHashCode() {

private Object getDefaultValueArg(
Method method,
int numberOfFormattedKeyArgs,
Object... args) {

Object result = null;
final Class<?> type = TypeUtils.wrapToBoxedType(method.getReturnType());

// parameter default > method-level default
if (args != null && args.length > 0) {
result = args[0];
if (args != null && args.length > numberOfFormattedKeyArgs) {
result = args[args.length-1];
}
if (result == null && method.isAnnotationPresent(DefaultValue.class)) {
final TypedValue value = new TypedValue();
res.getValue(
method.getAnnotation(DefaultValue.class).value(),
value,
true);

if (type == Boolean.class) {
result = value.data != 0;
} else if (type == Float.class) {
Expand Down
Loading