Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RealmConfiguration + new constructors #929

Merged
merged 37 commits into from
Jun 4, 2015
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
5b29976
Added RealmConfiguration + Builder. Refactored Realm to use this inst…
cmelchior Mar 6, 2015
632e487
Removing test code
cmelchior Mar 6, 2015
a39ca18
Streamline new constructors and deprecate old constructors + other ut…
cmelchior Mar 16, 2015
3c70bab
Merge branch 'master' into cm-configuration-builder
cmelchior Mar 16, 2015
fdbe368
Added test cases for RealmConfiguration + minor refactoring.
cmelchior Mar 19, 2015
083fd7f
Merge branch 'master' into cm-configuration-builder
cmelchior Mar 22, 2015
6393086
Fixed unit tests. Renamed version to SchemaVersion
cmelchior Mar 22, 2015
1fa0ddb
Cleanup unit tests. Removed automatic version upgrade with no schema …
cmelchior Mar 22, 2015
1a4ec73
Merge branch 'master' into cm-configuration-builder
cmelchior May 5, 2015
7463741
Cleaned up naming. Removed deleteRealmBeforeOpening, should be replac…
cmelchior May 6, 2015
07dee9f
Removed option of deleting Realm on start
cmelchior May 6, 2015
ee52efa
Merge branch 'master' into cm-configuration-builder
cmelchior May 13, 2015
84170e2
RealmModule is now public
cmelchior May 13, 2015
589565d
Adding addModule and setModules. Removed schema from Realm and added …
cmelchior May 13, 2015
76db508
Added unit tests for addModule and setModules.
cmelchior May 13, 2015
8f451dd
Renamed deleteRealmBeforeOpening to resetRealmBeforeOpening.
cmelchior May 13, 2015
83294a3
Cleanup
cmelchior May 13, 2015
8590785
Removed deprecation of Realm.getInstance(context)
cmelchior May 13, 2015
73bd53c
Fixed unit tests.
cmelchior May 13, 2015
1195443
Cleanup
cmelchior May 13, 2015
2393dc0
Merge branch 'master' into cm-configuration-builder
cmelchior May 21, 2015
5f852e7
Language cleanup.
cmelchior May 21, 2015
e4c3dcb
Updated changelog.
cmelchior May 21, 2015
06b31f1
Fixed bug when specifying individual classes. Added unit tests.
cmelchior May 22, 2015
7f53426
Better log message
cmelchior May 26, 2015
dba2699
Comment about error scenario
cmelchior May 26, 2015
9d65088
Added APT unit tests for all variants of RealmModules.
cmelchior May 26, 2015
72e6c90
Now looks after the mediator class in the correct package.
cmelchior May 26, 2015
35d7fc5
Improved error message for objects not part of the schema.
cmelchior May 26, 2015
93475d5
Language cleanup.
cmelchior May 28, 2015
e4e3c7d
Proper var args.
cmelchior May 29, 2015
7e667fc
Merge branch 'master' into cm-configuration-builder
cmelchior Jun 1, 2015
9828737
Merge branch 'master' into cm-configuration-builder
cmelchior Jun 2, 2015
b454011
Cleanup test + language. Encryption key length is now a constant.
cmelchior Jun 2, 2015
8e1dd5b
Readdded AllTypesRealmProxy unit test.
cmelchior Jun 2, 2015
153a79e
Merge branch 'master' into cm-configuration-builder
cmelchior Jun 3, 2015
da2637b
Removed addModule and exposed Realm.getDefaultModule().
cmelchior Jun 3, 2015
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
6 changes: 6 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
0.81
* Introduced RealmModules for working with custom schemas in libraries and apps.
* Introduced Realm.getDefaultInstance(), Realm.setDefaultInstance(RealmConfiguration) and Realm.getInstance(RealmConfiguration).
* Deprecated most constructors. They have been been replaced by Realm.getInstance(RealmConfiguration) and Realm.getDefaultInstance().
* Deprecated Realm.migrateRealmAtPath(). It has been replaced by Realm.migrateRealm(RealmConfiguration).
* Deprecated Realm.deleteFile(). It has been replaced by Realm.deleteRealm(RealmConfiguration).
* Deprecated Realm.compactFile(). It has been replaced by Realm.compactRealm(RealmConfiguration).
* RealmList.add(), RealmList.addAt() and RealmList.set() now copy standalone objects transparently into Realm.
* Realm now works with Kotlin (M12+). (thanks @cypressious)
* Fix a performance regression introduced in 0.80.3 occurring during the validation of the Realm schema.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Modifier;
import javax.tools.JavaFileObject;

import io.realm.annotations.internal.RealmModule;
import io.realm.annotations.RealmModule;

