{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
{-# OPTIONS_GHC -fno-warn-unused-matches #-}

-- Derived from AWS service descriptions, licensed under Apache 2.0.

-- |
-- Module      : Amazonka.CostExplorer.Types.Expression
-- Copyright   : (c) 2013-2021 Brendan Hay
-- License     : Mozilla Public License, v. 2.0.
-- Maintainer  : Brendan Hay <brendan.g.hay+amazonka@gmail.com>
-- Stability   : auto-generated
-- Portability : non-portable (GHC extensions)
module Amazonka.CostExplorer.Types.Expression where

import qualified Amazonka.Core as Core
import Amazonka.CostExplorer.Types.CostCategoryValues
import Amazonka.CostExplorer.Types.DimensionValues
import Amazonka.CostExplorer.Types.TagValues
import qualified Amazonka.Lens as Lens
import qualified Amazonka.Prelude as Prelude

-- | Use @Expression@ to filter by cost or by usage. There are two patterns:
--
-- -   Simple dimension values - You can set the dimension name and values
--     for the filters that you plan to use. For example, you can filter
--     for @REGION==us-east-1 OR REGION==us-west-1@. For
--     @GetRightsizingRecommendation@, the Region is a full name (for
--     example, @REGION==US East (N. Virginia)@. The @Expression@ example
--     is as follows:
--
--     @{ \"Dimensions\": { \"Key\": \"REGION\", \"Values\": [ \"us-east-1\", “us-west-1” ] } }@
--
--     The list of dimension values are OR\'d together to retrieve cost or
--     usage data. You can create @Expression@ and @DimensionValues@
--     objects using either @with*@ methods or @set*@ methods in multiple
--     lines.
--
-- -   Compound dimension values with logical operations - You can use
--     multiple @Expression@ types and the logical operators @AND\/OR\/NOT@
--     to create a list of one or more @Expression@ objects. By doing this,
--     you can filter on more advanced options. For example, you can filter
--     on
--     @((REGION == us-east-1 OR REGION == us-west-1) OR (TAG.Type == Type1)) AND (USAGE_TYPE != DataTransfer)@.
--     The @Expression@ for that is as follows:
--
--     @{ \"And\": [ {\"Or\": [ {\"Dimensions\": { \"Key\": \"REGION\", \"Values\": [ \"us-east-1\", \"us-west-1\" ] }}, {\"Tags\": { \"Key\": \"TagName\", \"Values\": [\"Value1\"] } } ]}, {\"Not\": {\"Dimensions\": { \"Key\": \"USAGE_TYPE\", \"Values\": [\"DataTransfer\"] }}} ] } @
--
--     Because each @Expression@ can have only one operator, the service
--     returns an error if more than one is specified. The following
--     example shows an @Expression@ object that creates an error.
--
--     @ { \"And\": [ ... ], \"DimensionValues\": { \"Dimension\": \"USAGE_TYPE\", \"Values\": [ \"DataTransfer\" ] } } @
--
-- For the @GetRightsizingRecommendation@ action, a combination of OR and
-- NOT isn\'t supported. OR isn\'t supported between different dimensions,
-- or dimensions and tags. NOT operators aren\'t supported. Dimensions are
-- also limited to @LINKED_ACCOUNT@, @REGION@, or @RIGHTSIZING_TYPE@.
--
-- For the @GetReservationPurchaseRecommendation@ action, only NOT is
-- supported. AND and OR aren\'t supported. Dimensions are limited to
-- @LINKED_ACCOUNT@.
--
-- /See:/ 'newExpression' smart constructor.
data Expression = Expression'
  { -- | Return results that don\'t match a @Dimension@ object.
    Expression -> Maybe Expression
not :: Prelude.Maybe Expression,
    -- | Return results that match both @Dimension@ objects.
    Expression -> Maybe [Expression]
and :: Prelude.Maybe [Expression],
    -- | Return results that match either @Dimension@ object.
    Expression -> Maybe [Expression]
or :: Prelude.Maybe [Expression],
    -- | The filter that\'s based on @CostCategory@ values.
    Expression -> Maybe CostCategoryValues
costCategories :: Prelude.Maybe CostCategoryValues,
    -- | The specific @Dimension@ to use for @Expression@.
    Expression -> Maybe DimensionValues
dimensions :: Prelude.Maybe DimensionValues,
    -- | The specific @Tag@ to use for @Expression@.
    Expression -> Maybe TagValues
tags :: Prelude.Maybe TagValues
  }
  deriving (Expression -> Expression -> Bool
(Expression -> Expression -> Bool)
-> (Expression -> Expression -> Bool) -> Eq Expression
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Expression -> Expression -> Bool
$c/= :: Expression -> Expression -> Bool
== :: Expression -> Expression -> Bool
$c== :: Expression -> Expression -> Bool
Prelude.Eq, ReadPrec [Expression]
ReadPrec Expression
Int -> ReadS Expression
ReadS [Expression]
(Int -> ReadS Expression)
-> ReadS [Expression]
-> ReadPrec Expression
-> ReadPrec [Expression]
-> Read Expression
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Expression]
$creadListPrec :: ReadPrec [Expression]
readPrec :: ReadPrec Expression
$creadPrec :: ReadPrec Expression
readList :: ReadS [Expression]
$creadList :: ReadS [Expression]
readsPrec :: Int -> ReadS Expression
$creadsPrec :: Int -> ReadS Expression
Prelude.Read, Int -> Expression -> ShowS
[Expression] -> ShowS
Expression -> String
(Int -> Expression -> ShowS)
-> (Expression -> String)
-> ([Expression] -> ShowS)
-> Show Expression
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Expression] -> ShowS
$cshowList :: [Expression] -> ShowS
show :: Expression -> String
$cshow :: Expression -> String
showsPrec :: Int -> Expression -> ShowS
$cshowsPrec :: Int -> Expression -> ShowS
Prelude.Show, (forall x. Expression -> Rep Expression x)
-> (forall x. Rep Expression x -> Expression) -> Generic Expression
forall x. Rep Expression x -> Expression
forall x. Expression -> Rep Expression x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Expression x -> Expression
$cfrom :: forall x. Expression -> Rep Expression x
Prelude.Generic)

-- |
-- Create a value of 'Expression' with all optional fields omitted.
--
-- Use <https://hackage.haskell.org/package/generic-lens generic-lens> or <https://hackage.haskell.org/package/optics optics> to modify other optional fields.
--
-- The following record fields are available, with the corresponding lenses provided
-- for backwards compatibility:
--
-- 'not', 'expression_not' - Return results that don\'t match a @Dimension@ object.
--
-- 'and', 'expression_and' - Return results that match both @Dimension@ objects.
--
-- 'or', 'expression_or' - Return results that match either @Dimension@ object.
--
-- 'costCategories', 'expression_costCategories' - The filter that\'s based on @CostCategory@ values.
--
-- 'dimensions', 'expression_dimensions' - The specific @Dimension@ to use for @Expression@.
--
-- 'tags', 'expression_tags' - The specific @Tag@ to use for @Expression@.
newExpression ::
  Expression
newExpression :: Expression
newExpression =
  Expression' :: Maybe Expression
-> Maybe [Expression]
-> Maybe [Expression]
-> Maybe CostCategoryValues
-> Maybe DimensionValues
-> Maybe TagValues
-> Expression
Expression'
    { $sel:not:Expression' :: Maybe Expression
not = Maybe Expression
forall a. Maybe a
Prelude.Nothing,
      $sel:and:Expression' :: Maybe [Expression]
and = Maybe [Expression]
forall a. Maybe a
Prelude.Nothing,
      $sel:or:Expression' :: Maybe [Expression]
or = Maybe [Expression]
forall a. Maybe a
Prelude.Nothing,
      $sel:costCategories:Expression' :: Maybe CostCategoryValues
costCategories = Maybe CostCategoryValues
forall a. Maybe a
Prelude.Nothing,
      $sel:dimensions:Expression' :: Maybe DimensionValues
dimensions = Maybe DimensionValues
forall a. Maybe a
Prelude.Nothing,
      $sel:tags:Expression' :: Maybe TagValues
tags = Maybe TagValues
forall a. Maybe a
Prelude.Nothing
    }

-- | Return results that don\'t match a @Dimension@ object.
expression_not :: Lens.Lens' Expression (Prelude.Maybe Expression)
expression_not :: (Maybe Expression -> f (Maybe Expression))
-> Expression -> f Expression
expression_not = (Expression -> Maybe Expression)
-> (Expression -> Maybe Expression -> Expression)
-> Lens Expression Expression (Maybe Expression) (Maybe Expression)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
Lens.lens (\Expression' {Maybe Expression
not :: Maybe Expression
$sel:not:Expression' :: Expression -> Maybe Expression
not} -> Maybe Expression
not) (\s :: Expression
s@Expression' {} Maybe Expression
a -> Expression
s {$sel:not:Expression' :: Maybe Expression
not = Maybe Expression
a} :: Expression)

-- | Return results that match both @Dimension@ objects.
expression_and :: Lens.Lens' Expression (Prelude.Maybe [Expression])
expression_and :: (Maybe [Expression] -> f (Maybe [Expression]))
-> Expression -> f Expression
expression_and = (Expression -> Maybe [Expression])
-> (Expression -> Maybe [Expression] -> Expression)
-> Lens
     Expression Expression (Maybe [Expression]) (Maybe [Expression])
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
Lens.lens (\Expression' {Maybe [Expression]
and :: Maybe [Expression]
$sel:and:Expression' :: Expression -> Maybe [Expression]
and} -> Maybe [Expression]
and) (\s :: Expression
s@Expression' {} Maybe [Expression]
a -> Expression
s {$sel:and:Expression' :: Maybe [Expression]
and = Maybe [Expression]
a} :: Expression) ((Maybe [Expression] -> f (Maybe [Expression]))
 -> Expression -> f Expression)
-> ((Maybe [Expression] -> f (Maybe [Expression]))
    -> Maybe [Expression] -> f (Maybe [Expression]))
-> (Maybe [Expression] -> f (Maybe [Expression]))
-> Expression
-> f Expression
forall b c a. (b -> c) -> (a -> b) -> a -> c
Prelude.. AnIso [Expression] [Expression] [Expression] [Expression]
-> Iso
     (Maybe [Expression])
     (Maybe [Expression])
     (Maybe [Expression])
     (Maybe [Expression])
forall (f :: * -> *) (g :: * -> *) s t a b.
(Functor f, Functor g) =>
AnIso s t a b -> Iso (f s) (g t) (f a) (g b)
Lens.mapping AnIso [Expression] [Expression] [Expression] [Expression]
forall s t a b. (Coercible s a, Coercible t b) => Iso s t a b
Lens.coerced

-- | Return results that match either @Dimension@ object.
expression_or :: Lens.Lens' Expression (Prelude.Maybe [Expression])
expression_or :: (Maybe [Expression] -> f (Maybe [Expression]))
-> Expression -> f Expression
expression_or = (Expression -> Maybe [Expression])
-> (Expression -> Maybe [Expression] -> Expression)
-> Lens
     Expression Expression (Maybe [Expression]) (Maybe [Expression])
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
Lens.lens (\Expression' {Maybe [Expression]
or :: Maybe [Expression]
$sel:or:Expression' :: Expression -> Maybe [Expression]
or} -> Maybe [Expression]
or) (\s :: Expression
s@Expression' {} Maybe [Expression]
a -> Expression
s {$sel:or:Expression' :: Maybe [Expression]
or = Maybe [Expression]
a} :: Expression) ((Maybe [Expression] -> f (Maybe [Expression]))
 -> Expression -> f Expression)
-> ((Maybe [Expression] -> f (Maybe [Expression]))
    -> Maybe [Expression] -> f (Maybe [Expression]))
-> (Maybe [Expression] -> f (Maybe [Expression]))
-> Expression
-> f Expression
forall b c a. (b -> c) -> (a -> b) -> a -> c
Prelude.. AnIso [Expression] [Expression] [Expression] [Expression]
-> Iso
     (Maybe [Expression])
     (Maybe [Expression])
     (Maybe [Expression])
     (Maybe [Expression])
forall (f :: * -> *) (g :: * -> *) s t a b.
(Functor f, Functor g) =>
AnIso s t a b -> Iso (f s) (g t) (f a) (g b)
Lens.mapping AnIso [Expression] [Expression] [Expression] [Expression]
forall s t a b. (Coercible s a, Coercible t b) => Iso s t a b
Lens.coerced

-- | The filter that\'s based on @CostCategory@ values.
expression_costCategories :: Lens.Lens' Expression (Prelude.Maybe CostCategoryValues)
expression_costCategories :: (Maybe CostCategoryValues -> f (Maybe CostCategoryValues))
-> Expression -> f Expression
expression_costCategories = (Expression -> Maybe CostCategoryValues)
-> (Expression -> Maybe CostCategoryValues -> Expression)
-> Lens
     Expression
     Expression
     (Maybe CostCategoryValues)
     (Maybe CostCategoryValues)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
Lens.lens (\Expression' {Maybe CostCategoryValues
costCategories :: Maybe CostCategoryValues
$sel:costCategories:Expression' :: Expression -> Maybe CostCategoryValues
costCategories} -> Maybe CostCategoryValues
costCategories) (\s :: Expression
s@Expression' {} Maybe CostCategoryValues
a -> Expression
s {$sel:costCategories:Expression' :: Maybe CostCategoryValues
costCategories = Maybe CostCategoryValues
a} :: Expression)

