/*******************************************************************************
* Copyright (c) 2006-2012
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Berlin, Germany
* - initial API and implementation
******************************************************************************/
package org.reuseware.sokan.index.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.reuseware.sokan.Constraint;
import org.reuseware.sokan.FacetedRequest;
import org.reuseware.sokan.FacetedResponse;
import org.reuseware.sokan.IndexRow;
import org.reuseware.sokan.SokanFactory;
import org.reuseware.sokan.index.SokanIndexPlugin;
/**
* Utility methods to perform facet-based querying on Sokan's index.
*/
public final class FacetUtil {
private FacetUtil() { }
/**
* Builds a list of constraints out of a specific constraint array. This
* array needs look like the following: <br>
* <br>
* schema:<br>
* <code>
* {fName,vName1,vName2,...},{fName,vName1,vName2,...},...<br>
* </code> <br>
* example:<br>
* <code>
* String[][] cons = {{"color","Brown","Blue"},{"size","Large"}};
* </code>
*
* @param constraintArray
* The array containing the constraint information.
* @return A list of constraints ready to be used to build a
* <code>FacetedRequest</code> object.
*/
public static List<Constraint> buildConstraints(String[][] constraintArray) {
List<Constraint> constraints = new LinkedList<Constraint>();
if (constraintArray == null) {
return constraints;
}
try {
List<String> valueList;
for (String[] constraint : constraintArray) {
valueList = new ArrayList<String>(constraint.length - 1);
for (int i = 1; i < constraint.length; i++) {
valueList.add(constraint[i]);
}
constraints.add(createConstraint(constraint[0], valueList));
}
} catch (Exception e) {
SokanIndexPlugin.logError(
"Error parsing the constraint array.", e);
}
return constraints;
}
/**
* Builds a list of constraints by the given name and the give single value.
*
* @param facetName
* The facet/column name to constrain on.
* @param value
* The single value.
* @return A list of constraints ready to be used to build a
* <code>FacetedRequest</code> object.
*/
public static List<Constraint> buildConstraints(String facetName,
String value) {
List<Constraint> cons = new LinkedList<Constraint>();
cons.add(createConstraint(facetName, value));
return cons;
}
/**
* Builds a list of constraints by the given facetName (aka. index column
* name) and an array of facet values.
*
* @param facetName
* The facet/column name to constrain on.
* @param valueArray
* An array of values.
* @return A list of constraints ready to be used to build a
* <code>FacetedRequest</code> object.
*/
public static List<Constraint> buildConstraints(String facetName,
String[] valueArray) {
if (valueArray == null) {
return new LinkedList<Constraint>();
}
List<String> valueList = new ArrayList<String>(valueArray.length);
for (String string : valueArray) {
valueList.add(string);
}
return buildConstraints(facetName, valueList);
}
/**
* Builds a list of constraints by the given facetName (aka. index column
* name) and an list of facet values.
*
* @param facetName
* The facet/column name to constrain on.
* @param valueList
* An list of values.
* @return A list of constraints ready to be used to build a
* <code>FacetedRequest</code> object.
*/
public static List<Constraint> buildConstraints(String facetName,
List<String> valueList) {
List<Constraint> constraints = new LinkedList<Constraint>();
if (facetName == null | valueList == null) {
return constraints;
}
Constraint con = createConstraint(facetName, valueList);
constraints.add(con);
return constraints;
}
/**
* Builds a list of constraints out of a specific constraint string. This
* string needs to have to following structure: <br>
* <br>
* fName=vName[,vName][;fName=vName[,vName]] <br>
* <br>
* e.g.:<br>
* color=Brown,Blue;numberType=Even;size=Big,Large
*
* @param constraintString
* A <code>String</code> that contains all facet names and
* values.
* @return A list of constraints ready to be used to build a
* <code>FacetedRequest</code> object.
*/
public static List<Constraint> buildConstraints(String constraintString) {
try {
// color=Brown,Golden;numberType=Even
String[] facetValuePairs = constraintString.split(";");
List<String> valueList;
List<Constraint> constraints = new LinkedList<Constraint>();
for (String facetValuePair : facetValuePairs) {
String[] parts = facetValuePair.split("=");
if (parts.length == 1) {
valueList = new ArrayList<String>(0);
} else {
String[] valueArray = parts[1].split(",");
valueList = new ArrayList<String>(valueArray.length);
for (String value : valueArray) {
valueList.add(value);
}
}
constraints.add(createConstraint(parts[0], valueList));
}
return constraints;
} catch (Exception e) {
SokanIndexPlugin.logError(
"Error parsing the constraintString.", e);
return Collections.emptyList();
}
}
/**
* Builds a simple {@link FacetedRequest} using the given constraints. The
* {@link FacetedResponse} to this request won't contain any value counts.
*
* @param constraints
* The faceted constrains filtering the result set.
* @return A new <code>FacetedRequest</code> instance.
*/
public static FacetedRequest buildFacetedRequest(
List<Constraint> constraints) {
if (constraints == null || constraints.size() == 0) {
return null;
}
FacetedRequest request = SokanFactory.eINSTANCE.createFacetedRequest();
request.getConstraints().addAll(constraints);
return request;
}
/**
* Builds a simple {@link FacetedRequest} using the facetName and
* valueArray. The {@link FacetedResponse} to this request won't contain any
* value counts.
*
* @see FacetUtil#buildConstraints(String, String[])
* @param facetName
* The facet/column name to constrain on.
* @param valueArray
* An array of values.
* @return A new <code>FacetedRequest</code> instance.
*/
public static FacetedRequest buildFacetedRequest(String facetName,
String[] valueArray) {
List<Constraint> constraints = buildConstraints(facetName, valueArray);
if (constraints == null || constraints.size() == 0) {
return null;
}
FacetedRequest request = SokanFactory.eINSTANCE.createFacetedRequest();
request.getConstraints().addAll(constraints);
return request;
}
/**
* Builds a {@link FacetedRequest} using the given information.
*
* @param constraints
* The faceted constrains filtering the result set.
* @param facetFields
* A list of field/column names value counts are needed for.
* @param keywordSearchString
* A search string to filter the result set. (Not supported yet.)
* @param rows
* The maximum number of index rows in the response.
* @param offset
* An offset needed to split the result set into pages.
*
* @see FacetedRequest#getRows()
* @see FacetedRequest#getOffset()
*
* @return A new <code>FacetedRequest</code> instance.
*/
public static FacetedRequest buildFacetedRequest(
List<Constraint> constraints, List<String> facetFields,
String keywordSearchString, int rows, int offset) {
if (constraints == null || constraints.size() == 0) {
return null;
}
FacetedRequest request = SokanFactory.eINSTANCE.createFacetedRequest();
request.getConstraints().addAll(constraints);
request.setFacetFields(adaptECollection(facetFields));
request.setKeywordSearchString(keywordSearchString);
request.setKeywordSearchString(keywordSearchString);
request.setRows(rows);
request.setOffset(offset);
return request;
}
/**
* Builds a {@link FacetedResponse} using the given information.
*
* @param request
* The {@link FacetedRequest} that leaded to this response.
* @param content
* The result set fulfilling the constraints.
* @param valueCounts
* The facet value's occurrence of the facets list in the
* request.
* @see FacetedRequest#setFacetFields(EList)
* @return A new <code>FacetedResponse</code> instance.
*/
public static FacetedResponse buildFacetedResponse(FacetedRequest request,
List<IndexRow> content, Map<String, Map<String, Long>> valueCounts) {
FacetedResponse response = SokanFactory.eINSTANCE
.createFacetedResponse();
response.setQuery(request);
response.getContent().addAll(content);
response.setValueCountMap(valueCounts);
return response;
}
private static EList<String> adaptECollection(List<String> facetFields) {
return new BasicEList<String>(facetFields);
}
/**
* Creates a <code>Constraint</code> with the given name and the give single
* value.
*
* @param facetName
* The facet/column name to constrain on.
* @param value
* The single value.
* @return A new <code>Constraint</code> object
*/
public static Constraint createConstraint(String facetName, String value) {
List<String> values = new ArrayList<String>(1);
values.add(value);
return createConstraint(facetName, values);
}
/**
* Creates a <code>Constraint</code> with the given name and values.
*
* @param facetName
* The facet/column name to constrain on.
* @param values
* The list of value.
* @return A new <code>Constraint</code> object
*/
public static Constraint createConstraint(String facetName,
List<String> values) {
Constraint con = SokanFactory.eINSTANCE.createConstraint();
con.setName(facetName);
con.setValues(CoreUtil.adapt(values));
return con;
}
}