/*
* #%L
* FlatPack serialization code
* %%
* Copyright (C) 2012 Perka 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.
* #L%
*/
package com.getperka.flatpack;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Type;
import java.security.Principal;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Provider;
import org.junit.After;
import org.junit.Before;
import com.getperka.flatpack.domain.Employee;
import com.getperka.flatpack.domain.Manager;
import com.getperka.flatpack.domain.PersistentEmployee;
import com.getperka.flatpack.ext.Codex;
import com.getperka.flatpack.ext.DeserializationContext;
import com.getperka.flatpack.ext.SerializationContext;
import com.getperka.flatpack.inject.FlatPackTestModule;
import com.getperka.flatpack.inject.PackScope;
import com.getperka.flatpack.visitors.PackScanner;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonWriter;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* A base test type for constructing a FlatPack stack.
*/
public abstract class FlatPackTest {
private int counter;
@Inject
private Provider<DeserializationContext> deserializationContexts;
@Inject
private Provider<Employee> employees;
@Inject
private Provider<Manager> managers;
@Inject
private Injector injector;
@Inject
protected FlatPack flatpack;
@Inject
private PackScope packScope;
@Inject
private Provider<PersistentEmployee> persistentEmployees;
@Inject
private Provider<SerializationContext> serializationContexts;
@Inject
private Provider<PackScanner> packScanners;
@Inject
private Visitors visitors;
@After
public void after() {
packScope.exit();
}
@Before
public void before() {
Guice.createInjector(new FlatPackTestModule(getConfiguration())).injectMembers(this);
}
protected void check(Employee expected, Employee actual) {
assertNotSame(expected, actual);
assertEquals(expected, actual);
assertEquals(expected.getAddress().getStreet(), actual.getAddress().getStreet());
assertEquals(expected.getEmployeeNumber(), actual.getEmployeeNumber());
assertEquals(expected.getName(), actual.getName());
}
protected void closeContext() {
packScope.exit();
}
protected <T> T deepPack(Type type, T value) throws IOException {
return deepPack(type, value, null);
}
protected <T> T deepPack(Type type, T value, Principal principal) throws IOException {
@SuppressWarnings("unchecked")
FlatPackEntity<T> entity = (FlatPackEntity<T>) FlatPackEntity.create(type, value, principal)
.withTraversalMode(TraversalMode.DEEP);
StringWriter out = new StringWriter();
flatpack.getPacker().pack(entity, out);
System.out.println(out.toString());
FlatPackEntity<T> entity2 = flatpack.getUnpacker().unpack(
type, new StringReader(out.toString()), principal);
return entity2.getValue();
}
/**
* Must be paired with a call to {@link #closeContext()}.
*/
protected DeserializationContext deserializationContext() {
packScope.enter();
return deserializationContexts.get();
}
protected Configuration getConfiguration() {
return new Configuration().withPrettyPrint(true).withVerbose(true);
}
protected Employee makeEmployee() {
Employee toReturn = employees.get();
toReturn.setEmployeeNumber(++counter);
toReturn.setName("Employee Name");
toReturn.getAddress().setStreet("street");
return toReturn;
}
protected Manager makeManager() {
Manager toReturn = managers.get();
toReturn.setName("Manager Name");
toReturn.getAddress().setStreet("manager street");
return toReturn;
}
protected PersistentEmployee makePersistentEmployee() {
PersistentEmployee toReturn = persistentEmployees.get();
toReturn.setEmployeeNumber(++counter);
toReturn.setName("Employee Name");
toReturn.getAddress().setStreet("street");
return toReturn;
}
/**
* Must be paired with a call to {@link #closeContext()}.
*/
protected SerializationContext serializationContext(FlatPackEntity<?> entity, Writer out) {
JsonWriter json = new JsonWriter(out);
json.setLenient(true);
json.setIndent(" ");
json.setSerializeNulls(false);
packScope.enter().withEntity(entity).withJsonWriter(json);
return serializationContexts.get();
}
protected SerializationContext serializationContext(Writer out) {
return serializationContext(FlatPackEntity.nullResponse(), out);
}
protected <T> T testCodex(Provider<? extends Codex<T>> codexes, T value, Set<HasUuid> scanned) {
// Just smoke-test the description
assertNotNull(codexes.get().describe());
StringWriter out = new StringWriter();
SerializationContext serialization = serializationContext(out);
try {
Codex<T> codex = codexes.get();
codexes.get().write(value, serialization);
if (scanned != null) {
visitors.getWalkers().walkImmutable(codex).accept(packScanners.get(), value);
scanned.addAll(serialization.getEntities());
}
} finally {
closeContext();
}
DeserializationContext deserialization = deserializationContext();
try {
JsonElement element = new JsonParser().parse(out.toString());
return codexes.get().read(element, deserialization);
} finally {
closeContext();
}
}
/**
* Performs an encode/decode operation.
*/
protected <T> T testCodex(TypeLiteral<? extends Codex<T>> codexType, T value) {
return testCodex(codexType, value, null);
}
/**
* Performs an encode/decode operation, accumulating any scanned entities.
*/
protected <T> T testCodex(TypeLiteral<? extends Codex<T>> codexType, T value, Set<HasUuid> scanned) {
Provider<? extends Codex<T>> codexes = injector.getProvider(Key.get(codexType));
return testCodex(codexes, value, scanned);
}
}