/**
* Copyright (C) 2011-2012 trivago GmbH <mario.mueller@trivago.com>, <christian.krause@trivago.com>
*
* 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 com.trivago.mail.pigeon.bean;
import com.trivago.mail.pigeon.storage.ConnectionFactory;
import org.apache.log4j.Logger;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.Transaction;
import org.svenson.JSONProperty;
/**
* Abstract Bean as parent for the other entity beans. Your new beans should
* inherit from this one.
*
* @author Mario Mueller mario.mueller@trivago.com
*/
public abstract class AbstractBean
{
/**
* The data node from neo4j
*/
protected Node dataNode;
protected static final Logger log = Logger.getLogger("com.trivago.mail.pigeon.bean");
/**
* The Node class is a wrapper from the neo4j libraries.
*
* @return returns the data node from neo4j
*/
@JSONProperty(ignore = true)
public Node getDataNode()
{
return dataNode;
}
/**
* Wrapper for writing properties directly to the node. Do not use this within another transaction as it will fail.
*
* @param key name of the property
* @param value value of the property. Should be of type String, a boxed scalar or at least serializable.
*/
protected void writeProperty(final String key, final Object value)
{
Transaction tx = ConnectionFactory.getDatabase().beginTx();
try
{
dataNode.setProperty(key, value);
tx.success();
}
catch (Exception e)
{
tx.failure();
}
finally
{
tx.finish();
}
}
/**
* Gets a property from the Node. You must give a type that the value should be cast to. You can use ignoreMissing
* if you expect the property to be missing (e.g. after you migrated the data model and added or removed a property
* from the beans).
*
* @param type type of value the property value should be cast to.
* @param key name of the property
* @param ignoreMissing in a normal case, neo4j throws an exception for every missing property. set this true to ignore it
* @param <T> The class the property value should be cast to.
* @return an object of class T or null
* @throws NotFoundException
*/
protected <T> T getProperty(Class<T> type, String key, boolean ignoreMissing)
{
try
{
return type.cast(getDataNode().getProperty(key));
}
catch (NotFoundException e)
{
if (ignoreMissing)
{
try
{
return type.getConstructor(String.class).newInstance("");
}
catch (Exception e1)
{
return null;
}
}
else
{
throw e;
}
}
}
/**
* Gets a property from the Node. You must give a type that the value should be cast to.
*
* This is a shortcut for getProperty(type, key, true).
*
* @see AbstractBean#getProperty(Class, String, boolean)
* @param type type of value the property value should be cast to.
* @param key name of the property
* @param <T> The class the property value should be cast to.
* @return an object of class T or null
* @throws NotFoundException
*/
protected <T> T getProperty(Class<T> type, String key)
{
return getProperty(type, key, true);
}
/**
* This is a helper method for wrapped properties. The intended use case was a date, which was saved as a Long in the
* property and should be returned as Date. The property value must match a constructor of the wrapper class.
*
* <code>
* Date myDate = bean.getWrappedProperty(Date.class, Long.class, "date");
* </code>
*
* @param returnType The class that wraps the node's property value
* @param argumentType The class that the property is cast to and that must match to constructor of the returnType
* @param key The name of the property
* @param <T> The return type (e.g. Date)
* @param <W> The constructor type (e.g. Long)
* @return A constructed wrapper instance of T with the property value cast to W as constructor paramter of T
*/
protected <T, W> T getWrappedProperty(Class<T> returnType, Class<W> argumentType, String key)
{
try
{
W data = getProperty(argumentType, key);
try
{
return returnType.getConstructor(argumentType).newInstance(data);
}
catch (NullPointerException ex)
{
return null;
}
}
catch (Exception e)
{
return null;
}
}
}