storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/bucket/replication/filter.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2020 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package replication
    18  
    19  import (
    20  	"encoding/xml"
    21  )
    22  
    23  var (
    24  	errInvalidFilter = Errorf("Filter must have exactly one of Prefix, Tag, or And specified")
    25  )
    26  
    27  // Filter - a filter for a replication configuration Rule.
    28  type Filter struct {
    29  	XMLName xml.Name `xml:"Filter" json:"Filter"`
    30  	Prefix  string
    31  	And     And
    32  	Tag     Tag
    33  	// Caching tags, only once
    34  	cachedTags map[string]struct{}
    35  }
    36  
    37  // IsEmpty returns true if filter is not set
    38  func (f Filter) IsEmpty() bool {
    39  	return f.And.isEmpty() && f.Tag.IsEmpty() && f.Prefix == ""
    40  }
    41  
    42  // MarshalXML - produces the xml representation of the Filter struct
    43  // only one of Prefix, And and Tag should be present in the output.
    44  func (f Filter) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    45  	if err := e.EncodeToken(start); err != nil {
    46  		return err
    47  	}
    48  
    49  	switch {
    50  	case !f.And.isEmpty():
    51  		if err := e.EncodeElement(f.And, xml.StartElement{Name: xml.Name{Local: "And"}}); err != nil {
    52  			return err
    53  		}
    54  	case !f.Tag.IsEmpty():
    55  		if err := e.EncodeElement(f.Tag, xml.StartElement{Name: xml.Name{Local: "Tag"}}); err != nil {
    56  			return err
    57  		}
    58  	default:
    59  		// Always print Prefix field when both And & Tag are empty
    60  		if err := e.EncodeElement(f.Prefix, xml.StartElement{Name: xml.Name{Local: "Prefix"}}); err != nil {
    61  			return err
    62  		}
    63  	}
    64  
    65  	return e.EncodeToken(xml.EndElement{Name: start.Name})
    66  }
    67  
    68  // Validate - validates the filter element
    69  func (f Filter) Validate() error {
    70  	// A Filter must have exactly one of Prefix, Tag, or And specified.
    71  	if !f.And.isEmpty() {
    72  		if f.Prefix != "" {
    73  			return errInvalidFilter
    74  		}
    75  		if !f.Tag.IsEmpty() {
    76  			return errInvalidFilter
    77  		}
    78  		if err := f.And.Validate(); err != nil {
    79  			return err
    80  		}
    81  	}
    82  	if f.Prefix != "" {
    83  		if !f.Tag.IsEmpty() {
    84  			return errInvalidFilter
    85  		}
    86  	}
    87  	if !f.Tag.IsEmpty() {
    88  		if err := f.Tag.Validate(); err != nil {
    89  			return err
    90  		}
    91  	}
    92  	return nil
    93  }
    94  
    95  // TestTags tests if the object tags satisfy the Filter tags requirement,
    96  // it returns true if there is no tags in the underlying Filter.
    97  func (f *Filter) TestTags(ttags []string) bool {
    98  	if f.cachedTags == nil {
    99  		tags := make(map[string]struct{})
   100  		for _, t := range append(f.And.Tags, f.Tag) {
   101  			if !t.IsEmpty() {
   102  				tags[t.String()] = struct{}{}
   103  			}
   104  		}
   105  		f.cachedTags = tags
   106  	}
   107  	for ct := range f.cachedTags {
   108  		foundTag := false
   109  		for _, t := range ttags {
   110  			if ct == t {
   111  				foundTag = true
   112  				break
   113  			}
   114  		}
   115  		if !foundTag {
   116  			return false
   117  		}
   118  	}
   119  	return true
   120  }