1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.statistics.examples.distribution;
18
19 import java.util.List;
20 import java.util.concurrent.Callable;
21 import org.apache.commons.statistics.distribution.DiscreteDistribution;
22 import picocli.CommandLine.Mixin;
23
24 /**
25 * Base command for a discrete distribution.
26 *
27 * <p>Sub-classes are assumed to have a name that corresponds to the command to action.
28 * Typically this is a function value in the {@link DistributionFunction} enum. The
29 * distribution will be evaluated for this function using the points defined by the
30 * {@link DistributionOptions}.
31 *
32 * <p>Alternatively the sub-class name may indicate a special command to execute.
33 *
34 * <p>Sub-classes must provide the list of distributions to evaluate and options for the
35 * evaluation.
36 */
37 abstract class AbstractDiscreteDistributionCommand implements Callable<Void> {
38 /** The standard options. */
39 @Mixin
40 private StandardOptions standardOptions;
41
42 @Override
43 public Void call() {
44 final List<Distribution<DiscreteDistribution>> distributions = getDistributions();
45 final DistributionOptions distributionOptions = getDistributionOptions();
46 // Set the function based on the class name
47 final String name = getClass().getSimpleName();
48
49 // Special handling of sub-classes which do not evaluate a function of the distribution.
50 // This is done here to avoid duplicating an overridden 'call()' method for each instance.
51 // Currently this applies to a hidden 'check' command that performs verification checks
52 // on the distribution.
53 if ("Check".equals(name)) {
54 // This is not an evaluation of a single function.
55 DistributionUtils.check(distributions,
56 (DiscreteDistributionOptions) distributionOptions);
57 return null;
58 }
59
60 // Assume an evaluation of a distribution function
61 distributionOptions.distributionFunction = DistributionFunction.valueOf(name);
62 // Assume there are only two types of options:
63 // Forward functions: x (int) -> p-value
64 // Inverse functions: p-value -> x (int)
65 if (distributionOptions instanceof InverseDiscreteDistributionOptions) {
66 DistributionUtils.evaluate(distributions,
67 (InverseDiscreteDistributionOptions) distributionOptions);
68 } else {
69 DistributionUtils.evaluate(distributions,
70 (DiscreteDistributionOptions) distributionOptions);
71 }
72 return null;
73 }
74
75 /**
76 * Gets the distributions to evaluate.
77 *
78 * @return the distributions
79 */
80 protected abstract List<Distribution<DiscreteDistribution>> getDistributions();
81
82 /**
83 * Gets the distribution options.
84 * This will define the points to evaluate, and the output options.
85 *
86 * @return the distribution options
87 */
88 protected abstract DistributionOptions getDistributionOptions();
89 }