1 | package tuffy.mln; |
2 | import java.io.BufferedWriter; |
3 | import java.io.File; |
4 | import java.io.FileInputStream; |
5 | import java.io.FileOutputStream; |
6 | import java.io.IOException; |
7 | import java.io.OutputStreamWriter; |
8 | import java.io.PipedInputStream; |
9 | import java.io.PipedOutputStream; |
10 | import java.io.Writer; |
11 | import java.util.HashSet; |
12 | |
13 | import org.postgresql.PGConnection; |
14 | |
15 | import tuffy.db.RDB; |
16 | import tuffy.util.Config; |
17 | import tuffy.util.ExceptionMan; |
18 | |
19 | /** |
20 | * A domain/type of constants; i.e., a subset of constants. |
21 | */ |
22 | public class Type { |
23 | |
24 | /** |
25 | * Built-in types |
26 | */ |
27 | public static Type Generic = new Type("_GENERIC"); |
28 | public static Type Float = new Type("_FLOAT"); |
29 | public static Type Integer = new Type("_INTEGER"); |
30 | public static Type String = new Type("_STRING"); |
31 | public static Type Bool = new Type("_BOOL"); |
32 | |
33 | private boolean isNonSymbolicType = false; |
34 | |
35 | private Type nonSymbolicType = null; |
36 | |
37 | /** |
38 | * See if this type is non-symbolic. |
39 | * "Non-symbolic" means that the value of this type is directly |
40 | * stored in the predicate table, whereas values of a "symbolic" (default) |
41 | * type are represented by unique IDs as per the symbol table. |
42 | * @return |
43 | */ |
44 | public boolean isNonSymbolicType(){ |
45 | return isNonSymbolicType; |
46 | } |
47 | |
48 | public Type getNonSymbolicType(){ |
49 | return nonSymbolicType; |
50 | } |
51 | |
52 | public String getNonSymbolicTypeInSQL(){ |
53 | if(nonSymbolicType.name.equals("_FLOAT")){ |
54 | return "float"; |
55 | }else if (nonSymbolicType.name.equals("_STRING")){ |
56 | return "string"; |
57 | }else if (nonSymbolicType.name.equals("_INTEGER")){ |
58 | return "integer"; |
59 | }else if (nonSymbolicType.name.equals("_BOOL")){ |
60 | return "boolean"; |
61 | }else{ |
62 | return null; |
63 | } |
64 | } |
65 | |
66 | /** |
67 | * The domain of variable values. The members of a domain are |
68 | * named as integer. |
69 | */ |
70 | private HashSet<Integer> domain = new HashSet<Integer>(); |
71 | |
72 | /** |
73 | * Name of this Type. |
74 | */ |
75 | public String name; |
76 | |
77 | /** |
78 | * Name of the relational table corresponding to this type. |
79 | * Here it is type_$name. |
80 | */ |
81 | private String relName; |
82 | |
83 | public boolean isProbArg = false; |
84 | |
85 | /** |
86 | * Constructor of Type. |
87 | * |
88 | * @param name the name of this new type; it must be unique among all types |
89 | */ |
90 | public Type(String name){ |
91 | this.name = name; |
92 | relName = "type_" + name; |
93 | |
94 | if(name.endsWith("_")){ |
95 | isNonSymbolicType = true; |
96 | if(name.toLowerCase().startsWith("float")){ |
97 | nonSymbolicType = Float; |
98 | }else if(name.toLowerCase().startsWith("double")){ |
99 | nonSymbolicType = Float; |
100 | }else if(name.toLowerCase().startsWith("int")){ |
101 | nonSymbolicType = Integer; |
102 | }else{ |
103 | isNonSymbolicType = false; |
104 | } |
105 | } |
106 | |
107 | if(name.endsWith("_p_")){ |
108 | this.isProbArg = true; |
109 | } |
110 | |
111 | } |
112 | |
113 | /** |
114 | * Return the name of the DB relational table of this type. |
115 | */ |
116 | public String getRelName(){ |
117 | return relName; |
118 | } |
119 | |
120 | /** |
121 | * Store the list of constants in a DB table. |
122 | * |
123 | * @param db |
124 | */ |
125 | public void storeConstantList(RDB db, boolean... onlyNonEmptyDomain){ |
126 | |
127 | if(onlyNonEmptyDomain.length>0 && onlyNonEmptyDomain[0] == true && domain.size() == 0){ |
128 | return; |
129 | } |
130 | |
131 | String sql; |
132 | |
133 | if(onlyNonEmptyDomain.length == 0){ |
134 | db.dropTable(relName); |
135 | //String sql = "CREATE TEMPORARY TABLE " + relName + "(constantID INTEGER)\n"; |
136 | sql = "CREATE TABLE " + relName + "(constantID bigint, constantVALUE TEXT)\n"; |
137 | db.update(sql); |
138 | } |
139 | |
140 | |
141 | BufferedWriter writer = null; |
142 | File loadingFile = new File(Config.getLoadingDir(), "loading_type_" + name); |
143 | try { |
144 | writer = new BufferedWriter(new OutputStreamWriter |
145 | (new FileOutputStream(loadingFile),"UTF8")); |
146 | for(int v : domain) { |
147 | writer.append(v + "\n"); |
148 | } |
149 | writer.close(); |
150 | |
151 | FileInputStream in = new FileInputStream(loadingFile); |
152 | PGConnection con = (PGConnection)db.getConnection(); |
153 | sql = "COPY " + relName + " (constantID) FROM STDIN "; |
154 | con.getCopyAPI().copyIn(sql, in); |
155 | in.close(); |
156 | |
157 | sql = "UPDATE " + relName + " SET constantVALUE = t1.string FROM " + Config.relConstants + " t1 WHERE t1.id = constantID AND constantVALUE IS NULL"; |
158 | db.execute(sql); |
159 | |
160 | //domain.clear(); |
161 | }catch(Exception e) { |
162 | ExceptionMan.handle(e); |
163 | } |
164 | |
165 | db.analyze(relName); |
166 | } |
167 | |
168 | /** |
169 | * Add a constant to this type. |
170 | * |
171 | * @param con the constant to be added |
172 | */ |
173 | public void addConstant(int con) { |
174 | domain.add(con); |
175 | } |
176 | |
177 | public HashSet<Integer> getDomain(){ |
178 | return domain; |
179 | } |
180 | |
181 | /** |
182 | * Return true if this type contains the constant x |
183 | */ |
184 | public boolean contains(int x){ |
185 | return domain.contains(x); |
186 | } |
187 | |
188 | /** |
189 | * Return the number of constants in this type domain. |
190 | */ |
191 | public int size(){ |
192 | RDB db = RDB.getRDBbyConfig(Config.db_schema); |
193 | int a = (int) db.countTuples(this.relName); |
194 | db.close(); |
195 | return a; |
196 | // return domain.size(); |
197 | } |
198 | |
199 | /** |
200 | * Return the name of this type. |
201 | */ |
202 | public String name(){ |
203 | return name; |
204 | } |
205 | } |