| /* |
| * |
| * Copyright (c) 2013, 2016 - Loetz GmbH&Co.KG, 69115 Heidelberg, Germany |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| * |
| */ |
| package org.eclipse.osbp.xtext.datamartdsl.validation |
| |
| import com.google.inject.Inject |
| import java.util.List |
| import java.util.Set |
| import org.eclipse.osbp.xtext.basic.validation.IBasicValidatorDelegate |
| import org.eclipse.osbp.xtext.datamartdsl.AxisEnum |
| import org.eclipse.osbp.xtext.datamartdsl.ConditionalExpression |
| import org.eclipse.osbp.xtext.datamartdsl.Conjunction |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartAttribute |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartAttributeBase |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartCube |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartCubeAxis |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartDSLPackage |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartDefinition |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartEntity |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartHierarchy |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartHierarchyLevel |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartHierarchyLevelMultiple |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartHierarchyLevelSingle |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartSetFunction |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartSetTuple |
| import org.eclipse.osbp.xtext.datamartdsl.DatamartTask |
| import org.eclipse.osbp.xtext.datamartdsl.Expression |
| import org.eclipse.osbp.xtext.datamartdsl.SetFunctionEnum |
| import org.eclipse.osbp.xtext.datamartdsl.util.DatamartAttributeUtil |
| import org.eclipse.osbp.xtext.datamartdsl.util.DatamartHierarchyUtil |
| import org.eclipse.xtext.validation.Check |
| |
| /** |
| * Custom validation rules. |
| * |
| * see http://www.eclipse.org/Xtext/documentation.html#validation |
| */ |
| class DatamartDSLValidator extends AbstractDatamartDSLValidator { |
| |
| @Inject(optional=true) IBasicValidatorDelegate delegate |
| @Inject extension DatamartHierarchyUtil |
| |
| |
| @Check |
| def checkCommercialLicensed(DatamartDefinition datamart) { |
| if ((datamart.source instanceof DatamartTask)) { |
| if(delegate !== null && !delegate.validateCommercial("datamart", "net.osbee.bpm")) { |
| info('''BPM is needed and not yet licensed. License BPM at www.osbee.net''', datamart, null) |
| } |
| } |
| if ((datamart.source instanceof DatamartCube)) { |
| if(delegate !== null && !delegate.validateCommercial("datamart", "net.osbee.xtext.cube")) { |
| info('''Cube is needed and not yet licensed. License Cube at www.osbee.net''', datamart, null) |
| } |
| } |
| } |
| |
| @Check |
| def checkForDuplicatedAttributeNamesOrAliases(DatamartAttribute attribute) { |
| var attributeNames = <String>newHashSet() |
| var eObj = attribute.eContainer |
| while ((eObj !== null) && !(eObj instanceof DatamartEntity)){ |
| eObj = eObj.eContainer |
| } |
| if (eObj !== null){ |
| (eObj as DatamartEntity).checkForDuplicatedAttributeNamesOrAliases(attributeNames) |
| } |
| } |
| |
| private def void checkForDuplicatedAttributeNamesOrAliases(DatamartEntity entity, Set<String> attributeNames) { |
| var error = false |
| for (attribute : entity.attributes) { |
| var added = attributeNames.add(DatamartAttributeUtil.getAliasedAttributeName(attribute)) |
| if (!added){ |
| error = true |
| var errorTxt = '''Duplicated attribute names or aliases are not allowed in the same datamart definition.''' |
| if (attribute.aliased){ |
| error(errorTxt, attribute, DatamartDSLPackage.Literals.DATAMART_ATTRIBUTE__ALIAS_NAME) |
| } else { |
| error(errorTxt, attribute, DatamartDSLPackage.Literals.DATAMART_ATTRIBUTE_BASE__ATTRIBUTE_REF) |
| } |
| } |
| } |
| if (!error){ |
| var eObj = entity.eContainer |
| while ((eObj !== null) && !(eObj instanceof DatamartEntity)){ |
| eObj = eObj.eContainer |
| } |
| if (eObj !== null){ |
| (eObj as DatamartEntity).checkForDuplicatedAttributeNamesOrAliases(attributeNames) |
| } |
| } |
| } |
| |
| /** |
| * Checks if both axis "rows" and "columns" are defined when a DatamartCube definition contains either the axis "pages", "chapters" "sections" or all 3 of them. |
| */ |
| @Check |
| def checkForRowsAndColumnsPresenceInCube(DatamartCube cube) { |
| var error = false |
| |
| var hasAxisColumns = cube.axisslicer.exists[it instanceof DatamartCubeAxis && (it as DatamartCubeAxis).axis.name == AxisEnum.COLUMNS] |
| var hasAxisRows = cube.axisslicer.exists[it instanceof DatamartCubeAxis && (it as DatamartCubeAxis).axis.name == AxisEnum.ROWS] |
| |
| var axisPages = cube.axisslicer.findFirst[it instanceof DatamartCubeAxis && (it as DatamartCubeAxis).axis.name == AxisEnum.PAGES] |
| var axisChapters = cube.axisslicer.findFirst[it instanceof DatamartCubeAxis && (it as DatamartCubeAxis).axis.name == AxisEnum.CHAPTERS] |
| var axisSections = cube.axisslicer.findFirst[it instanceof DatamartCubeAxis && (it as DatamartCubeAxis).axis.name == AxisEnum.SECTIONS] |
| |
| //Pages |
| if(axisPages!==null && !hasAxisColumns || axisPages!==null && !hasAxisRows){ |
| error = true |
| var errorTxt = ''' "pages" can't be used without setting up both "columns" and "rows".''' |
| error(errorTxt, axisPages, DatamartDSLPackage.Literals.DATAMART_CUBE_AXIS__AXIS) |
| } |
| //Chapters |
| if(axisChapters!==null && !hasAxisColumns || axisChapters!==null && !hasAxisRows){ |
| error = true |
| var errorTxt = ''' ''chapters'' can't be used without setting up both ''columns'' and ''rows''.''' |
| error(errorTxt, axisChapters, DatamartDSLPackage.Literals.DATAMART_CUBE_AXIS__AXIS) |
| } |
| //Sections |
| if(axisSections!==null && !hasAxisColumns || axisSections!==null && !hasAxisRows){ |
| error = true |
| var errorTxt = ''' ''sections'' can't be used without setting up both ''columns'' and ''rows''.''' |
| error(errorTxt, axisSections, DatamartDSLPackage.Literals.DATAMART_CUBE_AXIS__AXIS) |
| } |
| } |
| |
| /** |
| * Checks if both axis "rows" and "columns" are defined when a DatamartEntity definition contains either the axis "pages", "chapters" "sections" or all 3 of them. |
| */ |
| @Check |
| def checkForRowsAndColumnsPresenceInEntity(DatamartEntity entity) { |
| var error = false |
| |
| var hasAxisColumns = entity.attributes.exists[it instanceof DatamartAttribute && (it as DatamartAttribute).axis.name == AxisEnum.COLUMNS] |
| var hasAxisRows = entity.attributes.exists[it instanceof DatamartAttribute && (it as DatamartAttribute).axis.name == AxisEnum.ROWS] |
| |
| var axisPages = entity.attributes.findFirst[it instanceof DatamartAttribute && (it as DatamartAttribute).axis.name == AxisEnum.PAGES] |
| var axisChapters = entity.attributes.findFirst[it instanceof DatamartAttribute && (it as DatamartAttribute).axis.name == AxisEnum.CHAPTERS] |
| var axisSections = entity.attributes.findFirst[it instanceof DatamartAttribute && (it as DatamartAttribute).axis.name == AxisEnum.SECTIONS] |
| |
| //Pages |
| if(axisPages!==null && !hasAxisColumns || axisPages!==null && !hasAxisRows){ |
| error = true |
| var errorTxt = ''' ''pages'' can't be used without setting up both ''columns'' and ''rows''.''' |
| error(errorTxt, axisPages, DatamartDSLPackage.Literals.DATAMART_ATTRIBUTE__AXIS) |
| } |
| //Chapters |
| if(axisChapters!==null && !hasAxisColumns || axisChapters!==null && !hasAxisRows){ |
| error = true |
| var errorTxt = ''' ''chapters'' can't be used without setting up both ''columns'' and ''rows''.''' |
| error(errorTxt, axisChapters, DatamartDSLPackage.Literals.DATAMART_ATTRIBUTE__AXIS) |
| } |
| //Sections |
| if(axisSections!==null && !hasAxisColumns || axisSections!==null && !hasAxisRows){ |
| error = true |
| var errorTxt = ''' ''sections'' can't be used without setting up both ''columns'' and ''rows''.''' |
| error(errorTxt, axisSections, DatamartDSLPackage.Literals.DATAMART_ATTRIBUTE__AXIS) |
| } |
| } |
| |
| /** |
| * Checks that no transient attribute is used. |
| */ |
| @Check |
| def checkForTransientAttribute(DatamartAttributeBase attribute) { |
| val entityAttribute = attribute.attributeRef |
| var error = false |
| if ((entityAttribute.eIsProxy) || (!entityAttribute.eIsProxy && entityAttribute.transient)) { |
| error = true |
| var errorTxt = ''' ''attribute'' can't refer to an unresolved or transient entity attribute.''' |
| error(errorTxt, attribute, DatamartDSLPackage.Literals.DATAMART_ATTRIBUTE_BASE__ATTRIBUTE_REF) |
| } |
| } |
| |
| /** |
| * Checks that two same hierarchies are not used in the same datamart axis row definition. |
| */ |
| // @Check |
| // def checkForUniqueHierarchy(DatamartHierarchy hierarchy) { |
| // var error = false |
| // var parent = hierarchy.eContainer |
| // if (parent instanceof DatamartCubeAxis) { |
| // var hierarchiesFound = 0 |
| // for (element : (parent as DatamartCubeAxis).elements) { |
| // if (element instanceof DatamartHierarchy) { |
| // if (hierarchy.hierarchyRef.name.equals((element as DatamartHierarchy).hierarchyRef.name)) { |
| // hierarchiesFound++ |
| // } |
| // } |
| // if (hierarchiesFound > 1) { |
| // error = true |
| // var errorTxt = ''' ''hierarchy'' can't refer to more than one member of the same hierarchy.''' |
| // error(errorTxt, hierarchy, DatamartDSLPackage.Literals.DATAMART_HIERARCHY__HIERARCHY_REF) |
| // } |
| // } |
| // } |
| // } |
| |
| @Check |
| def checkNoLevelInYtd(DatamartHierarchy hierarchy){ |
| var eObject = hierarchy.eContainer |
| while ((eObject!==null) && !(eObject instanceof DatamartSetTuple)){ |
| eObject = eObject.eContainer |
| } |
| if (eObject !== null){ |
| var function = (eObject as DatamartSetTuple).left.setFunction |
| if ((function instanceof DatamartSetFunction) && SetFunctionEnum.YTD.equals((function as DatamartSetFunction).setFunction)){ |
| if (hierarchy.existLevelDefinition){ |
| var errorTxt = ''' ''hierarchy'' can't define a level as part of the '«SetFunctionEnum.YTD.literal»' function. Please remove the complete level.''' |
| error(errorTxt, hierarchy, DatamartDSLPackage.Literals.DATAMART_HIERARCHY__LEVEL) |
| } |
| } |
| } |
| } |
| |
| @Check |
| def checkSortedInLevel(DatamartHierarchyLevel hierarchyLevel){ |
| if (hierarchyLevel instanceof DatamartHierarchyLevelMultiple) { |
| var sorted = 0 |
| for (level : hierarchyLevel.levels) { |
| if (level.sorted) sorted++ |
| if (sorted > 1) { |
| var errorTxt = ''' Only one level is allowed to have the ''sorted'' attribute. Please remain only one ''sorted'' attribute.''' |
| error(errorTxt, hierarchyLevel, DatamartDSLPackage.Literals.DATAMART_HIERARCHY_LEVEL_SINGLE__SORTED) |
| } |
| } |
| } else { |
| if (!(hierarchyLevel.eContainer instanceof DatamartHierarchyLevelMultiple)) { |
| if ((hierarchyLevel instanceof DatamartHierarchyLevelSingle) && (hierarchyLevel as DatamartHierarchyLevelSingle).sorted) { |
| var errorTxt = ''' Only a level of a hierarchized hierarchy is allowed to have the ''sorted'' attribute. Please remove it.''' |
| error(errorTxt, hierarchyLevel, DatamartDSLPackage.Literals.DATAMART_HIERARCHY_LEVEL_SINGLE__SORTED) |
| } |
| } |
| } |
| } |
| |
| @Check |
| def checkConditions(DatamartEntity entity){ |
| for(datamartCondition : entity.conditions) { |
| var rangedList = <String>newArrayList() |
| var filteredList = <String>newArrayList() |
| fillRangedAndFilteredExpression(datamartCondition.condition, rangedList, filteredList) |
| for (filteredAttribute : filteredList){ |
| if (rangedList.contains(filteredAttribute)){ |
| var errorTxt = '''A filtered and a ranged condition is not allowed on the same attribute.''' |
| error(errorTxt, datamartCondition, DatamartDSLPackage.Literals.DATAMART_CONDITION__CONDITION) |
| |
| } |
| } |
| } |
| } |
| |
| def void fillRangedAndFilteredExpression(Expression expression, List<String> rangedList, List<String> filteredList){ |
| if (expression instanceof ConditionalExpression) { |
| var conditionalExpression = expression as ConditionalExpression |
| if (conditionalExpression.right.ranged){ |
| if (conditionalExpression.left instanceof DatamartAttributeBase){ |
| var attributeName = (conditionalExpression.left as DatamartAttributeBase).attributeRef.name |
| if (attributeName!==null){ |
| rangedList.add(attributeName) |
| } |
| } |
| } else if (conditionalExpression.right.filtered){ |
| if (conditionalExpression.left instanceof DatamartAttributeBase){ |
| var attributeName = (conditionalExpression.left as DatamartAttributeBase).attributeRef.name |
| if (attributeName!==null){ |
| filteredList.add(attributeName) |
| } |
| } |
| } |
| } else if (expression instanceof Conjunction) { |
| fillRangedAndFilteredExpression(expression.left, rangedList, filteredList); |
| fillRangedAndFilteredExpression(expression.right, rangedList, filteredList); |
| } |
| } |
| |
| } |