updates for 0.9.4
[debian/openrocket] / src / net / sf / openrocket / motor / MotorDigest.java
1 package net.sf.openrocket.motor;
2
3 import java.io.UnsupportedEncodingException;
4 import java.security.MessageDigest;
5 import java.security.NoSuchAlgorithmException;
6
7 import net.sf.openrocket.util.TextUtil;
8
9 public class MotorDigest {
10         
11         private static final double EPSILON = 0.00000000001;
12         
13         public enum DataType {
14                 /** An array of time points at which data is available (in ms) */
15                 TIME_ARRAY(0, 1000),
16                 /** Mass data for a few specific points (normally initial and empty mass) (in 0.1g) */
17                 MASS_SPECIFIC(1, 10000),
18                 /** Mass per time (in 0.1g) */
19                 MASS_PER_TIME(2, 10000),
20                 /** CG position for a few specific points (normally initial and final CG) (in mm) */
21                 CG_SPECIFIC(3, 1000),
22                 /** CG position per time (in mm) */
23                 CG_PER_TIME(4, 1000),
24                 /** Thrust force per time (in mN) */
25                 FORCE_PER_TIME(5, 1000);
26
27                 private final int order;
28                 private final int multiplier;
29                 DataType(int order, int multiplier) {
30                         this.order = order;
31                         this.multiplier = multiplier;
32                 }
33                 public int getOrder() {
34                         return order;
35                 }
36                 public int getMultiplier() {
37                         return multiplier;
38                 }
39         }
40         
41
42         private final MessageDigest digest;
43         private boolean used = false;
44         private int lastOrder = -1;
45         
46         
47         public MotorDigest() {
48                 try {
49                         digest = MessageDigest.getInstance("MD5");
50                 } catch (NoSuchAlgorithmException e) {
51                         throw new IllegalStateException("MD5 digest not supported by JRE", e);
52                 }
53         }
54         
55         
56         public void update(DataType type, int ... values) {
57
58                 // Check for correct order
59                 if (lastOrder >= type.getOrder()) {
60                         throw new IllegalArgumentException("Called with type="+type+" order="+type.getOrder()+
61                                         " while lastOrder=" + lastOrder);
62                 }
63                 lastOrder = type.getOrder();
64                 
65                 // Digest the type
66                 digest.update(bytes(type.getOrder()));
67                 
68                 // Digest the data length
69                 digest.update(bytes(values.length));
70                 
71                 // Digest the values
72                 for (int v: values) {
73                         digest.update(bytes(v));
74                 }
75                 
76         }
77         
78         
79         private void update(DataType type, int multiplier, double ... values) {
80
81                 int[] intValues = new int[values.length];
82                 for (int i=0; i<values.length; i++) {
83                         double v = values[i];
84                         v = next(v);
85                         v *= multiplier;
86                         v = next(v);
87                         intValues[i] = (int) Math.round(v);
88                 }
89                 update(type, intValues);
90         }
91         
92         public void update(DataType type, double ... values) {
93                 update(type, type.getMultiplier(), values);
94         }
95         
96         private static double next(double v) {
97                 return v + Math.signum(v) * EPSILON;
98         }
99         
100         
101         public String getDigest() {
102                 if (used) {
103                         throw new IllegalStateException("MotorDigest already used");
104                 }
105                 used = true;
106                 byte[] result = digest.digest();
107                 return TextUtil.hexString(result);
108         }
109
110         
111         
112         private byte[] bytes(int value) {
113                 return new byte[] {
114                                 (byte) ((value>>>24) & 0xFF), (byte) ((value>>>16) & 0xFF),
115                                 (byte) ((value>>>8) & 0xFF), (byte) (value & 0xFF) 
116                 };
117         }
118
119         
120         
121         
122         public static String digestComment(String comment) {
123                 comment = comment.replaceAll("\\s+", " ").trim();
124                 
125                 MessageDigest digest;
126                 try {
127                         digest = MessageDigest.getInstance("MD5");
128                 } catch (NoSuchAlgorithmException e) {
129                         throw new IllegalStateException("MD5 digest not supported by JRE", e);
130                 }
131                 
132                 try {
133                         digest.update(comment.getBytes("UTF-8"));
134                 } catch (UnsupportedEncodingException e) {
135                         throw new IllegalStateException("UTF-8 encoding not supported by JRE", e);
136                 }
137
138                 return TextUtil.hexString(digest.digest());
139         }
140         
141 }