// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.dataquality.helpers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.talend.dataquality.domain.Domain;
import org.talend.dataquality.domain.DomainFactory;
import org.talend.dataquality.domain.JavaUDIIndicatorParameter;
import org.talend.dataquality.domain.LiteralValue;
import org.talend.dataquality.domain.RangeRestriction;
import org.talend.dataquality.domain.RealNumberValue;
import org.talend.dataquality.domain.TextValue;
import org.talend.dataquality.domain.pattern.ExpressionType;
import org.talend.dataquality.domain.pattern.Pattern;
import org.talend.dataquality.domain.pattern.PatternComponent;
import org.talend.dataquality.domain.pattern.PatternFactory;
import org.talend.dataquality.domain.pattern.PatternPackage;
import org.talend.dataquality.domain.pattern.RegularExpression;
import org.talend.i18n.Messages;
import orgomg.cwm.objectmodel.core.Expression;
/**
* @author scorreia
*
* Helper class for Domain object.
*/
public final class DomainHelper {
public static final String SQL_PATTERN_FOLDER = "SQL Patterns"; //$NON-NLS-1$
public static final String PATTERN_FOLDER = "Patterns"; //$NON-NLS-1$
private DomainHelper() {
}
/**
* The available pattern types.
*/
static enum PatternType {
TABLE_PATTERN("Table Pattern"), //$NON-NLS-1$
VIEW_PATTERN("View Pattern"), //$NON-NLS-1$
EXPECTED_VALUE("Expected value"); //$NON-NLS-1$
final String label;
PatternType(String lab) {
this.label = lab;
}
}
/**
* The available domain types.
*/
static enum DomainType {
ANALYSIS_DATA_FILTER("Analysis Data Filter"), //$NON-NLS-1$
INDICATOR_EXPECTED_VALUE("Indicator expected value"); //$NON-NLS-1$
String label;
DomainType(String lab) {
this.label = lab;
}
}
private static final DomainFactory DOMAIN = DomainFactory.eINSTANCE;
/**
* Method "createDomain" creates a new Domain with the given name.
*
* @param name the name of the domain (could be null)
* @return the new domain.
*/
public static Domain createDomain(String name) {
Domain domain = DOMAIN.createDomain();
domain.setName(name);
return domain;
}
/**
* Method "getRegexp".
*
* @param pattern a pattern
* @return the body of the regular expression applicable to this dbms or null
*/
public static String getSQLRegexp(Pattern pattern) {
return getRegexp(pattern, "SQL");
}
/**
* DOC yyi Comment method "getJavaRegexp".
*
* @param pattern
* @return
*/
public static String getJavaRegexp(Pattern pattern) {
return getRegexp(pattern, "Java");
}
/**
* DOC bZhou Comment method "getRegexp".
*
* @param pattern
* @param language
* @return
*/
public static String getRegexp(Pattern pattern, String language) {
EList<PatternComponent> components = pattern.getComponents();
for (PatternComponent patternComponent : components) {
if (patternComponent != null) {
Expression expression = getExpression(patternComponent, language);
if (expression != null) {
return expression.getBody();
}
}
}
return null;
}
/**
* Method "getExpression".
*
* @param patternComponent
* @param language a language (see DbmsLanguage)
* @return the expression for the given language or null
*/
public static Expression getExpression(PatternComponent patternComponent, String language) {
if (patternComponent != null && patternComponent.eClass().equals(PatternPackage.eINSTANCE.getRegularExpression())) {
RegularExpression regExp = (RegularExpression) patternComponent;
Expression expr = regExp.getExpression();
if (expr != null && language != null && language.equalsIgnoreCase(regExp.getExpression().getLanguage())) {
return expr;
}
}
// not a regular expression
return null;
}
/**
* Method "createIndicatorExpectedValueDomain".
*
* @return a domain dedicated to storing the expected value. The created domain's name is already set.
*/
public static Domain createIndicatorExpectedValueDomain() {
return createDomain(DomainHelper.DomainType.INDICATOR_EXPECTED_VALUE.label);
}
/**
* Method "addRangeRestriction" creates a new range restriction and adds it to the given domain.
*
* @param domain the domain to which a new range restriction will be added
* @return the newly created range restriction
*/
public static RangeRestriction addRangeRestriction(Domain domain) {
RangeRestriction rangeRestriction = DOMAIN.createRangeRestriction();
domain.getRanges().add(rangeRestriction);
return rangeRestriction;
}
/**
* Method "createContiguousClosedBinsIntoDomain".
*
* @param domainName (can be null)
* @param nbBins the number of bins to create
* @param min the minimal value
* @param max the maximal value
* @return the domain
*/
public static Domain createContiguousClosedBinsIntoDomain(String domainName, int nbBins, double min, double max) {
double[] bins = BinsHandler.generateClosedBins(min, max, nbBins);
return createContiguousClosedBinsIntoDomain(domainName, bins);
}
/**
* Method "createContiguousClosedBinsIntoDomain".
*
* @param domainName the domain name (can be null)
* @param bins the "closed" bins (the first value of array is the beginning of the bins and the last value of the
* array is the end of bins)
* @return the new Domain
*/
public static Domain createContiguousClosedBinsIntoDomain(String domainName, double[] bins) {
Domain domain = createDomain(domainName);
for (int i = 0; i < bins.length - 1; i++) {
double min = bins[i];
double max = bins[i + 1];
RangeRestriction rangeRestriction = createRealRangeRestriction(min, max);
domain.getRanges().add(rangeRestriction);
}
return domain;
}
/**
* Method "createRangeRestriction".
*
* @param min the min value of the range
* @param max the max value of the range
* @return the new Range restriction.
*/
public static RangeRestriction createRealRangeRestriction(double min, double max) {
RangeRestriction rangeRestriction = DOMAIN.createRangeRestriction();
rangeRestriction.setLowerValue(createRealNumberValue(null, min));
rangeRestriction.setUpperValue(createRealNumberValue(null, max));
return rangeRestriction;
}
public static RangeRestriction createStringRangeRestriction(String min, String max) {
RangeRestriction rangeRestriction = DOMAIN.createRangeRestriction();
rangeRestriction.setLowerValue(createStringValue(null, min));
rangeRestriction.setUpperValue(createStringValue(null, max));
return rangeRestriction;
}
/**
*
* DOC klliu Comment method "createJavaUDIIndicatorParameter".
*
* @param key
* @param value
* @return
*/
public static JavaUDIIndicatorParameter createJavaUDIIndicatorParameter(String key, String value) {
JavaUDIIndicatorParameter javaUDIIndicatorParameter = DOMAIN.createJavaUDIIndicatorParameter();
javaUDIIndicatorParameter.setKey(key);
javaUDIIndicatorParameter.setValue(value);
return javaUDIIndicatorParameter;
}
public static TextValue createStringValue(String meaning, String value) {
TextValue textValue = DomainFactory.eINSTANCE.createTextValue();
textValue.setEncodeValueMeaning(meaning);
textValue.setValue(value);
return textValue;
}
/**
* Method "createRealNumberValue".
*
* @param meaning the meaning of the value (can be null)
* @param value the value
* @return a real number value
*/
public static RealNumberValue createRealNumberValue(String meaning, double value) {
RealNumberValue realNumberValue = DomainFactory.eINSTANCE.createRealNumberValue();
realNumberValue.setEncodeValueMeaning(meaning);
realNumberValue.setValue(value);
return realNumberValue;
}
/**
* Method "getNumberOfBins".
*
* @param domain the domain containing bins
* @return the number of bins for this domain
*/
public static int getNumberOfBins(Domain domain) {
assert domain != null;
// TODO scorreia do check that the given domain is really a bins container.
return domain.getRanges().size();
}
/**
* Method "getMinBinValue".
*
* @param domain
* @return the lower value of the first bin.
*/
public static double getMinBinValue(Domain domain) {
EList<RangeRestriction> ranges = domain.getRanges();
if (ranges.isEmpty()) {
throw new IllegalArgumentException(Messages.getString("DomainHelper.NoRangeMin", domain.getName())); //$NON-NLS-1$
}
RangeRestriction r1 = ranges.get(0);
if (r1 == null) {
throw new IllegalArgumentException(Messages.getString("DomainHelper.FirstRangeMin", domain.getName())); //$NON-NLS-1$
}
return getRealValue(r1.getLowerValue());
}
/**
* Method "getMaxBinValue".
*
* @param domain
* @return the higher value of the last bin.
* @throws IllegalArgumentException
*/
public static double getMaxBinValue(Domain domain) {
EList<RangeRestriction> ranges = domain.getRanges();
if (ranges.isEmpty()) {
throw new IllegalArgumentException(Messages.getString("DomainHelper.NoRangeMax", domain.getName())); //$NON-NLS-1$
}
int lastIdx = ranges.size() - 1;
RangeRestriction r1 = ranges.get(lastIdx);
if (r1 == null) {
throw new IllegalArgumentException(Messages.getString("DomainHelper.LastRangeMax", domain.getName())); //$NON-NLS-1$
}
return getRealValue(r1.getUpperValue());
}
public static String getMinValue(RangeRestriction range) {
return getValueAsText(range.getLowerValue());
}
public static String getMaxValue(RangeRestriction range) {
return getValueAsText(range.getUpperValue());
}
public static double getRealValue(LiteralValue object) {
RealNumberValue upperValue = DataqualitySwitchHelper.REAL_NB_VALUE_SWITCH.doSwitch(object);
if (upperValue == null) {
throw new IllegalArgumentException(Messages.getString("DomainHelper.NotContainRealValue", object)); //$NON-NLS-1$
}
return upperValue.getValue();
}
private static String getValueAsText(LiteralValue object) {
return DataqualitySwitchHelper.LITTERAL_VALUE_AS_TEXT_SWITCH.doSwitch(object);
}
/**
* Method "getDomains".
*
* @param objects some objects
* @return only the Domain objects
*/
public static List<Domain> getDomains(Collection<EObject> objects) {
List<Domain> domains = new ArrayList<Domain>();
for (EObject object : objects) {
Domain domain = DataqualitySwitchHelper.DOMAIN_SWITCH.doSwitch(object);
if (domain != null) {
domains.add(domain);
}
}
return domains;
}
/**
* Method "getPatterns".
*
* @param objects a list of objects
* @return the Pattern objects extracted from the given list
*/
public static List<Pattern> getPatterns(Collection<EObject> objects) {
List<Pattern> patterns = new ArrayList<Pattern>();
for (EObject object : objects) {
Pattern pattern = DataqualitySwitchHelper.PATTERN_SWITCH.doSwitch(object);
if (pattern != null) {
patterns.add(pattern);
}
}
return patterns;
}
public static Domain setDataFilterTablePattern(final Collection<Domain> dataFilters, String tablePattern) {
return setDataFilterPattern(dataFilters, PatternType.TABLE_PATTERN, DomainType.ANALYSIS_DATA_FILTER, tablePattern);
}
public static Domain setDataFilterViewPattern(final Collection<Domain> dataFilters, String viewPattern) {
return setDataFilterPattern(dataFilters, PatternType.VIEW_PATTERN, DomainType.ANALYSIS_DATA_FILTER, viewPattern);
}
public static Domain setIndicatorExpectedValuePattern(final Collection<Domain> dataFilters, String filterPattern) {
return setDataFilterPattern(dataFilters, PatternType.EXPECTED_VALUE, DomainType.INDICATOR_EXPECTED_VALUE, filterPattern);
}
/**
* Method "setDataFilterPattern".
*
* @param dataFilters a list of data filters
* @param type
* @param domainName
* @param filterPattern
* @return
*/
private static Domain setDataFilterPattern(final Collection<Domain> dataFilters, PatternType type, DomainType domainName,
String filterPattern) {
RegularExpression filterExpr = BooleanExpressionHelper.createRegularExpression(null, filterPattern);
for (Domain domain : dataFilters) {
if (!domainName.label.equals(domain.getName())) {
continue;
}
boolean exists = false;
EList<Pattern> patterns = domain.getPatterns();
for (Pattern pattern : patterns) {
if (type.label.equals(pattern.getName())) {
exists = true;
pattern.getComponents().clear(); // remove previous expressions
pattern.getComponents().add(filterExpr);
}
}
if (!exists) {
// create pattern and set into the data filter
addPatternToDomain(domain, filterExpr, filterPattern, type);
}
return domain;
}
// no data filter has not been set yet
Domain domain = DomainFactory.eINSTANCE.createDomain();
dataFilters.add(domain);
domain.setName(domainName.label);
addPatternToDomain(domain, filterExpr, filterPattern, type);
return domain;
}
public static String getTablePattern(final Collection<Domain> dataFilters) {
return getPattern(dataFilters, DomainType.ANALYSIS_DATA_FILTER, PatternType.TABLE_PATTERN);
}
public static String getViewPattern(final Collection<Domain> dataFilters) {
return getPattern(dataFilters, DomainType.ANALYSIS_DATA_FILTER, PatternType.VIEW_PATTERN);
}
/**
* Method "getIndicatorExpectedValue".
*
* @param dataFilters
* @return the expected value constraint found in the list of domains.
*/
public static String getIndicatorExpectedValue(final Collection<Domain> dataFilters) {
return getPattern(dataFilters, DomainType.INDICATOR_EXPECTED_VALUE, PatternType.EXPECTED_VALUE);
}
/**
* Method "createPattern".
*
* @param language
* @param regexp
* @return a new pattern from the given regular expression
*/
public static Pattern createPattern(String language, String regexp) {
Pattern pattern = PatternFactory.eINSTANCE.createPattern();
pattern.getComponents().add(BooleanExpressionHelper.createRegularExpression(language, regexp));
return pattern;
}
private static String getPattern(final Collection<Domain> dataFilters, DomainType domainType, PatternType patternType) {
if (dataFilters == null) {
return null;
}
for (Domain domain : dataFilters) {
if (!domainType.label.equals(domain.getName())) {
continue;
}
EList<Pattern> patterns = domain.getPatterns();
for (Pattern pattern : patterns) {
if (patternType.label.equals(pattern.getName())) {
PatternComponent next = pattern.getComponents().iterator().next();
if (next == null) {
continue;
} else {
RegularExpression regexp = (RegularExpression) next;
Expression expression = regexp.getExpression();
if (expression != null) {
return expression.getBody();
}
}
}
}
}
return null;
}
/**
* Method "addPatternToDomain" creates a Pattern object with the given expression and stores it in the given domain.
* Beware that it is also added to the owned elements of the Domain. This means that is contained in the domain and
* cannot be shared among several domains.
*
* @param domain
* @param tableFilter
* @param tablePattern
*/
private static void addPatternToDomain(Domain domain, RegularExpression tableFilter, String tablePattern, PatternType type) {
Pattern pattern = PatternFactory.eINSTANCE.createPattern();
pattern.setName(type.label);
pattern.getComponents().add(tableFilter);
domain.getPatterns().add(pattern);
domain.getOwnedElement().add(pattern);
}
/**
* Method "getExpressionType".
*
* @param pattern
* @return the expression type of the regular expression contained in the given pattern or null
*/
public static String getExpressionType(Pattern pattern) {
if (pattern != null) {
EList<PatternComponent> components = pattern.getComponents();
if (!components.isEmpty()) {
PatternComponent component = components.get(0);
if (component == null) {
return null;
} else {
RegularExpression regexp = DataqualitySwitchHelper.REGULAR_EXPR_SWITCH.doSwitch(component);
if (regexp != null) {
String expressionType = regexp.getExpressionType();
if (StringUtils.isEmpty(expressionType)) {
// identify the expression from the path where it is stored (useful for old patterns created
// in
// version 1.1 and before)
final Resource resource = regexp.eResource();
if (resource != null) {
// do not replace these strings. They are the folder names in version 1.1
if (resource.getURI().toString().contains(SQL_PATTERN_FOLDER)) {
expressionType = ExpressionType.SQL_LIKE.getLiteral();
} else if (resource.getURI().toString().contains(PATTERN_FOLDER)) {
expressionType = ExpressionType.REGEXP.getLiteral();
}
}
}
return expressionType;
}
}
}
}
return null;
}
}