-- | The specific @Dimension@ to use for @Expression@.
expression_dimensions :: Lens.Lens' Expression (Prelude.Maybe DimensionValues)
expression_dimensions :: (Maybe DimensionValues -> f (Maybe DimensionValues))
-> Expression -> f Expression
expression_dimensions = (Expression -> Maybe DimensionValues)
-> (Expression -> Maybe DimensionValues -> Expression)
-> Lens
     Expression
     Expression
     (Maybe DimensionValues)
     (Maybe DimensionValues)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
Lens.lens (\Expression' {Maybe DimensionValues
dimensions :: Maybe DimensionValues
$sel:dimensions:Expression' :: Expression -> Maybe DimensionValues
dimensions} -> Maybe DimensionValues
dimensions) (\s :: Expression
s@Expression' {} Maybe DimensionValues
a -> Expression
s {$sel:dimensions:Expression' :: Maybe DimensionValues
dimensions = Maybe DimensionValues
a} :: Expression)

-- | The specific @Tag@ to use for @Expression@.
expression_tags :: Lens.Lens' Expression (Prelude.Maybe TagValues)
expression_tags :: (Maybe TagValues -> f (Maybe TagValues))
-> Expression -> f Expression
expression_tags = (Expression -> Maybe TagValues)
-> (Expression -> Maybe TagValues -> Expression)
-> Lens Expression Expression (Maybe TagValues) (Maybe TagValues)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
Lens.lens (\Expression' {Maybe TagValues
tags :: Maybe TagValues
$sel:tags:Expression' :: Expression -> Maybe TagValues
tags} -> Maybe TagValues
tags) (\s :: Expression
s@Expression' {} Maybe TagValues
a -> Expression
s {$sel:tags:Expression' :: Maybe TagValues
tags = Maybe TagValues
a} :: Expression)

