1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package pl.edu.agh.cast.model.mapper.internal;
19
20 import java.io.BufferedOutputStream;
21 import java.io.BufferedWriter;
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.FileWriter;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.io.UnsupportedEncodingException;
28 import java.io.Writer;
29 import java.text.DateFormat;
30 import java.text.SimpleDateFormat;
31 import java.util.Date;
32
33 import org.eclipse.core.resources.IProject;
34
35 import pl.edu.agh.cast.model.base.BasePlugin;
36 import pl.edu.agh.cast.model.base.IDataSet;
37 import pl.edu.agh.cast.model.base.IModel;
38 import pl.edu.agh.cast.model.base.IRelation;
39 import pl.edu.agh.cast.model.mapper.Mappable;
40 import pl.edu.agh.cast.model.mapper.Mapper;
41 import pl.edu.agh.cast.resources.BaseProjectUtil;
42
43
44
45
46
47
48
49
50
51
52
53 public class XMLSaver extends AbstractSaver {
54
55
56
57
58 private static final String QUOTE_W_SPACE = "' ";
59
60
61
62
63 private static final String GT_W_NEW_LINE = ">\n";
64
65
66
67
68 private static final String LT_W_SLASH = "</";
69
70
71
72
73 private static final String GT_W_QUOTE_AND_NEW_LINE = "'>\n";
74
75
76
77
78 private static final String EQUAL_W_QUOTE = "='";
79
80
81
82
83 private static final String SINGLE_SPACE = " ";
84
85
86
87
88 private static final String LT = "<";
89
90
91
92
93 public static final String MODEL_PROPS = "project.props";
94
95 private static final String UTF_8 = "UTF-8";
96
97 private static final String ISO_8859_2 = "ISO-8859-2";
98
99 private static final String CP_1250 = "CP1250";
100
101
102
103
104 public static final String EXTENSION = ".xml";
105
106
107
108
109 public static final String ROOT = "model";
110
111
112
113
114 public static final String TYPE = "type";
115
116
117
118
119 public static final String ID = "id";
120
121
122
123
124 public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
125
126
127
128
129 public static final String SOURCE = "src";
130
131
132
133
134 public static final String TARGET = "dst";
135
136 private StringBuilder buffer = new StringBuilder();
137
138 private long lastId = 1;
139
140 private IProject project;
141
142 private OutputStream file;
143
144
145
146
147
148
149
150
151
152
153
154 public XMLSaver(Mappable object, boolean force, IProject project) {
155 super(object, force);
156 this.project = project;
157 }
158
159
160
161
162
163
164
165 public boolean save() {
166 try {
167 if (primaryObject instanceof IDataSet) {
168 IDataSet dataSet = (IDataSet)primaryObject;
169 saveModelProps(dataSet.getModel());
170 save(dataSet);
171 } else if (primaryObject instanceof IModel) {
172 saveModelProps((IModel)primaryObject);
173 for (IDataSet dataSet : ((IModel)primaryObject).getDataSets()) {
174 save(dataSet);
175 }
176 }
177 return true;
178 } catch (Exception e) {
179 e.printStackTrace();
180 return false;
181 }
182 }
183
184 private void saveModelProps(IModel model) throws IOException {
185 if (project != null) {
186 BaseProjectUtil.setProperty(project, BaseProjectUtil.PROJECT_ID_PROPERTY, model.getName());
187 } else {
188
189
190 Writer projectProps = new BufferedWriter(new FileWriter(dirFor(project) + MODEL_PROPS));
191 projectProps.write(model.getName());
192 projectProps.close();
193 }
194 }
195
196 private void save(IDataSet dataSet) throws Exception {
197 file = new BufferedOutputStream(new FileOutputStream(fileFor(project, dataSet.getId())));
198 buffer.append("<?xml version='1.0' ?>\n");
199 buffer.append(LT);
200 buffer.append(ROOT);
201 buffer.append(SINGLE_SPACE);
202 buffer.append(ID);
203 buffer.append(EQUAL_W_QUOTE);
204 buffer.append(dataSet.getModel().getId());
205 buffer.append(GT_W_QUOTE_AND_NEW_LINE);
206 store(null);
207 saveMappable(dataSet);
208 for (IRelation relation : dataSet.getRelations()) {
209 saveMappable(relation.getSource());
210 saveMappable(relation.getTarget());
211 saveRelation(relation);
212 }
213 buffer.append(LT_W_SLASH);
214 buffer.append(ROOT);
215 buffer.append(GT_W_NEW_LINE);
216 store(null);
217 file.close();
218 }
219
220
221
222
223
224
225
226
227 public static String dirFor(IProject project) {
228 String path = getProjectPath(project);
229 File dir = new File(path);
230 if (!dir.exists()) {
231 dir.mkdir();
232 }
233 if (!path.substring(path.length() - 1).equals(File.separator)) {
234 path += File.separator;
235 }
236 return path;
237 }
238
239
240
241
242
243
244
245
246
247
248 public static String fileFor(IProject project, String id) {
249
250 return dirFor(project) + id.replaceAll("[^a-zA-Z0-9_]", "_") + EXTENSION;
251 }
252
253 private static String getProjectPath(IProject project) {
254 if (project == null) {
255 return Mapper.DEFAULT_PATH;
256 } else {
257 return project.getLocation().toOSString() + File.separator + Mapper.DEFAULT_FOLDER;
258 }
259
260 }
261
262 private void saveMappable(Mappable mappable) throws Exception {
263 if (stored.contains(mappable)) {
264 return;
265 }
266 buffer.append(LT);
267 buffer.append(Helper.mappedTypeName(mappable.getClass()));
268 buffer.append(SINGLE_SPACE);
269 buffer.append(ID);
270 buffer.append(EQUAL_W_QUOTE);
271 mappable.setMid(lastId);
272 buffer.append(lastId++);
273 buffer.append(GT_W_QUOTE_AND_NEW_LINE);
274 appendAttributesXML(mappable, mappable.getClass());
275 buffer.append(LT_W_SLASH);
276 buffer.append(Helper.mappedTypeName(mappable.getClass()));
277 buffer.append(GT_W_NEW_LINE);
278 store(mappable);
279 }
280
281 private void saveRelation(IRelation relation) throws Exception {
282 if (stored.contains(relation)) {
283 return;
284 }
285 buffer.append(LT);
286 buffer.append(Helper.mappedTypeName(relation.getClass()));
287 buffer.append(SINGLE_SPACE);
288 buffer.append(ID);
289 buffer.append(EQUAL_W_QUOTE);
290 relation.setMid(lastId);
291 buffer.append(lastId++);
292 buffer.append(QUOTE_W_SPACE);
293 buffer.append(SOURCE);
294 buffer.append(EQUAL_W_QUOTE);
295 buffer.append(relation.getSource().getMid());
296 buffer.append(QUOTE_W_SPACE);
297 buffer.append(TARGET);
298 buffer.append(EQUAL_W_QUOTE);
299 buffer.append(relation.getTarget().getMid());
300 buffer.append(GT_W_QUOTE_AND_NEW_LINE);
301 appendAttributesXML(relation, relation.getClass());
302 buffer.append(LT_W_SLASH);
303 buffer.append(Helper.mappedTypeName(relation.getClass()));
304 buffer.append(GT_W_NEW_LINE);
305 store(relation);
306 }
307
308 private void store(Mappable mappable) throws IOException {
309
310 String value = buffer.toString();
311 buffer.setLength(0);
312 value = convertToUTF(value);
313 file.write(value.getBytes(UTF_8));
314 if (mappable != null) {
315 stored.add(mappable);
316 }
317 }
318
319 private String convertToUTF(String value) {
320 String valueCopy = value + "";
321 boolean shouldConvert = false;
322
323 boolean windowsEncoding = false;
324 for (byte byteValue : valueCopy.getBytes()) {
325 if (byteValue < 0) {
326 int code = 256 + byteValue;
327
328
329 if (code == 195 || code == 196 || code == 197 && !shouldConvert) {
330 break;
331 }
332
333 if (code == 191 || code == 243 || code == 179 || code == 230 || code == 234 || code == 241
334 || code == 175 || code == 211 || code == 163 || code == 198 || code == 202 || code == 209) {
335 shouldConvert = true;
336 }
337
338 if (code == 182 || code == 177 || code == 188 || code == 166 || code == 161 || code == 172) {
339 shouldConvert = true;
340 break;
341 }
342 if (code == 156 || code == 185 || code == 159 || code == 140 || code == 165 || code == 143) {
343 shouldConvert = true;
344 windowsEncoding = true;
345 break;
346 }
347 }
348 }
349 try {
350 if (shouldConvert) {
351 if (windowsEncoding) {
352 valueCopy = new String(value.getBytes(), CP_1250);
353 } else {
354 valueCopy = new String(value.getBytes(), ISO_8859_2);
355 }
356 }
357 } catch (UnsupportedEncodingException ex) {
358 BasePlugin.getLogger().error("Cannot save file as UTF", ex);
359 return valueCopy;
360 }
361 return valueCopy;
362 }
363
364 private void appendAttributesXML(Mappable mappable, Class klass) throws Exception {
365 if (Helper.isSuperMapped(klass)) {
366 appendAttributesXML(mappable, klass.getSuperclass());
367 }
368 for (AttributeEntry entry : Helper.getMappedAttributes(klass)) {
369 Object value = entry.getMethod().invoke(mappable);
370 String attributeName = entry.getAnnotation().name();
371 if (attributeName.equals("")) {
372 attributeName = entry.getMethod().getName();
373 }
374 buffer.append(LT);
375 buffer.append(attributeName);
376 buffer.append(SINGLE_SPACE);
377 buffer.append(TYPE);
378 buffer.append(EQUAL_W_QUOTE);
379 buffer.append(entry.getMethod().getReturnType().getCanonicalName());
380 buffer.append("'>");
381 if (value instanceof Date) {
382 buffer.append(DATE_FORMAT.format((Date)value));
383 } else {
384 buffer.append(value);
385 }
386 buffer.append(LT_W_SLASH);
387 buffer.append(attributeName);
388 buffer.append(GT_W_NEW_LINE);
389 }
390 }
391 }