equal_expression.go raw

   1  // Copyright 2022-2025 The sacloud/iaas-api-go Authors
   2  //
   3  // Licensed under the Apache License, Version 2.0 (the "License");
   4  // you may not use this file except in compliance with the License.
   5  // You may obtain a copy of the License at
   6  //
   7  //      http://www.apache.org/licenses/LICENSE-2.0
   8  //
   9  // Unless required by applicable law or agreed to in writing, software
  10  // distributed under the License is distributed on an "AS IS" BASIS,
  11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12  // See the License for the specific language governing permissions and
  13  // limitations under the License.
  14  
  15  package search
  16  
  17  import (
  18  	"encoding/json"
  19  	"fmt"
  20  	"strings"
  21  	"time"
  22  )
  23  
  24  // EqualExpression Equalで比較する際の条件
  25  type EqualExpression struct {
  26  	Op         LogicalOperator
  27  	Conditions []interface{}
  28  }
  29  
  30  // PartialMatch 部分一致(Partial Match)かつAND条件を示すEqualFilterを作成
  31  //
  32  // AndEqualのエイリアス
  33  func PartialMatch(conditions ...string) *EqualExpression {
  34  	return AndEqual(conditions...)
  35  }
  36  
  37  // ExactMatch 完全一致(Partial Match)かつOR条件を示すEqualFilterを作成
  38  //
  39  // OrEqualのエイリアス
  40  func ExactMatch(conditions ...string) *EqualExpression {
  41  	var values []interface{}
  42  	for _, p := range conditions {
  43  		values = append(values, p)
  44  	}
  45  	return OrEqual(values...)
  46  }
  47  
  48  // AndEqual 部分一致(Partial Match)かつAND条件を示すEqualFilterを作成
  49  func AndEqual(conditions ...string) *EqualExpression {
  50  	var values []interface{}
  51  	for _, p := range conditions {
  52  		values = append(values, p)
  53  	}
  54  
  55  	return &EqualExpression{
  56  		Op:         OpAnd,
  57  		Conditions: values,
  58  	}
  59  }
  60  
  61  // OrEqual 完全一致(Exact Match)かつOR条件を示すEqualFilterを作成
  62  func OrEqual(conditions ...interface{}) *EqualExpression {
  63  	return &EqualExpression{
  64  		Op:         OpOr,
  65  		Conditions: conditions,
  66  	}
  67  }
  68  
  69  // TagsAndEqual タグのAND検索
  70  func TagsAndEqual(tags ...string) *EqualExpression {
  71  	return OrEqual(tags) // 配列のまま渡す
  72  }
  73  
  74  // MarshalJSON .
  75  func (eq *EqualExpression) MarshalJSON() ([]byte, error) {
  76  	var conditions []interface{}
  77  	for _, cond := range eq.Conditions {
  78  		var c interface{}
  79  		switch v := cond.(type) {
  80  		case time.Time:
  81  			c = v.Format(time.RFC3339)
  82  		case string:
  83  			c = escapeFilterString(v)
  84  		case int, int8, int16, int32, int64,
  85  			uint, uint8, uint16, uint32, uint64,
  86  			float32, float64:
  87  			c = fmt.Sprintf("%v", v)
  88  		default:
  89  			c = v
  90  		}
  91  		if c != nil {
  92  			conditions = append(conditions, c)
  93  		}
  94  	}
  95  
  96  	var value interface{}
  97  	switch eq.Op {
  98  	case OpOr:
  99  		value = conditions
 100  	case OpAnd:
 101  		var strConds []string
 102  		for _, c := range conditions {
 103  			strConds = append(strConds, c.(string)) // Note: OpAndで文字列以外の要素が指定された場合のことは考慮しない
 104  		}
 105  		value = strings.Join(strConds, "%20")
 106  	default:
 107  		return nil, fmt.Errorf("invalid search.LogicalOperator: %v", eq.Op)
 108  	}
 109  
 110  	return json.Marshal(value)
 111  }
 112