instance Core.FromJSON Expression where
  parseJSON :: Value -> Parser Expression
parseJSON =
    String
-> (Object -> Parser Expression) -> Value -> Parser Expression
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Core.withObject
      String
"Expression"
      ( \Object
x ->
          Maybe Expression
-> Maybe [Expression]
-> Maybe [Expression]
-> Maybe CostCategoryValues
-> Maybe DimensionValues
-> Maybe TagValues
-> Expression
Expression'
            (Maybe Expression
 -> Maybe [Expression]
 -> Maybe [Expression]
 -> Maybe CostCategoryValues
 -> Maybe DimensionValues
 -> Maybe TagValues
 -> Expression)
-> Parser (Maybe Expression)
-> Parser
     (Maybe [Expression]
      -> Maybe [Expression]
      -> Maybe CostCategoryValues
      -> Maybe DimensionValues
      -> Maybe TagValues
      -> Expression)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
Prelude.<$> (Object
x Object -> Text -> Parser (Maybe Expression)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
Core..:? Text
"Not")
            Parser
  (Maybe [Expression]
   -> Maybe [Expression]
   -> Maybe CostCategoryValues
   -> Maybe DimensionValues
   -> Maybe TagValues
   -> Expression)
-> Parser (Maybe [Expression])
-> Parser
     (Maybe [Expression]
      -> Maybe CostCategoryValues
      -> Maybe DimensionValues
      -> Maybe TagValues
      -> Expression)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
Prelude.<*> (Object
x Object -> Text -> Parser (Maybe (Maybe [Expression]))
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
Core..:? Text
"And" Parser (Maybe (Maybe [Expression]))
-> Maybe [Expression] -> Parser (Maybe [Expression])
forall a. Parser (Maybe a) -> a -> Parser a
Core..!= Maybe [Expression]
forall a. Monoid a => a
Prelude.mempty)
            Parser
  (Maybe [Expression]
   -> Maybe CostCategoryValues
   -> Maybe DimensionValues
   -> Maybe TagValues
   -> Expression)
-> Parser (Maybe [Expression])
-> Parser
     (Maybe CostCategoryValues
      -> Maybe DimensionValues -> Maybe TagValues -> Expression)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
Prelude.<*> (Object
x Object -> Text -> Parser (Maybe (Maybe [Expression]))
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
Core..:? Text
"Or" Parser (Maybe (Maybe [Expression]))
-> Maybe [Expression] -> Parser (Maybe [Expression])
forall a. Parser (Maybe a) -> a -> Parser a
Core..!= Maybe [Expression]
forall a. Monoid a => a
Prelude.mempty)
            Parser
  (Maybe CostCategoryValues
   -> Maybe DimensionValues -> Maybe TagValues -> Expression)
-> Parser (Maybe CostCategoryValues)
-> Parser (Maybe DimensionValues -> Maybe TagValues -> Expression)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
Prelude.<*> (Object
x Object -> Text -> Parser (Maybe CostCategoryValues)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
Core..:? Text
"CostCategories")
            Parser (Maybe DimensionValues -> Maybe TagValues -> Expression)
-> Parser (Maybe DimensionValues)
-> Parser (Maybe TagValues -> Expression)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
Prelude.<*> (Object
x Object -> Text -> Parser (Maybe DimensionValues)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
Core..:? Text
"Dimensions")
            Parser (Maybe TagValues -> Expression)
-> Parser (Maybe TagValues) -> Parser Expression
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
Prelude.<*> (Object
x Object -> Text -> Parser (Maybe TagValues)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
Core..:? Text
"Tags")
      )