/**
* This class is responsible for creating the DefaultRealmModule that contains all known
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,12 @@

package io.realm.processor;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import io.realm.annotations.RealmModule;

import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;

import io.realm.annotations.internal.RealmModule;
import javax.lang.model.element.*;
import java.util.*;

/**
* Utility class for holding metadata for the Realm modules.
Expand All @@ -39,7 +32,7 @@ public class ModuleMetaData {
private final RoundEnvironment env;
private Map<String, Set<ClassMetaData>> modules = new HashMap<String, Set<ClassMetaData>>();
private Map<String, Set<ClassMetaData>> libraryModules = new HashMap<String, Set<ClassMetaData>>();
private Map<String, ClassMetaData> classMetaData = new HashMap<String, ClassMetaData>();
private Map<String, ClassMetaData> classMetaData = new HashMap<String, ClassMetaData>(); // <FullyQualifiedClassName, ClassMetaData>
private boolean shouldCreateDefaultModule;

public ModuleMetaData(RoundEnvironment env, Set<ClassMetaData> availableClasses) {
Expand Down Expand Up @@ -69,8 +62,8 @@ public boolean generate(ProcessingEnvironment processingEnv) {

// Check that allClasses and classes are not set at the same time
RealmModule module = classElement.getAnnotation(RealmModule.class);
Utils.note("Processing " + classSimpleName);
if (module.allClasses() && module.classes().length > 0) {
Utils.note("Processing module " + classSimpleName);
if (module.allClasses() && hasCustomClassList(classElement)) {
Utils.error("Setting @RealmModule(allClasses=true) will override @RealmModule(classes={...}) in " + classSimpleName);
return false;
}
Expand All @@ -82,16 +75,12 @@ public boolean generate(ProcessingEnvironment processingEnv) {
classes = availableClasses;
} else {
classes = new HashSet<ClassMetaData>();
for (Class<?> clazz : module.classes()) {
if (!clazz.getSuperclass().toString().endsWith("RealmObject")) {
Utils.error(clazz.getSimpleName() + " is not extending RealmObject. Only RealmObjects can be " +
"part of a module.");
return false;
}
ClassMetaData metadata = classMetaData.get(clazz.getName());
Set<String> classNames = getClassMetaDataFromModule(classElement);
for (String fullyQualifiedClassName : classNames) {
ClassMetaData metadata = classMetaData.get(fullyQualifiedClassName);
if (metadata == null) {
Utils.error(Utils.stripPackage(qualifiedName) + " could not be added to the module. It is not " +
"possible to add classes which are part of another library.");
Utils.error(Utils.stripPackage(fullyQualifiedClassName) + " could not be added to the module. " +
"Only classes extending RealmObject, which are part of this project, can be added.");
return false;
}
classes.add(metadata);
Expand Down Expand Up @@ -122,6 +111,58 @@ public boolean generate(ProcessingEnvironment processingEnv) {
return true;
}

// Detour needed to access the class elements in the array
// See http://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/
private Set<String> getClassMetaDataFromModule(Element classElement) {
AnnotationMirror annotationMirror = getAnnotationMirror(classElement);
AnnotationValue annotationValue = getAnnotationValue(annotationMirror);
Set<String> classes = new HashSet<String>();
List<? extends AnnotationValue> moduleClasses = (List<? extends AnnotationValue>) annotationValue.getValue();
for (AnnotationValue classMirror : moduleClasses) {
String fullyQualifiedClassName = classMirror.getValue().toString();
classes.add(fullyQualifiedClassName);
}
return classes;
}

// Work around for asking for a Class primitive array which would otherwise throw a TypeMirrorException
// https://community.oracle.com/thread/1184190
private boolean hasCustomClassList(Element classElement) {
AnnotationMirror annotationMirror = getAnnotationMirror(classElement);
AnnotationValue annotationValue = getAnnotationValue(annotationMirror);
if (annotationValue == null) {
return false;
} else {
List<? extends AnnotationValue> moduleClasses = (List<? extends AnnotationValue>) annotationValue.getValue();
return moduleClasses.size() > 0;
}
}

private AnnotationMirror getAnnotationMirror(Element classElement) {
AnnotationMirror annotationMirror = null;
for (AnnotationMirror am : classElement.getAnnotationMirrors()) {
if (am.getAnnotationType().toString().equals(RealmModule.class.getCanonicalName())) {
annotationMirror = am;
break;
}
}
return annotationMirror;
}

private AnnotationValue getAnnotationValue(AnnotationMirror annotationMirror) {
if (annotationMirror == null) {
return null;
}
AnnotationValue annotationValue = null;
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) {
if (entry.getKey().getSimpleName().toString().equals("classes")) {
annotationValue = entry.getValue();
break;
}
}
return annotationValue;
}

/**
* Returns all module classes and the RealmObjects they know of.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import javax.lang.model.element.Modifier;
import javax.tools.JavaFileObject;

import io.realm.annotations.internal.RealmModule;
import io.realm.annotations.RealmModule;

public class RealmProxyMediatorGenerator {
private final String className;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@

import javax.tools.JavaFileObject;

import java.util.Arrays;

import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
import static org.truth0.Truth.ASSERT;

public class RealmProcessorTest {

private JavaFileObject simpleModel = JavaFileObjects.forResource("some/test/Simple.java");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should still check that we produce the expected model class proxy! This is a problem introduced in the Modules PR

private JavaFileObject simpleProxy = JavaFileObjects.forResource("io/realm/SimpleRealmProxy.java");
private JavaFileObject allTypesModel = JavaFileObjects.forResource("some/test/AllTypes.java");
private JavaFileObject allTypesProxy = JavaFileObjects.forResource("io/realm/AllTypesRealmProxy.java");
private JavaFileObject allTypesDefaultModule = JavaFileObjects.forResource("io/realm/RealmDefaultModule.java");
private JavaFileObject allTypesDefaultMediator = JavaFileObjects.forResource("io/realm/RealmDefaultModuleMediator.java");
private JavaFileObject booleansModel = JavaFileObjects.forResource("some/test/Booleans.java");
Expand Down Expand Up @@ -111,6 +113,70 @@ public void compareProcessedAllTypesFile() throws Exception {
.generatesSources(allTypesDefaultMediator, allTypesDefaultModule, allTypesDefaultMediator);
}

@Test
public void compileAppModuleCustomClasses() throws Exception {
ASSERT.about(javaSources())
.that(Arrays.asList(allTypesModel, JavaFileObjects.forResource("some/test/AppModuleCustomClasses.java")))
.processedWith(new RealmProcessor())
.compilesWithoutError();
}

@Test
public void compileAppModuleAllClasses() throws Exception {
ASSERT.about(javaSources())
.that(Arrays.asList(allTypesModel, JavaFileObjects.forResource("some/test/AppModuleAllClasses.java")))
.processedWith(new RealmProcessor())
.compilesWithoutError();
}

@Test
public void compileLibraryModulesAllClasses() throws Exception {
ASSERT.about(javaSources())
.that(Arrays.asList(allTypesModel, JavaFileObjects.forResource("some/test/LibraryModuleAllClasses.java")))
.processedWith(new RealmProcessor())
.compilesWithoutError();
}

@Test
public void compileLibraryModulesCustomClasses() throws Exception {
ASSERT.about(javaSources())
.that(Arrays.asList(allTypesModel, JavaFileObjects.forResource("some/test/LibraryModuleCustomClasses.java")))
.processedWith(new RealmProcessor())
.compilesWithoutError();
}

@Test
public void compileAppModuleMixedParametersFail() throws Exception {
ASSERT.about(javaSources())
.that(Arrays.asList(allTypesModel, JavaFileObjects.forResource("some/test/InvalidAppModuleMixedParameters.java")))
.processedWith(new RealmProcessor())
.failsToCompile();
}

@Test
public void compileAppModuleWrongTypeFail() throws Exception {
ASSERT.about(javaSources())
.that(Arrays.asList(allTypesModel, JavaFileObjects.forResource("some/test/InvalidAppModuleWrongType.java")))
.processedWith(new RealmProcessor())
.failsToCompile();
}

@Test
public void compileLibraryModuleMixedParametersFail() throws Exception {
ASSERT.about(javaSources())
.that(Arrays.asList(allTypesModel, JavaFileObjects.forResource("some/test/InvalidLibraryModuleMixedParameters.java")))
.processedWith(new RealmProcessor())
.failsToCompile();
}

@Test
public void compileLibraryModuleWrongTypeFail() throws Exception {
ASSERT.about(javaSources())
.that(Arrays.asList(allTypesModel, JavaFileObjects.forResource("some/test/InvalidLibraryModuleWrongType.java")))
.processedWith(new RealmProcessor())
.failsToCompile();
}

@Test
public void compileBooleanFile() {
ASSERT.about(javaSource())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.realm;


@io.realm.annotations.internal.RealmModule(allClasses = true)
@io.realm.annotations.RealmModule(allClasses = true)
class DefaultRealmModule {

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import org.json.JSONObject;
import some.test.AllTypes;

@io.realm.annotations.internal.RealmModule
@io.realm.annotations.RealmModule
class DefaultRealmModuleMediator extends RealmProxyMediator {

private static final List<Class<? extends RealmObject>> MODEL_CLASSES;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2015 Realm 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 some.test;

import java.util.Date;

import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.RealmModule;

@RealmModule(allClasses = true)
public class AppModuleAllClasses {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2015 Realm 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 some.test;

import java.util.Date;

import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.RealmModule;

@RealmModule(classes = { AllTypes.class })
public class AppModuleCustomClasses {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2015 Realm 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 some.test;

import java.util.Date;

import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.RealmModule;

// Setting both allClasses and classes is not allowed at the same time
@RealmModule(allClasses = true, classes = { AllTypes.class })
public class InvalidAllTypesModuleMixedParameters {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2015 Realm 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 some.test;

import java.util.Date;

import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.RealmModule;

// Object is not a RealmObject which the Annotation Processor should be able to detect.
@RealmModule(classes = { Object.class, AllTypes.class })
public class InvalidAllTypesModuleWrongType {

}
Loading