Skip to content

Commit

Permalink
Fixed ClassNotFoundException when removing classes from the class h…
Browse files Browse the repository at this point in the history
…ierarchy
  • Loading branch information
luontola committed Apr 15, 2013
1 parent dc4be38 commit dceacb6
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 21 deletions.
6 changes: 1 addition & 5 deletions .idea/ant.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Release Notes

### Upcoming Changes

- TBD
- Fixed `ClassNotFoundException` when removing classes from the class hierarchy

### JSON Migraine 1.0.0 (2012-11-02)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
// Copyright © 2012 Solita Oy <www.solita.fi>
// Copyright © 2012-2013 Solita Oy <www.solita.fi>
// This software is released under the MIT License.
// The license text is at http://opensource.org/licenses/MIT

package fi.solita.jsonmigraine.internal;

public class DataVersion {

public final Class<?> dataType;
public final String dataType;
public final int dataVersion;

public DataVersion(Class<?> dataType, int dataVersion) {
this(dataType.getName(), dataVersion);
}

public DataVersion(String dataType, int dataVersion) {
this.dataType = dataType;
this.dataVersion = dataVersion;
}
Expand Down
18 changes: 5 additions & 13 deletions src/main/java/fi/solita/jsonmigraine/internal/DataVersions.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2012 Solita Oy <www.solita.fi>
// Copyright © 2012-2013 Solita Oy <www.solita.fi>
// This software is released under the MIT License.
// The license text is at http://opensource.org/licenses/MIT

Expand All @@ -15,10 +15,10 @@ public class DataVersions {
public final List<DataVersion> versions = new ArrayList<DataVersion>();

public int getVersion(Class<?> dataType) {
return forDataType(dataType).dataVersion;
return forDataType(dataType.getName()).dataVersion;
}

private DataVersion forDataType(Class<?> dataType) {
private DataVersion forDataType(String dataType) {
for (DataVersion version : versions) {
if (version.dataType.equals(dataType)) {
return version;
Expand All @@ -35,7 +35,7 @@ public DataVersions add(DataVersion dataVersion) {
public JsonNode toJson() {
ObjectNode json = JsonNodeFactory.instance.objectNode();
for (DataVersion version : versions) {
json.put(version.dataType.getName(), version.dataVersion);
json.put(version.dataType, version.dataVersion);
}
return json;
}
Expand All @@ -44,19 +44,11 @@ public static DataVersions fromJson(JsonNode json, TypeRenames renames) {
DataVersions versions = new DataVersions();
for (String dataType : asIterable(json.getFieldNames())) {
int dataVersion = json.get(dataType).asInt();
versions.add(new DataVersion(toClass(renames.getLatestName(dataType)), dataVersion));
versions.add(new DataVersion(renames.getLatestName(dataType), dataVersion));
}
return versions;
}

private static Class<?> toClass(String fieldName) {
try {
return Class.forName(fieldName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}

private static <T> Iterable<T> asIterable(final Iterator<T> iterator) {
return new Iterable<T>() {
@Override
Expand Down
102 changes: 102 additions & 0 deletions src/test/java/fi/solita/jsonmigraine/RemovingClassesTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright © 2012-2013 Solita Oy <www.solita.fi>
// This software is released under the MIT License.
// The license text is at http://opensource.org/licenses/MIT

package fi.solita.jsonmigraine;

import fi.solita.jsonmigraine.api.*;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;
import org.junit.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

public class RemovingClassesTest {

private final TypeRenames renames = new TypeRenames();
private final JsonMigraine jsonMigraine = new JsonMigraine(new ObjectMapper(), renames);

{
renames.rename(ChildV1.class.getName(), ChildV2.class.getName());
renames.rename(ParentV1.class.getName(), ParentV1.class.getName().replace("V1", "V2")); // class removed in V2
}

@Test
public void can_remove_classes_from_the_class_hierarchy() throws Exception {
ChildV1 v1 = new ChildV1();
v1.unmodified = "foo";
v1.parentField = "bar";

ChildV2 v2 = upgrade(v1);

assertThat("should not change unrelated fields", v2.unmodified, is(v1.unmodified));
assertThat("should migrate values of relocated fields", v2.relocatedField, is(v1.parentField));
}

private ChildV2 upgrade(ChildV1 v1) throws Exception {
String serialized = jsonMigraine.serialize(v1);
return (ChildV2) jsonMigraine.deserialize(serialized);
}


@Upgradeable(ParentUpgraderV1.class)
static class ParentV1 {
public String parentField;
}


@Upgradeable(ChildUpgraderV1.class)
static class ChildV1 extends ParentV1 {
public String unmodified;
}

@Upgradeable(ChildUpgraderV2.class)
static class ChildV2 {
public String relocatedField;
public String unmodified;
}

static class ParentUpgraderV1 implements Upgrader {

@Override
public int version() {
return 1;
}

@Override
public JsonNode upgrade(JsonNode data, int version) {
return data;
}
}

static class ChildUpgraderV1 implements Upgrader {

@Override
public int version() {
return 1;
}

@Override
public JsonNode upgrade(JsonNode data, int version) {
return data;
}
}

static class ChildUpgraderV2 extends ObjectUpgrader {

@Override
public int version() {
return 2;
}

@Override
public ObjectNode upgrade(ObjectNode data, int version) {
if (version == 1) {
Refactor.renameField(data, "parentField", "relocatedField");
}
return data;
}
}
}

0 comments on commit dceacb6

Please sign in to comment.