ncube.grv.exp.NCubeGroovyExpression.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of n-cube Show documentation
Show all versions of n-cube Show documentation
Multi-dimensional Rule Engine
package ncube.grv.exp
import com.cedarsoftware.ncube.ApplicationID
import com.cedarsoftware.ncube.Axis
import com.cedarsoftware.ncube.Column
import com.cedarsoftware.ncube.DecisionTable
import com.cedarsoftware.ncube.NCube
import com.cedarsoftware.ncube.NCubeAppContext
import com.cedarsoftware.ncube.NCubeInfoDto
import com.cedarsoftware.ncube.NCubeMutableClient
import com.cedarsoftware.ncube.NCubeRuntimeClient
import com.cedarsoftware.ncube.exception.RuleJump
import com.cedarsoftware.ncube.exception.RuleStop
import com.cedarsoftware.util.CaseInsensitiveSet
import com.cedarsoftware.util.CompactCILinkedMap
import com.cedarsoftware.util.TrackingMap
import groovy.transform.CompileStatic
import static com.cedarsoftware.ncube.NCubeConstants.SEARCH_ACTIVE_RECORDS_ONLY
import static com.cedarsoftware.util.StringUtilities.createUTF8String
import static com.cedarsoftware.util.StringUtilities.equalsIgnoreCase
import static com.cedarsoftware.util.UrlUtilities.getContentFromUrl
/**
* Base class for all GroovyExpression and GroovyMethod's within n-cube CommandCells.
* @see com.cedarsoftware.ncube.GroovyBase
*
* @author John DeRegnaucourt ([email protected])
*
* Copyright (c) Cedar Software LLC
*
* 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.
*/
@CompileStatic
class NCubeGroovyExpression
{
public Map input
public Map output
public NCube ncube
private static NCubeMutableClient mutableClient = null
private static boolean legacyNCubeGroovyExpression = false
/**
* Fetch the named n-cube from the NCubeRuntime. It looks at the same
* account, app, and version as the running n-cube.
* @param name String n-cube name (optional, defaults to name of currently executing cube).
* @param quiet boolean (optional, defaults to false). Set to true if you want null returned
* when the cube is not found (as opposed to an exception being thrown).
* @return NCube with the given name.
*/
NCube getCube(String name = ncube.name, boolean quiet = false)
{
if (equalsIgnoreCase(ncube.name, name))
{
return ncube
}
NCube cube = ncubeRuntime.getCube(ncube.applicationID, name)
if (cube == null && !quiet)
{
throw new IllegalArgumentException("getCube() call within cell attempted, n-cube: ${name} not found.")
}
return cube
}
/**
* Short-cut to fetch ApplicationID for current cell.
*/
ApplicationID getApplicationID()
{
return ncube.applicationID
}
/**
* Fetch all cube names in the current application.
* @return Set cube names>
*/
Set getCubeNames(boolean activeOnly = true)
{
List searchResults = ncubeRuntime.search(ncube.applicationID, null, null, [(SEARCH_ACTIVE_RECORDS_ONLY):activeOnly])
Set names = new CaseInsensitiveSet(searchResults.size())
searchResults.each { NCubeInfoDto dto -> names.add(dto.name) }
return names
}
/**
* Fetch cube records that match the given pattern.
* @param namePattern String text pattern or exact file name used to filter cube name(s)
* @param textPattern String text pattern filter cubes returned. This is matched
* against the JSON content (contains() search).
* @param options Map of NCubeRuntime.SEARCH_* options. Optional. Defaults to active records only.
* @return Object[] of NCubeInfoDto instances.
*/
List search(String namePattern, String textPattern, Map options = [(SEARCH_ACTIVE_RECORDS_ONLY):true])
{
List dtos = ncubeRuntime.search(ncube.applicationID, namePattern, textPattern, options)
return dtos
}
/**
* @return Map containing system parameters (e.g. branch, etc.)
*/
Map getSystemParams()
{
return ncubeRuntime.systemParams
}
/**
* Using the input Map passed in, fetch the coordinate at that location.
* @param coord Map containing precise coordinate to use.
* @param cubeName String n-cube name. This argument is optional and defaults
* to the same cube as the cell currently executing.
* @param defaultValue Object to return when no cell exists at the target coordinate
* and the cube does not have a cube-level default. This argument is optional.
* @return executed cell contents at the given coordinate.
*/
def go(Map coord, String cubeName = ncube.name, def defaultValue = null)
{
if (coord.is(input))
{
coord = dupe(inputWithoutTrackingMap)
}
return getCube(cubeName).getCell(coord, output, defaultValue)
}
/**
* Using the input Map passed in, fetch the coordinate at that location.
* @param coord Map containing precise coordinate to use.
* @param cube NCube the n-cube to fetch the result from - passed in to save processing time.
* @param defaultValue Object to return when no cell exists at the target coordinate
* and the cube does not have a cube-level default. This argument is optional.
* @return executed cell contents at the given coordinate.
*/
def go(Map coord, NCube cube, def defaultValue = null)
{
if (coord.is(input))
{
coord = dupe(inputWithoutTrackingMap)
}
return cube.getCell(coord, output, defaultValue)
}
/**
* Using the input Map passed in, fetch the coordinate at that location.
* @param coord Map containing precise coordinate to use.
* @param cubeName String n-cube name. This argument is optional and defaults
* to the same cube as the cell currently executing.
* @param defaultValue Object to return when no cell exists at the target coordinate
* and the cube does not have a cube-level default.
* @param ApplicationID of a different application (reference data application for
* example) from which the running cube exists.
* @return executed cell contents at the given coordinate.
*/
def go(Map coord, String cubeName, def defaultValue, ApplicationID appId)
{
NCube target = ncubeRuntime.getCube(appId, cubeName)
if (target == null)
{
throw new IllegalArgumentException("go() attempted from cell, n-cube: ${cubeName} not found, app: ${appId}")
}
if (coord.is(input))
{
coord = dupe(inputWithoutTrackingMap)
}
return target.getCell(coord, output, defaultValue)
}
/**
* Fetch the cell contents using the current input coordinate and specified n-cube,
* but first apply any updates from the passed in coordinate.
* @param coord Map containing 'updates' to the current input coordinate.
* @param cubeName String n-cube name. This argument is optional and defaults
* to the same cube as the cell currently executing.
* @param defaultValue Object to return when no cell exists at the target coordinate
* and the cube does not have a cube-level default. This argument is optional.
* @return executed cell contents at the current input location and specified n-cube,
* but first apply updates to the current input coordinate from the passed in coord.
*/
def at(Map coord, String cubeName = ncube.name, def defaultValue = null)
{
Map copy = inputWithoutTrackingMap
copy = dupe(copy)
copy.putAll(coord)
return getCube(cubeName).getCell(copy, output, defaultValue)
}
/**
* Fetch the cell contents using the current input coordinate and specified n-cube,
* but first apply any updates from the passed in coordinate.
* @param coord Map containing 'updates' to the current input coordinate.
* @param cubeName String n-cube name. This argument is optional and defaults
* to the same cube as the cell currently executing.
* @param defaultValue Object to return when no cell exists at the target coordinate
* and the cube does not have a cube-level default. This argument is optional.
* @return executed cell contents at the current input location and specified n-cube,
* but first apply updates to the current input coordinate from the passed in coord.
*/
def at(Map coord, NCube cube, def defaultValue = null)
{
Map copy = inputWithoutTrackingMap
copy = dupe(copy)
copy.putAll(coord)
return cube.getCell(copy, output, defaultValue)
}
/**
* Fetch the cell contents using the current input coordinate and specified n-cube,
* but first apply any updates from the passed in coordinate.
* @param coord Map containing 'updates' to the current input coordinate.
* @param cubeName String n-cube name. This argument is optional and defaults
* to the same cube as the cell currently executing.
* @param defaultValue Object to return when no cell exists at the target coordinate
* and the cube does not have a cube-level default.
* @param ApplicationID of a different application (reference data application for
* example) from which the running cube exists.
* @return executed cell contents at the current input location and specified n-cube,
* but first apply updates to the current input coordinate from the passed in coord.
*/
def at(Map coord, String cubeName, def defaultValue, ApplicationID appId)
{
NCube target = ncubeRuntime.getCube(appId, cubeName)
if (target == null)
{
throw new IllegalArgumentException("at() attempted from cell, n-cube: ${cubeName} not found, app: ${appId}")
}
Map copy = inputWithoutTrackingMap
copy = dupe(copy)
copy.putAll(coord)
return target.getCell(copy, output, defaultValue)
}
/**
* Fetch the cell at location 'altInput', but execute with the current cell location (input). This
* API allows you to create reference cells and execute them from anywhere, with the context (input
* coordinate) of the calling cell.
* @param altInput Map coordinate of reference cell (often a cell on a default column, e.g [businessUnit:null] as input)
* The original input is implied, so all that is typically added to altInput, is the necessary changes to input
* to have it point to another cell.
* @param cubeName String name of a cube (optional), when pointing to a cell in another n-cube.
* @param defaultValue Object to return when no cell exists at the target coordinate
* and the cube does not have a cube-level default.
* @return value from executing the cell identified by current input map + modifications from altInput.
*/
def use(Map altInput, String cubeName = ncube.name, def defaultValue = null)
{
Map copy = inputWithoutTrackingMap
Map origInput = new CompactCILinkedMap(copy)
Map modInput = dupe(copy)
modInput.putAll(altInput)
return getCube(cubeName).use(modInput, origInput, output, defaultValue)
}
/**
* Fetch the cell at location 'altInput', but execute with the current cell location (input). This
* API allows you to create reference cells and execute them from anywhere, with the context (input
* coordinate) of the calling cell.
* @param altInput Map coordinate of reference cell (often a cell on a default column, e.g [businessUnit:null] as input)
* The original input is implied, so all that is typically added to altInput, is the necessary changes to input
* to have it point to another cell.
* @param cubeName String name of a cube (optional), when pointing to a cell in another n-cube.
* @param defaultValue Object to return when no cell exists at the target coordinate
* and the cube does not have a cube-level default.
* @param ApplicationID of a different application, needed only if reference cell resides in another app, for
* example, an n-cube full of reference cells by design.
* @return value from executing the cell identified by current input map + modifications from altInput.
*/
def use(Map altInput, String cubeName, def defaultValue, ApplicationID appId)
{
NCube target = ncubeRuntime.getCube(appId, cubeName)
if (target == null)
{
throw new IllegalArgumentException("use() attempted in cell, n-cube: ${cubeName} not found, app: ${appId}")
}
Map copy = inputWithoutTrackingMap
Map origInput = new CompactCILinkedMap(copy)
Map modInput = dupe(copy)
modInput.putAll(altInput)
return target.use(modInput, origInput, output, defaultValue)
}
private Map getInputWithoutTrackingMap()
{
Map copy = input
while (copy instanceof TrackingMap)
{
copy = ((TrackingMap)copy).getWrappedMap()
}
return copy
}
private Map dupe(Map map)
{
return legacyNCubeGroovyExpression ? map : new CompactCILinkedMap(map)
}
/**
* Filter rows of an n-cube. Use this API to fetch a subset of an n-cube, similar to SQL SELECT.
* @param rowAxisName String name of axis acting as the ROW axis.
* @param colAxisName String name of axis acting as the COLUMN axis.
* @param where String groovy statement block (or expression) written as condition in terms of the columns on the colAxisName.
* Example: "(input.state == 'TX' || input.state == 'OH') && (input.attribute == 'fuzzy')". This will only return rows
* where this condition is met ('state' and 'attribute' are two column values from the colAxisName). The values for each
* row in the rowAxis is bound to the where expression for each row. If the row passes the 'where' condition, it is
* included in the output.
* @param columnsToSearch Set which allows reducing the number of columns bound for use in the where clause. If not
* specified, all columns on the colAxisName can be used. For example, if you had an axis named 'attribute', and it
* has 10 columns on it, you could list just two (2) of the columns here, and only those columns would be placed into
* values accessible to the where clause via input.xxx == 'someValue'. The mapReduce() API runs faster when fewer
* columns are included in the columnsToSearch.
* @param columnsToReturn Set of values to indicate which columns to return. If not specified, the entire 'row' is
* returned. For example, if you had an axis named 'attribute', and it has 10 columns on it, you could list just
* two (2) of the columns here, in the returned Map of rows, only these two columns will be in the returned Map.
* The columnsToSearch and columnsToReturn can be completely different, overlap, or not be specified. This param
* is similar to the 'Select List' portion of the SQL SELECT statement. It essentially defaults to '*', but you
* can have it return less column/value pairs in the returned Map if you add only the columns you want returned
* here.
* @param cubeName String name of another cube (when the reference is to an n-cube other than 'this' n-cube). If not
* specified, the mapReduce() is run against the cube containing 'this' cell.
* @param appId ApplicationID of another n-cube application. If not specified, the appId of the n-cube containing
* 'this' cell is used.
* @param defaultValue Object placed here will be returned if there is no cell at the location
* pinpointed by the input coordinate. Normally, the defaulValue of the
* n-cube is returned, but if this parameter is passed a non-null value,
* then it will be returned. Optional.
* @return Map of Maps - The outer Map is keyed by the column values of all row columns. If the row Axis is a discrete
* axis, then the keys of the map are all the values of the columns. If a non-discrete axis is used, then the keys
* are the name meta-key for each column. If a non-discrete axis is used and there are no name attributes on the columns,
* and exception will be thrown. The 'value' associated to the key (column value or column name) is a Map record,
* where the keys are the column values (or names) for axis named colAxisName. The associated values are the values
* for each cell in the same column, for when the 'where' condition holds true (groovy true).
*/
Map mapReduce(String colAxisName, Closure where = { true }, Map options = [:], String cubeName = null, ApplicationID appId = null)
{
NCube target
if (cubeName != null)
{
appId = appId ?: applicationID
target = ncubeRuntime.getCube(appId, cubeName)
if (target == null)
{
throw new IllegalArgumentException("mapReduce() attempted within cell, but n-cube: ${cubeName} not found in app: ${appId}")
}
}
else
{
target = ncube
}
options.input = input
options.output = output
return target.mapReduce(colAxisName, where, options)
}
/**
* Main API for querying a Decision Table with a single query input from an NCube cell.
* @param decisionInput Map containing key/value pairs for all the input_value columns
* @param cubeName String name of another cube (when the reference is to an n-cube other than 'this' n-cube). If not
* specified, the getDecision() is run against the cube containing 'this' cell.
* @param appId ApplicationID of another n-cube application. If not specified, the appId of the n-cube containing
* 'this' cell is used.
* @return List>
*/
Map getDecision(Map decisionInput, String cubeName, ApplicationID appId = ncube.applicationID)
{
NCube ncube = ncubeRuntime.getCube(appId, cubeName)
if (ncube == null)
{
throw new IllegalArgumentException("getDecision() attempted within cell, but n-cube: ${cubeName} not found in app: ${appId}")
}
return ncube.decisionTable.getDecision(decisionInput)
}
/**
* Main API for querying a Decision Table with multiple inputs from an NCube cell, where the result will be OR'ed together.
* @param iterable Iterable
© 2015 - 2024 Weber Informatics LLC | Privacy Policy