Skip to content
This repository was archived by the owner on Jan 31, 2019. It is now read-only.

Example generation of complete object graphs. #6

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*.jar
*.war
*.ear
.idea
.classpath
.project
.settings/**
Expand Down
38 changes: 33 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cloudifysource</groupId>
<artifactId>rest-doclet</artifactId>
<version>0.5.2</version>
<version>0.5.8</version>

<properties>
<springVersion>3.1.3.RELEASE</springVersion>
<springVersion>3.2.4.RELEASE</springVersion>
</properties>

<dependencies>
Expand All @@ -20,14 +20,25 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springVersion}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springVersion}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
Expand All @@ -49,7 +60,17 @@
<artifactId>jackson-core-asl</artifactId>
<version>1.9.9</version>
</dependency>
</dependencies>
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>default-profile</id>
Expand Down Expand Up @@ -108,4 +129,11 @@
</plugins>
<finalName>rest-doclet</finalName>
</build>
</project>
<distributionManagement>
<repository>
<id>aristaeus.mediagraft.com</id>
<name>aristaeus.mediagraft.com-releases</name>
<url>http://aristaeus.mediagraft.com:8080/libs-release-local</url>
</repository>
</distributionManagement>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,35 @@

import org.apache.commons.lang.ClassUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.springframework.web.multipart.MultipartFile;

import com.sun.javadoc.Type;

/**
* Creates a default example -
* creates a JSON format of an instantiated object of the given clazz.
* Creates a default example -
* creates a JSON format of an instantiated object of the given clazz.
* @author yael
* @since 0.5.0
*/
public class DocDefaultExampleGenerator implements
IDocExampleGenerator {

private ObjectCreator objectCreator_ = new ObjectCreator();

private String generateJSON(final Type type) throws Exception {
Class<?> clazz = ClassUtils.getClass(type.qualifiedTypeName());
if (MultipartFile.class.getName().equals(clazz.getName())) {
return "\"file content\"";
}
if (clazz.isInterface()) {
throw new InstantiationException(
"the given class is an interface [" + clazz.getName() + "].");
}
Object newInstance = null;
if (clazz.isPrimitive()) {
newInstance = PrimitiveExampleValues.getValue(clazz);
}
Class<?> classToInstantiate = clazz;
if (newInstance == null) {
newInstance = classToInstantiate.newInstance();
}
return new ObjectMapper().writeValueAsString(newInstance);

Object newInstance = objectCreator_.createObject(clazz);
return new ObjectMapper()
.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false)
.writeValueAsString(newInstance);
}

@Override
@Override
public String generateExample(final Type type) throws Exception {
return generateJSON(type);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
package org.cloudifysource.restDoclet.exampleGenerators;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import com.google.common.primitives.Primitives;
import static com.google.common.collect.Lists.newArrayList;

/**
* @author Ed Kimber
*/
public class ObjectCreator {

private Objenesis objenesis_;
private static final Logger logger_ = Logger.getLogger(ObjectCreator.class.getName());
private List<ExampleCreator> exampleCreators_;

public ObjectCreator() {
objenesis_ = new ObjenesisStd();
exampleCreators_ = newArrayList(primitiveCreator_, wrapperCreator_, stringCreator_, enumCreator_, dateCreator_, listCreator_);
}

public Object createObject(final Class<?> cls) throws IllegalAccessException {
if (isAbstractOrInterface(cls)) return createProxy(cls);

try {
Object object = objenesis_.newInstance(cls);
instantiateFieldsOn(object);
return object;
}
catch (IllegalAccessError illegal) {
logger_.warning("Could not instantiate an object of class: " + cls.getName());
return null;
}
}

public void instantiateFieldsOn(final Object object) throws IllegalAccessException {
Class<?> cls = object.getClass();
for (Field f : cls.getDeclaredFields()) {
if (f.getType().equals(cls)) {
continue; //avoid infinite recursion!
}
else {
tryToSetField(f, object);
}
}
}

private void tryToSetField(final Field field, final Object object) {
try {
field.setAccessible(true);
Class<?> fieldType = field.getType();

if (field.getGenericType() instanceof ParameterizedType) {
field.set(object, createParameterizedType(fieldType, (ParameterizedType) field.getGenericType()));
}
else {
field.set(object, createValueForType(fieldType));
}
}
catch (IllegalAccessException illegal) {
logger_.warning("Could not set field " + field.getName() + " on a " + object.getClass());
}
}

public Object createProxy(final Class cls) {
return Enhancer.create(cls, new MethodInterceptor() {
@Override
public Object intercept(final Object proxy, final Method method,
final Object[] args, final MethodProxy methodProxy)
throws Throwable
{
return createValueForType(method.getReturnType());
}
});
}

/**
* Only Lists with one simple generic param currently supported.
*/
private Object createParameterizedType(final Class base, final ParameterizedType genericType)
throws IllegalAccessException
{
Class type = (Class) genericType.getActualTypeArguments()[0];
if (List.class.isAssignableFrom(base)) {
return createListOfType(type);
}
else {
return createObject(base);
}
}

private Object createValueForType(final Class<?> cls) throws IllegalAccessException {
for (ExampleCreator creator : exampleCreators_) {
if (creator.match(cls)) {
return creator.create(cls);
}
}
return createObject(cls);
}

@SuppressWarnings("unchecked")
private List createListOfType(final Class type) throws IllegalAccessException {
LinkedList list = new LinkedList();
list.add(createValueForType(type));
list.add(createValueForType(type));
return list;
}

private boolean isAbstractOrInterface(final Class<?> cls) {
int modifiers = cls.getModifiers();
return Modifier.isInterface(modifiers) || Modifier.isAbstract(modifiers);
}

interface ExampleCreator {
boolean match(Class cls);
Object create(Class cls) throws IllegalAccessException;
}

private static ExampleCreator stringCreator_ = new ExampleCreator() {

@Override
public boolean match(Class cls) {
return String.class.isAssignableFrom(cls);
}

@Override
public Object create(final Class cls) {
return "foo";
}
};

private static ExampleCreator primitiveCreator_ = new ExampleCreator() {
@Override
public boolean match(final Class cls) {
return cls.isPrimitive();
}

@Override
public Object create(final Class cls) {
return PrimitiveExampleValues.getValue(cls);
}
};

private static ExampleCreator wrapperCreator_ = new ExampleCreator() {
@Override
public boolean match(final Class cls) {
return Primitives.isWrapperType(cls);
}

@Override
public Object create(final Class cls) throws IllegalAccessException {
return PrimitiveExampleValues.getValue(Primitives.unwrap(cls));
}
};

private static ExampleCreator enumCreator_ = new ExampleCreator() {
@Override
public boolean match(final Class cls) {
return cls.isEnum();
}

@Override
public Object create(final Class cls) {
return Enum.valueOf((Class<? extends Enum>) cls, cls.getEnumConstants()[0].toString());
}
};

private ExampleCreator listCreator_ = new ExampleCreator() {
@Override
public boolean match(final Class cls) {
return List.class.isAssignableFrom(cls);
}

@Override
public Object create(final Class cls) throws IllegalAccessException {
return createListOfType(Object.class);
}
};

private ExampleCreator dateCreator_ = new ExampleCreator() {
@Override
public boolean match(final Class cls) {
return Date.class.isAssignableFrom(cls);
}

@Override
public Object create(final Class cls) throws IllegalAccessException {
return new Date();
}
};
}
Loading