/*
* Copyright (C) 2005-2012 BetaCONCEPT Limited
*
* This file is part of Astroboa.
*
* Astroboa is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Astroboa 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 Astroboa. If not, see <http://www.gnu.org/licenses/>.
*/
package org.betaconceptframework.astroboa.engine.jcr.query;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import org.apache.commons.lang.ArrayUtils;
import org.betaconceptframework.astroboa.api.model.exception.CmsException;
import org.betaconceptframework.astroboa.api.model.query.Order;
import org.betaconceptframework.astroboa.engine.jcr.util.JcrValueUtils;
import org.betaconceptframework.astroboa.model.impl.item.CmsBuiltInItem;
import org.betaconceptframework.astroboa.model.impl.item.JcrBuiltInItem;
import org.betaconceptframework.astroboa.util.PropertyPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Gregory Chomatas (gchomatas@betaconcept.com)
* @author Savvas Triantafyllou (striantafyllou@betaconcept.com)
*
*/
public class CmsScoreNode implements Comparable<CmsScoreNode>{
private final Logger logger = LoggerFactory.getLogger(CmsScoreNode.class);
private Node node;
private double score=0;
private Map<String ,Object> valuesToBeCompared = new HashMap<String, Object>();
private Map<String, Order> orderProperties = new LinkedHashMap<String, Order>();
public Node getJcrNode()
{
return node;
}
public CmsScoreNode(Node node, double score)
{
this.node = node;
try {
if (this.node != null)
{
while (!this.node.isNodeType(CmsBuiltInItem.StructuredContentObject.getJcrName()))
{
this.node = this.node.getParent();
}
}
} catch (Exception e) {
throw new CmsException(e);
}
this.score = score;
}
public void setOrderProperties(Map<String, Order> orderProperties)
{
if (orderProperties != null && ! orderProperties.isEmpty())
{
this.orderProperties.putAll(orderProperties);
}
}
public double getScore()
{
return score;
}
public Comparable getValueFromMap(String property) throws RepositoryException
{
if (! valuesToBeCompared.containsKey(property)){
if (JcrBuiltInItem.JcrScore.getJcrName().equals(property))
{
//Check JcrScore returned in rows
valuesToBeCompared.put(property, score);
}
else
{
if (node != null){
Object valueForProperty = getValueForProperty(node, property);
//It could be null
valuesToBeCompared.put(property, valueForProperty);
}
}
}
return (Comparable) valuesToBeCompared.get(property);
}
public int compareTo(CmsScoreNode rowToBeCompared) {
try{
if (rowToBeCompared == null)
{
return 1;
}
else if (node == null)
{
return -1;
}
else
{
if (logger.isDebugEnabled()){
logger.debug("\n\nComparing nodes : {} and {}", node.getPath(), rowToBeCompared.getJcrNode().getPath());
}
for (Entry<String, Order> orderBy : orderProperties.entrySet())
{
String property = orderBy.getKey();
Order order = orderBy.getValue();
logger.debug("Comparing property {} with order {}", property, order);
int orderWeight = 1;
if (order == Order.descending)
orderWeight = -1;
//find appropriate values
Comparable thisValue = getValueFromMap(property);
Comparable valueToBeCompared = rowToBeCompared.getValueFromMap(property);
int valueCompare = compareValues(thisValue, valueToBeCompared);
logger.debug("Value for property of first node {}, Value for property of second node {}, Comparison outcome {}",
new Object[]{thisValue, valueToBeCompared, valueCompare});
if (valueCompare != 0){
logger.debug("Exiting loop.");
return valueCompare * orderWeight;
}
}
//All order properties are equal
return 0;
}
}
catch(Exception e)
{
logger.warn("",e);
return -1;
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((node == null) ? 0 : node.hashCode());
result = prime * result
+ ((orderProperties == null) ? 0 : orderProperties.hashCode());
long temp;
temp = Double.doubleToLongBits(score);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime
* result
+ ((valuesToBeCompared == null) ? 0 : valuesToBeCompared
.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CmsScoreNode other = (CmsScoreNode) obj;
if (node == null) {
if (other.node != null)
return false;
} else if (!node.equals(other.node))
return false;
if (orderProperties == null) {
if (other.orderProperties != null)
return false;
} else if (!orderProperties.equals(other.orderProperties))
return false;
if (Double.doubleToLongBits(score) != Double
.doubleToLongBits(other.score))
return false;
if (valuesToBeCompared == null) {
if (other.valuesToBeCompared != null)
return false;
} else if (!valuesToBeCompared.equals(other.valuesToBeCompared))
return false;
return true;
}
private Object getValueForProperty(Node node, String property) throws RepositoryException {
String propertyPath = PropertyPath.getJcrPropertyPath(property);
if (node.hasProperty(propertyPath)){
Property jcrProperty = node.getProperty(propertyPath);
if (!jcrProperty.getDefinition().isMultiple()){
Value value = node.getProperty(propertyPath).getValue();
return JcrValueUtils.getObjectValue(value);
}
else{
Value[] values = node.getProperty(propertyPath).getValues();
if (ArrayUtils.isEmpty(values)){
return null;
}
else{
// Get the last value to compare with
return JcrValueUtils.getObjectValue(values[values.length-1]);
}
}
}
else{
if (logger.isDebugEnabled()){
logger.debug("Node {} does not have property {}", node.getPath(), propertyPath );
}
}
return null;
}
private int compareValues(Comparable value1, Comparable value2) throws RepositoryException {
if (value1 == null){
return (value2 == null ? 0: -1);
}
else{
return (value2 != null ? value1.compareTo(value2): 1);
}
}
}