instance Prelude.Hashable Expression

instance Prelude.NFData Expression

instance Core.ToJSON Expression where
  toJSON :: Expression -> Value
toJSON Expression' {Maybe [Expression]
Maybe DimensionValues
Maybe CostCategoryValues
Maybe TagValues
Maybe Expression
tags :: Maybe TagValues
dimensions :: Maybe DimensionValues
costCategories :: Maybe CostCategoryValues
or :: Maybe [Expression]
and :: Maybe [Expression]
not :: Maybe Expression
$sel:tags:Expression' :: Expression -> Maybe TagValues
$sel:dimensions:Expression' :: Expression -> Maybe DimensionValues
$sel:costCategories:Expression' :: Expression -> Maybe CostCategoryValues
$sel:or:Expression' :: Expression -> Maybe [Expression]
$sel:and:Expression' :: Expression -> Maybe [Expression]
$sel:not:Expression' :: Expression -> Maybe Expression
..} =
    [Pair] -> Value
Core.object
      ( [Maybe Pair] -> [Pair]
forall a. [Maybe a] -> [a]
Prelude.catMaybes
          [ (Text
"Not" Text -> Expression -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
Core..=) (Expression -> Pair) -> Maybe Expression -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
Prelude.<$> Maybe Expression
not,
            (Text
"And" Text -> [Expression] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
Core..=) ([Expression] -> Pair) -> Maybe [Expression] -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
Prelude.<$> Maybe [Expression]
and,
            (Text
"Or" Text -> [Expression] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
Core..=) ([Expression] -> Pair) -> Maybe [Expression] -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
Prelude.<$> Maybe [Expression]
or,
            (Text
"CostCategories" Text -> CostCategoryValues -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
Core..=)
              (CostCategoryValues -> Pair)
-> Maybe CostCategoryValues -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
Prelude.<$> Maybe CostCategoryValues
costCategories,
            (Text
"Dimensions" Text -> DimensionValues -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
Core..=) (DimensionValues -> Pair) -> Maybe DimensionValues -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
Prelude.<$> Maybe DimensionValues
dimensions,
            (Text
"Tags" Text -> TagValues -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
Core..=) (TagValues -> Pair) -> Maybe TagValues -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
Prelude.<$> Maybe TagValues
tags
          ]
      )