001/* 002 * Copyright © 2025 CUI-OpenSource-Software (info@cuioss.de) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package de.cuioss.test.generator.internal.net.java.quickcheck.generator.support; 017 018import de.cuioss.test.generator.internal.net.java.quickcheck.FrequencyGenerator; 019import de.cuioss.test.generator.internal.net.java.quickcheck.Generator; 020 021import java.util.ArrayList; 022import java.util.List; 023import java.util.Objects; 024 025public class DefaultFrequencyGenerator<T> implements FrequencyGenerator<T> { 026 027 /** 028 * Weight used to generate equal weighted frequency generator. 029 */ 030 public static final int EQUAL_WEIGHT_OF_GENERATORS = 1; 031 032 private final List<Frequency<T>> frequencies = new ArrayList<>(); 033 private IntegerGenerator choose; 034 private int sum = 0; 035 036 public DefaultFrequencyGenerator(Generator<T> generator) { 037 this(generator, EQUAL_WEIGHT_OF_GENERATORS); 038 } 039 040 public DefaultFrequencyGenerator(Generator<T> generator, int weight) { 041 add(generator, weight); 042 } 043 044 @Override 045 public FrequencyGenerator<T> add(Generator<T> generator) { 046 return add(generator, EQUAL_WEIGHT_OF_GENERATORS); 047 } 048 049 @Override 050 public FrequencyGenerator<T> add(Generator<T> generator, int weight) { 051 Objects.requireNonNull(generator, "generator"); 052 if (EQUAL_WEIGHT_OF_GENERATORS > weight) { 053 throw new IllegalArgumentException("weight"); 054 } 055 056 this.frequencies.add(new Frequency<>(generator, weight)); 057 this.sum += weight; 058 this.choose = null; 059 return this; 060 } 061 062 @Override 063 public T next() { 064 if (1 > this.sum) { 065 throw new IllegalArgumentException("number of generators"); 066 } 067 068 int next = choose().nextInt(); 069 for (Frequency<T> pair : this.frequencies) { 070 int weight = pair.getWeight(); 071 if (next <= weight) { 072 return pair.getGenerator().next(); 073 } 074 next -= weight; 075 } 076 throw new IllegalStateException(); 077 } 078 079 private IntegerGenerator choose() { 080 if (this.choose == null) { 081 this.choose = new IntegerGenerator(1, this.sum); 082 } 083 return this.choose; 084 } 085 086 private static class Frequency<T> { 087 088 private final Generator<T> generator; 089 private final int weight; 090 091 private Frequency(Generator<T> generator, int weight) { 092 this.generator = generator; 093 this.weight = weight; 094 } 095 096 private Generator<T> getGenerator() { 097 return this.generator; 098 } 099 100 private int getWeight() { 101 return this.weight; 102 } 103 } 104}