rs.data.file.storage.AbstractStorageStrategy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of data-file Show documentation
Show all versions of data-file Show documentation
Library for file-based data access
The newest version!
/*
* This file is part of RS Library (Data File Library).
*
* RS Library is free software: you can redistribute it
* and/or modify it under the terms of version 3 of the GNU
* Lesser General Public License as published by the Free Software
* Foundation.
*
* RS Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with RS Library. If not, see
* .
*/
package rs.data.file.storage;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.CollectionUtils;
import rs.baselib.bean.BeanSupport;
import rs.baselib.lang.LangUtils;
import rs.data.api.IDaoFactory;
import rs.data.api.bo.IGeneralBO;
/**
* Abstract implementation of a storage stratey.
* @param type of ID for Business Objects to be managed
* @param type of Business Object the strategy manages
* @param type of specifier, e.g. a file
* @author ralph
*
*/
public abstract class AbstractStorageStrategy, S> implements IStorageStrategy {
/** ICache of transient properties per class */
private static Map, Set> transientCache = new HashMap, Set>();
/** The encoding used */
private String encoding = Charset.defaultCharset().name();
/** A factory reference */
private IDaoFactory daoFactory;
/**
* Constructor.
* @param daoFactory - the responsible DAO factory
*/
public AbstractStorageStrategy(IDaoFactory daoFactory) {
setDaoFactory(daoFactory);
}
/**
* Returns the daoFactory.
* @return the daoFactory
*/
public IDaoFactory getDaoFactory() {
return daoFactory;
}
/**
* Sets the daoFactory.
* @param daoFactory the daoFactory to set
*/
public void setDaoFactory(IDaoFactory daoFactory) {
this.daoFactory = daoFactory;
}
/**
* {@inheritDoc}
* The default implementation returns the number of specifiers.
*/
@Override
public int getObjectCount(Collection specifiers) throws IOException {
return specifiers.size();
}
/**
* {@inheritDoc}
* The default implementation forwards to {@link #getObjectCount(Collection)}.
*/
@Override
public int getDefaultObjectCount(Collection specifiers) throws IOException {
return getObjectCount(specifiers);
}
/**
* {@inheritDoc}
* The default implementation forwards to {@link #getList(Collection)}.
*/
@Override
public Map getDefaultList(Collection specifiers) throws IOException {
return getList(specifiers);
}
/**
* Serializes the given value.
* Collections, Maps and other non-serializable objects cannot be serialized by this method.
* @param value value to be serialized
* @return the serialized string or null if it cannot be serialized safely. Values encoded in BASE64 are
* prefixed with "BASE64"
.
* @throws IOException - the I/O exception when operating on a filesystem
*/
protected String serialize(Object value) throws IOException {
if (value instanceof Number) {
return value.toString();
} else if (value instanceof Boolean) {
return value.toString();
} else if (value instanceof Enum) {
return value.toString();
} else if (value instanceof String) {
// encode only when out of sight characters
boolean isClean = true;
for (char c : ((String) value).toCharArray()) {
if (c > '\u007f') {
isClean = false;
break;
}
}
if (isClean) {
return value.toString();
}
return "BASE64:"+new String(Base64.encodeBase64(((String) value).getBytes(getEncoding())), StandardCharsets.UTF_8);
} else if (value instanceof Serializable) {
return "BASE64:"+LangUtils.serializeBase64(value);
}
return null;
}
/**
* Unserializes the given value.
* Collections, Maps and other non-serializable objects cannot be unserialized by this method.
* @param className the expected class to be produced
* @param value the serialized string. Values encoded in BASE64 must be prefixed with "BASE64"
.
* @return the object (or null)
* @throws IOException - the I/O exception when operating on a filesystem
* @throws ClassNotFoundException - when class could not be found
* @throws InstantiationException - when object cannot be instantiated
* @throws IllegalAccessException - when constructor is not accessible
* @throws InvocationTargetException - when constructor threw an exception
* @throws NoSuchMethodException - when constructor does not exist
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
protected Object unserialize(String className, String value) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Class> clazz = LangUtils.forName(className);
if (Number.class.isAssignableFrom(clazz)) {
return (Number)clazz.getConstructor(String.class).newInstance(value);
} else if (Boolean.class.isAssignableFrom(clazz) ) {
return Boolean.valueOf(value);
} else if (clazz.isEnum()) {
return Enum.valueOf((Class)clazz, value);
} else if (String.class.isAssignableFrom(clazz)) {
if (value.startsWith("BASE64:")) return Base64.decodeBase64(value.substring(7));
return value;
} else if (Serializable.class.isAssignableFrom(clazz)) {
return LangUtils.unserialize(value);
}
return null;
}
/**
* Returns all properties as defined in the BO interface.
* @param object the object
* @return the names of all relevant interfaces
*/
@SuppressWarnings("unchecked")
protected Collection getPropertyNames(Object object) {
Set rc = transientCache.get(object.getClass());
if (rc == null) {
Set transients = new HashSet();
Set nontransients = new HashSet();
// Collect all transient and persistent properties from interfaces
for (Class> clazz2 : object.getClass().getInterfaces()) {
transients.addAll(BeanSupport.INSTANCE.getTransientProperties(clazz2));
nontransients.addAll(BeanSupport.INSTANCE.getNonTransientProperties(clazz2));
}
// Make difference of both sets
;
// Add all others to the return
rc = new HashSet(CollectionUtils.subtract(nontransients, transients));
transientCache.put(object.getClass(), Collections.unmodifiableSet(rc));
}
return rc;
}
/**
* Returns all properties as defined in the BO interface.
* @param object the object
* @return the names of all relevant interfaces
*/
protected Collection getBeanPropertyNames(Object object) {
return BeanSupport.INSTANCE.getNonTransientProperties(object);
}
/**
* Returns the {@link #encoding}.
* @return the encoding
*/
public String getEncoding() {
return encoding;
}
/**
* Sets the {@link #encoding}.
* @param encoding the encoding to set
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy