7 kumpf 1.6 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
31 mike 1.4 #include <fstream>
32 #include <Pegasus/Common/Exception.h>
33 #include <Pegasus/Common/FileSystem.h>
34 #include <Pegasus/Common/Exception.h>
35 #include "AssocClassTable.h"
36
37 PEGASUS_USING_STD;
38
39 PEGASUS_NAMESPACE_BEGIN
40
41 #define ASSOC_CLASS_NAME_INDEX 0
42 #define FROM_CLASS_NAME_INDEX 1
43 #define FROM_PROPERTY_NAME_INDEX 2
44 #define TO_CLASS_NAME_INDEX 3
45 #define TO_PROPERTY_NAME_INDEX 4
46 #define NUM_FIELDS 5
47
48 static inline Boolean _MatchNoCase(const String& x, const String& pattern)
49 {
50 return pattern.size() == 0 || String::equalNoCase(x, pattern);
51 }
52 mike 1.4
53 static String _Escape(const String& str)
54 {
55 String result;
56
57 for (Uint32 i = 0, n = str.size(); i < n; i++)
58 {
59 Char16 c = str[i];
60
61 switch (c)
62 {
63 case '\n':
64 result += "\\n";
65 break;
66
67 case '\r':
68 result += "\\r";
69 break;
70
71 case '\t':
72 result += "\\t";
73 mike 1.4 break;
74
75 case '\f':
76 result += "\\f";
77 break;
78
79 case '\\':
80 result += "\\\\";
81 break;
82
83 default:
84 result += c;
85 }
86 }
87
88 return result;
89 }
90
91 static String _Unescape(const String& str)
92 {
93 String result;
94 mike 1.4
95 for (Uint32 i = 0, n = str.size(); i < n; i++)
96 {
97 Char16 c = str[i];
98
99 if (c == '\\')
100 {
101 if (i + 1 == n)
102 break;
103
104 c = str[i + 1];
105
106 switch (c)
107 {
108 case 'n':
109 result += "\n";
110 break;
111
112 case 'r':
113 result += "\r";
114 break;
115 mike 1.4
116 case 't':
117 result += "\t";
118 break;
119
120 case 'f':
121 result += "\f";
122 break;
123
124 default:
125 result += c;
126 }
127
128 i++;
129 }
130 else
131 result += c;
132 }
133
134 return result;
135 }
136 mike 1.4
137 static Boolean _GetRecord(ifstream& is, Array<String>& fields)
138 {
139 fields.clear();
140 String line;
141
142 for (Uint32 i = 0; i < NUM_FIELDS; i++)
143 {
144 if (!GetLine(is, line))
145 return false;
146
147 fields.append(_Unescape(line));
148 }
149
150 // Skip the blank line:
151
152 if (!GetLine(is, line))
153 return false;
154
155 return true;
156 }
157 mike 1.4
158 static void _PutRecord(ofstream& os, Array<String>& fields)
159 {
160 for (Uint32 i = 0, n = fields.size(); i < n; i++)
161 os << _Escape(fields[i]) << endl;
162 os << endl;
163 }
164
165 void AssocClassTable::append(
166 PEGASUS_STD(ofstream)& os,
167 const String& assocClassName,
168 const String& fromClassName,
169 const String& fromPropertyName,
170 const String& toClassName,
171 const String& toPropertyName)
172 {
173 Array<String> fields;
174 fields.reserve(5);
175 fields.append(assocClassName);
176 fields.append(fromClassName);
177 fields.append(fromPropertyName);
178 mike 1.4 fields.append(toClassName);
179 fields.append(toPropertyName);
180
181 _PutRecord(os, fields);
182 }
183
184 void AssocClassTable::append(
185 const String& path,
186 const String& assocClassName,
187 const String& fromClassName,
188 const String& fromPropertyName,
189 const String& toClassName,
190 const String& toPropertyName)
191 {
192 // Open input file:
193
194 ofstream os;
195
196 if (!OpenAppend(os, path))
197 throw CannotOpenFile(path);
198
199 mike 1.4 // Insert the entry:
200
201 Array<String> fields;
202 fields.reserve(5);
203 fields.append(assocClassName);
204 fields.append(fromClassName);
205 fields.append(fromPropertyName);
206 fields.append(toClassName);
207 fields.append(toPropertyName);
208
209 _PutRecord(os, fields);
210 }
211
212 Boolean AssocClassTable::deleteAssociation(
213 const String& path,
214 const String& assocClassName)
215 {
216 // Open input file:
217
218 ifstream is;
219
220 mike 1.4 if (!Open(is, path))
221 return false;
222
223 // Open output file:
224
225 String tmpPath = path + ".tmp";
226 ofstream os;
227
228 if (!Open(os, tmpPath))
229 throw CannotOpenFile(tmpPath);
230
231 // Copy over all lines except ones with the given association instance name:
232
233 Array<String> fields;
234 Boolean found = false;
235
236 while (_GetRecord(is, fields))
237 {
238 if (assocClassName != fields[ASSOC_CLASS_NAME_INDEX])
239 {
240 _PutRecord(os, fields);
241 mike 1.4 found = true;
242 }
243 }
244
245 // Close both files:
246
247 is.close();
248 os.close();
249
250 // Remove orginal file:
251
252 if (!FileSystem::removeFile(path))
253 throw CannotRemoveFile(path);
254
255 // Rename back to original name:
256
257 if (!FileSystem::renameFile(tmpPath, path))
258 throw CannotRenameFile(path);
259
260 return found;
261 }
262 mike 1.4
263 Boolean AssocClassTable::getAssociatorNames(
264 const String& path,
265 const String& className,
266 const String& assocClass,
267 const String& resultClass,
268 const String& role,
269 const String& resultRole,
270 Array<String>& associatorNames)
271 {
272 // Open input file:
273
274 ifstream is;
275
276 if (!Open(is, path))
277 return false;
278
279 // For each line:
280
281 Array<String> fields;
282 Boolean found = false;
283 mike 1.4
284
285 while (_GetRecord(is, fields))
286 {
287 if (_MatchNoCase(className, fields[FROM_CLASS_NAME_INDEX]) &&
288 _MatchNoCase(fields[ASSOC_CLASS_NAME_INDEX], assocClass) &&
289 _MatchNoCase(fields[TO_CLASS_NAME_INDEX], resultClass) &&
290 _MatchNoCase(fields[FROM_PROPERTY_NAME_INDEX], role) &&
291 _MatchNoCase(fields[TO_PROPERTY_NAME_INDEX], resultRole))
292 {
293 associatorNames.append(fields[TO_CLASS_NAME_INDEX]);
294 found = true;
295 }
296 }
297
298 return found;
299 }
300
301 Boolean AssocClassTable::getReferenceNames(
302 const String& path,
303 const String& className,
304 mike 1.4 const String& resultClass,
305 const String& role,
306 Array<String>& referenceNames)
307 {
308 // Open input file:
309
310 ifstream is;
311
312 if (!Open(is, path))
313 return false;
314
315 // For each line:
316
317 Array<String> fields;
318 Boolean found = false;
319
320 while (_GetRecord(is, fields))
321 {
322 if (_MatchNoCase(className, fields[FROM_CLASS_NAME_INDEX]) &&
323 _MatchNoCase(fields[ASSOC_CLASS_NAME_INDEX], resultClass) &&
324 _MatchNoCase(fields[FROM_PROPERTY_NAME_INDEX], role))
325 mike 1.4 {
326 if (!Contains(referenceNames, fields[ASSOC_CLASS_NAME_INDEX]))
327 referenceNames.append(fields[ASSOC_CLASS_NAME_INDEX]);
328 found = true;
329 }
330 }
331
332 return found;
333 }
334
335 PEGASUS_NAMESPACE_END
|