
net.sourceforge.stripes.action.ObjectOutputBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of stripes Show documentation
Show all versions of stripes Show documentation
Stripes web framework jar, including tag library.
/*
* Copyright 2015 Stripes Framework.
*
* 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.sourceforge.stripes.action;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import net.sourceforge.stripes.util.Log;
/**
* This abstract class should be implemented by "builders" which take Java
* objects and convert them into a specific format (such as JavaScript, XML, or
* JSON). Originally created by using the JavaScript builder which contains
* functionality for property and class exclusion.
*
* @author Rick Grashel
* @param Subclass of this object
*/
public abstract class ObjectOutputBuilder< T extends ObjectOutputBuilder> {
/**
* Log instance used to log messages.
*/
private static final Log log = Log.getInstance(ObjectOutputBuilder.class);
/**
* Holds the set of classes representing the primitive types in Java.
*/
static final Set> simpleTypes = new HashSet>();
/**
* Holds the set of types that will be skipped over by default.
*/
static final Set> ignoredTypes = new HashSet>();
static {
simpleTypes.add(Byte.TYPE);
simpleTypes.add(Short.TYPE);
simpleTypes.add(Integer.TYPE);
simpleTypes.add(Long.TYPE);
simpleTypes.add(Float.TYPE);
simpleTypes.add(Double.TYPE);
simpleTypes.add(Boolean.TYPE);
simpleTypes.add(Character.TYPE);
ignoredTypes.add(Class.class);
}
/**
* Holds the root object which is to be converted to an output format.
*/
private final Object rootObject;
/**
* Holds the (potentially empty) set of user classes that should be skipped
* over.
*/
private final Set> excludeClasses;
/**
* Holds the (potentially empty) set of properties that should be skipped
* over.
*/
private final Set excludeProperties;
/**
* Holds an optional user-supplied name for the root property.
*/
private String rootVariableName = null;
/**
* Constructs a new ObjectOutputBuilder to build output for the root object
* supplied.
*
* @param root The root object from which to being translation into
* JavaScript
* @param objectsToExclude Zero or more Strings and/or Classes to be
* excluded from translation.
*/
public ObjectOutputBuilder(Object root, Object... objectsToExclude) {
this.rootObject = root;
this.excludeClasses = new HashSet>();
this.excludeProperties = new HashSet();
for (Object object : objectsToExclude) {
if (object instanceof Class>) {
addClassExclusion((Class>) object);
} else if (object instanceof String) {
addPropertyExclusion((String) object);
} else {
log.warn("Don't know to determine exclusion for objects of type ", object.getClass().getName(), ". You may only pass in instances of Class and/or String.");
}
}
this.excludeClasses.addAll(ignoredTypes);
}
/**
* Adds one or more properties to the list of property to exclude when
* translating to the formatted output.
*
* @param property one or more property names to be excluded
* @return the ObjectOutputBuilder instance to simplify method chaining
*/
public final T addPropertyExclusion(String... property) {
this.excludeProperties.addAll(Arrays.asList(property));
return (T) this;
}
/**
* Adds one or more properties to the list of properties to exclude when
* translating to JavaScript.
*
* @param clazz one or more classes to exclude
* @return the JavaScripBuilder instance to simplify method chaining
*/
public final T addClassExclusion(Class>... clazz) {
this.excludeClasses.addAll(Arrays.asList(clazz));
return (T) this;
}
/**
* Sets an optional user-supplied root variable name. If set this name will
* be used by the building when declaring the root variable to which the JS
* is assigned. If not provided then a randomly generated name will be used.
*
* @param rootVariableName the name to use when declaring the root variable
*/
public void setRootVariableName(final String rootVariableName) {
this.rootVariableName = rootVariableName;
}
/**
* Returns the name used to declare the root variable to which the built
* object is assigned.
*
* @return The root variable name for the object which is being converted
*/
public String getRootVariableName() {
return rootVariableName;
}
/**
* Causes the JavaScriptBuilder to navigate the properties of the supplied
* object and convert them to JavaScript.
*
* @return String a fragment of JavaScript that will define and return the
* JavaScript equivalent of the Java object supplied to the builder.
* @throws java.lang.Exception
*/
public String build() throws Exception {
Writer writer = new StringWriter();
build(writer);
return writer.toString();
}
/**
* Causes the ObjectOutputBuilder to navigate the properties of the supplied
* object and convert them to the desired format, writing them to the
* supplied writer as it goes.
*
* @param writer Instance of the writer that the converted object should be
* written to.
* @throws java.lang.Exception
*/
public abstract void build(Writer writer) throws Exception;
/**
* Returns true if the supplied type should be excluded from conversion,
* otherwise returns false. A class should be excluded if it is assignable
* to one of the types listed for exclusion, or, it is an array of such a
* type.
*
* @param type - Class to check to see if it is excluded for this builder.
* @return Whether or not the passed class is targeted for exclusion by the
* builder.
*/
public boolean isExcludedType(Class> type) {
for (Class> excludedType : this.excludeClasses) {
if (excludedType.isAssignableFrom(type)) {
return true;
} else if (type.isArray() && excludedType.isAssignableFrom(type.getComponentType())) {
return true;
}
}
return false;
}
/**
* Returns true if the object is of a type that can be converted to a simple
* scalar, and false otherwise.
*
* @param in Object to check to see if it is a scalar
* @return Whether or not the passed object is a scalar object.
*/
public boolean isScalarType(Object in) {
if (in == null) {
return true; // Though not strictly scalar, null can be treated as such
}
Class> type = in.getClass();
return simpleTypes.contains(type)
|| Number.class.isAssignableFrom(type)
|| String.class.isAssignableFrom(type)
|| Boolean.class.isAssignableFrom(type)
|| Character.class.isAssignableFrom(type)
|| Date.class.isAssignableFrom(type);
}
/**
* Returns the root object being built.
*
* @return Root object being built.
*/
public Object getRootObject() {
return this.rootObject;
}
/**
* Returns the properties that should be excluded from this
* object out.
*
* @return Set of excluded properties
*/
public Set getExcludedProperties() {
return this.excludeProperties;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy