| 1 | package PIANOS.datastructures; |
| 2 | |
| 3 | import PIANOS.exceptions.*; |
| 4 | import java.util.*; |
| 5 | import java.io.File; |
| 6 | import java.io.FileNotFoundException; |
| 7 | import java.util.StringTokenizer; |
| 8 | |
| 9 | |
| 10 | public class DistributionFactory{ |
| 11 | |
| 12 | private HashMap<String, DistributionSkeleton> userDistributions; |
| 13 | |
| 14 | |
| 15 | |
| 16 | public DistributionFactory (String name) throws MissingFunctionException, SyntaxException{ |
| 17 | |
| 18 | userDistributions = new HashMap<String, DistributionSkeleton>(); |
| 19 | |
| 20 | Scanner reader = null; |
| 21 | try{ |
| 22 | reader = new Scanner (new File (name)); |
| 23 | }catch (FileNotFoundException e){ |
| 24 | throw new MissingFunctionException ("The user defined function file could not be found!"); |
| 25 | // The file was not found |
| 26 | } |
| 27 | |
| 28 | StringTokenizer tokenizer; |
| 29 | String temp; |
| 30 | int count, index, line = 0, userParameters = 0; |
| 31 | |
| 32 | String nameOfFunction; |
| 33 | boolean[] type; |
| 34 | boolean hasGen; |
| 35 | |
| 36 | DistributionSkeleton skeleton; |
| 37 | |
| 38 | // Do as long as the first character in the line is '!' |
| 39 | while (reader.hasNextLine()){ |
| 40 | temp = reader.nextLine(); |
| 41 | |
| 42 | if (temp.length() > 0 && temp.charAt(0) != '!') |
| 43 | break; |
| 44 | |
| 45 | line++; |
| 46 | |
| 47 | if (temp.length() == 0) |
| 48 | continue; |
| 49 | |
| 50 | //Create a new StringTokenizer, tokens are sparated with '!', ' ' or ',' |
| 51 | tokenizer = new StringTokenizer (temp, " !"); |
| 52 | count = tokenizer.countTokens(); |
| 53 | |
| 54 | //Every line has to have at least 3 tokes: name, number of parameters and boolean value |
| 55 | count = count - 3; |
| 56 | if (count < 0) |
| 57 | //Line has less than 3 tokens... |
| 58 | throw new SyntaxException ("Syntax error has been detected in user defined function file \"" + name + "\"\nLine " + line + " does not have enough arguments."); |
| 59 | |
| 60 | //First token, the name of the function, is read |
| 61 | nameOfFunction = tokenizer.nextToken(); |
| 62 | nameOfFunction = nameOfFunction.toLowerCase(); |
| 63 | if (!nameOfFunction.startsWith("user_")) |
| 64 | throw new SyntaxException ("Syntax error has been detected in user defined function file \"" + name + "\"" |
| 65 | + "\n Line " + line + " has an incorrect function name. The function name needs to start with \"user_\""); |
| 66 | |
| 67 | //Second token, the number of parameters, is compared to total number of tokens |
| 68 | try{ |
| 69 | userParameters = Integer.parseInt(tokenizer.nextToken()); |
| 70 | }catch (NumberFormatException e){ |
| 71 | throw new SyntaxException ("Syntax error has been detected in user defined function file \"" + name + "\", line " + line |
| 72 | + "\nNumber of parameters field is not an integer."); |
| 73 | } |
| 74 | |
| 75 | if (count != userParameters) |
| 76 | //Oops... number of parameters and calculated number of parameters vary from eachother! |
| 77 | throw new SyntaxException ("Syntax error has been detected in user defined function file \"" + name + |
| 78 | "\"\nNumber of arguments does not corespond to number of parameters in line" + line); |
| 79 | |
| 80 | type = new boolean [count]; |
| 81 | index = 0; |
| 82 | |
| 83 | //Parameter types... |
| 84 | while (index < count){ |
| 85 | temp = tokenizer.nextToken(); |
| 86 | temp = temp.toLowerCase(); |
| 87 | if (temp.equals("integer")) |
| 88 | type[index] = true; |
| 89 | else if (temp.equals("real")) |
| 90 | type[index] = false; |
| 91 | else |
| 92 | //Syntax error in parameter type |
| 93 | throw new SyntaxException ("Syntax error has been detected in user defined function file \"" + name + |
| 94 | "\"\nLine " + line + " has an invalid parameter type."); |
| 95 | index++; |
| 96 | } |
| 97 | |
| 98 | //Last boolean value... |
| 99 | temp = tokenizer.nextToken(); |
| 100 | temp = temp.toLowerCase(); |
| 101 | if (temp.equals(".true.")) |
| 102 | hasGen = true; |
| 103 | else if (temp.equals(".false.")) |
| 104 | hasGen = false; |
| 105 | else |
| 106 | //Syntax error... |
| 107 | throw new SyntaxException ("Syntax error has been detected in user defined function file \"" + name + |
| 108 | "\"\nLine " + line + " has an invalid boolean value."); |
| 109 | |
| 110 | //Everything is fine, new skeleton is created |
| 111 | skeleton = new DistributionSkeleton (nameOfFunction, count, type, true, hasGen); |
| 112 | DistributionSkeleton check = null; |
| 113 | check = userDistributions.get(nameOfFunction); |
| 114 | if(check != null) |
| 115 | throw new SyntaxException ("User defined distribution '" + nameOfFunction + "' has been defined twice in the user defined distribution file!" |
| 116 | + "\nPlease remove the second definition."); |
| 117 | userDistributions.put(nameOfFunction, skeleton); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | public Distribution getDistribution (String name) throws MissingDistributionException{ |
| 122 | |
| 123 | name = name.toLowerCase(); |
| 124 | |
| 125 | if (name.equals("discrete_uniform")) |
| 126 | { |
| 127 | return new DiscreteUniformDistribution(); |
| 128 | } |
| 129 | else if (name.equals("binomial")) |
| 130 | { |
| 131 | return new BinomialDistribution(); |
| 132 | } |
| 133 | else if (name.equals("poisson")) |
| 134 | { |
| 135 | return new PoissonDistribution(); |
| 136 | } |
| 137 | else if (name.equals("continuous_uniform")) |
| 138 | { |
| 139 | return new ContinuousUniformDistribution(); |
| 140 | } |
| 141 | else if (name.equals("beta")) |
| 142 | { |
| 143 | return new BetaDistribution(); |
| 144 | } |
| 145 | |
| 146 | DistributionSkeleton skeleton = userDistributions.get(name); |
| 147 | if (skeleton == null) |
| 148 | throw new MissingDistributionException ("Could not find user-defined distribution called \"" + name + "\"."); |
| 149 | |
| 150 | return new UserDefinedDistribution (skeleton); |
| 151 | |
| 152 | } |
| 153 | |
| 154 | |
| 155 | } |