KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > dataview > dvmodeler > CayenneProject


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56
57 package org.objectstyle.cayenne.dataview.dvmodeler;
58
59 import java.io.BufferedWriter JavaDoc;
60 import java.io.File JavaDoc;
61 import java.io.FileOutputStream JavaDoc;
62 import java.io.IOException JavaDoc;
63 import java.io.OutputStreamWriter JavaDoc;
64 import java.util.ArrayList JavaDoc;
65 import java.util.Collections JavaDoc;
66 import java.util.HashMap JavaDoc;
67 import java.util.HashSet JavaDoc;
68 import java.util.Iterator JavaDoc;
69 import java.util.List JavaDoc;
70 import java.util.Map JavaDoc;
71 import java.util.Set JavaDoc;
72 import java.util.TreeMap JavaDoc;
73
74 import org.jdom.Document;
75 import org.jdom.Element;
76 import org.jdom.JDOMException;
77 import org.jdom.input.SAXBuilder;
78 import org.jdom.output.Format;
79 import org.jdom.output.XMLOutputter;
80
81 /**
82  * This class defines cayenne project.
83  *
84  * @author Andriy Shapochka
85  * @author Nataliya Kholodna
86  * @version 1.0
87  */

88
89 public class CayenneProject {
90
91     public static String JavaDoc DATAVIEW_FILE_SUFFIX = ".view.xml";
92     private File JavaDoc projectFile;
93     private File JavaDoc projectDirectory;
94     private Document projectDocument;
95     private List JavaDoc dataMaps = new ArrayList JavaDoc();
96     private List JavaDoc readOnlyDataMaps = Collections.unmodifiableList(dataMaps);
97     private List JavaDoc dataViews = new ArrayList JavaDoc();
98     private Map JavaDoc objEntityMap = new TreeMap JavaDoc();
99     private Map JavaDoc fieldLookupsTemp = new HashMap JavaDoc();
100     private ObjEntity[] objEntities;
101     private List JavaDoc loadErrors = new ArrayList JavaDoc();
102     private List JavaDoc saveErrors = new ArrayList JavaDoc();
103     private Map JavaDoc dataViewsElements = new HashMap JavaDoc();
104     private Set JavaDoc objEntitiesNames = new HashSet JavaDoc();
105     private Set JavaDoc objEntityViewsNames = new HashSet JavaDoc();
106
107     public CayenneProject(File JavaDoc projectFile) throws DVModelerException {
108         if (projectFile == null || !projectFile.isFile() || !projectFile.canRead())
109             throw new IllegalArgumentException JavaDoc(projectFile + " is invalid.");
110
111         this.projectFile = projectFile;
112         projectDirectory = projectFile.getParentFile();
113
114         load();
115     }
116
117     /* reterns project directory */
118     public File JavaDoc getProjectDirectory() {
119         return projectDirectory;
120     }
121
122     public List JavaDoc getLoadErrors() {
123         return Collections.unmodifiableList(loadErrors);
124     }
125
126     public List JavaDoc getSaveErrors() {
127         return Collections.unmodifiableList(saveErrors);
128     }
129
130     public List JavaDoc getDataMaps() {
131         return readOnlyDataMaps;
132     }
133
134     public List JavaDoc getDataViews() {
135         return dataViews;
136     }
137
138     public ObjEntity[] getObjEntities() {
139         return objEntities;
140     }
141
142     public void buildDataViewsElements() {
143         if (saveErrors.size() != 0) {
144             saveErrors.clear();
145         }
146         for (Iterator JavaDoc i = dataViews.iterator(); i.hasNext();) {
147             DataView dataView = (DataView) i.next();
148             String JavaDoc dataViewName = dataView.getName();
149             String JavaDoc location = dataView.getFile().getName();
150             List JavaDoc builtDataViews = dataViews.subList(0, dataViews.indexOf(dataView));
151             for (Iterator JavaDoc itr = builtDataViews.iterator(); itr.hasNext();) {
152                 DataView nextDataView = (DataView) itr.next();
153                 if (nextDataView.getName().equalsIgnoreCase(dataViewName)) {
154                     if (!nextDataView.getFile().getName().equalsIgnoreCase(location)) {
155                         saveErrors.add("<b>"
156                                 + dataViewName
157                                 + "</b><br>"
158                                 + "Data View names must be unique<br><br>");
159                         break;
160                     }
161                     else {
162                         saveErrors
163                                 .add("<font color = \"red\" ><b>"
164                                         + dataViewName
165                                         + "</b><br>"
166                                         + "Data View names and file locations must be unique</font><br><br>");
167                         break;
168                     }
169                 }
170                 else {
171                     if (nextDataView.getFile().getName().equalsIgnoreCase(location)) {
172                         saveErrors.add("<font color = \"red\" ><b>"
173                                 + dataViewName
174                                 + "</b><br>"
175                                 + "and \""
176                                 + nextDataView
177                                 + "\" have the same file location.</font><br><br>");
178                     }
179                 }
180             }
181             Element dataViewRoot = dataView.getDataViewElement();
182             dataViewsElements.put(dataView, dataViewRoot);
183
184             List JavaDoc views = dataView.getObjEntityViews();
185             for (Iterator JavaDoc j = views.iterator(); j.hasNext();) {
186                 ObjEntityView view = (ObjEntityView) j.next();
187                 if (objEntityViewsNames.add(view.getName()) == false) {
188                     String JavaDoc path = "<b>" + dataView + "." + view + "</b><br>";
189                     saveErrors.add(path
190                             + " ObjEntity View \""
191                             + view
192                             + "\" already exists in the Cayenne project<br><br>");
193                 }
194
195             }
196
197             saveErrors.addAll(dataView.getSaveErrors());
198         }
199         objEntityViewsNames.clear();
200     }
201
202     public void save() throws IOException JavaDoc {
203         Element root = projectDocument.getRootElement();
204         List JavaDoc views = root.getChildren("view");
205         views.clear();
206         XMLOutputter out = new XMLOutputter();
207         out.setFormat(Format.getPrettyFormat());
208
209         Set JavaDoc dataViewsElementsKeys = dataViewsElements.keySet();
210         for (Iterator JavaDoc i = dataViewsElementsKeys.iterator(); i.hasNext();) {
211             DataView dataView = (DataView) i.next();
212             String JavaDoc dataViewName = dataView.getName();
213             File JavaDoc dataViewFile = dataView.getFile();
214             Element dataViewRoot = (Element) dataViewsElements.get(dataView);
215             Document dataViewDocument = new Document(dataViewRoot);
216
217             if (dataViewFile == null) {
218                 dataViewFile = new File JavaDoc(projectDirectory, dataViewName
219                         + CayenneProject.DATAVIEW_FILE_SUFFIX);
220                 dataView.setFile(dataViewFile);
221             }
222
223             if (!dataViewFile.exists()) {
224                 dataViewFile.createNewFile();
225             }
226
227             if (dataViewFile.isFile() && dataViewFile.canWrite()) {
228                 // must encode as UTF-8 - a default used by all Cayenne XML files
229
OutputStreamWriter JavaDoc dataViewFileWriter = new OutputStreamWriter JavaDoc(
230                         new FileOutputStream JavaDoc(dataViewFile),
231                         "UTF-8");
232
233                 BufferedWriter JavaDoc dataViewWriter = new BufferedWriter JavaDoc(dataViewFileWriter);
234                 out.output(dataViewDocument, dataViewWriter);
235                 dataViewWriter.close();
236                 Element viewElement = new Element("view");
237                 viewElement.setAttribute("name", dataViewName);
238                 viewElement.setAttribute("location", dataViewFile.getName());
239                 views.add(viewElement);
240             }
241             else {
242                 throw new IOException JavaDoc("Cannot save data view "
243                         + dataViewName
244                         + "to file "
245                         + dataViewFile);
246             }
247         }
248
249         // must encode as UTF-8 - a default used by all Cayenne XML files
250
OutputStreamWriter JavaDoc fw = new OutputStreamWriter JavaDoc(
251                 new FileOutputStream JavaDoc(projectFile),
252                 "UTF-8");
253
254         out.output(projectDocument, fw);
255         fw.close();
256     }
257
258     public ObjEntity getObjEntity(String JavaDoc name) {
259         return (ObjEntity) objEntityMap.get(name);
260     }
261
262     public DataView createDataView() {
263         String JavaDoc nameRoot = "dataview";
264         String JavaDoc name = nameRoot;
265         for (int i = 0; i < Integer.MAX_VALUE; i++) {
266             name = nameRoot + i;
267             boolean nameExists = false;
268             for (int j = 0; j < dataViews.size(); j++) {
269                 DataView dataView = (DataView) dataViews.get(j);
270                 nameExists = name.equalsIgnoreCase(dataView.getName());
271                 if (nameExists)
272                     break;
273             }
274             if (!nameExists)
275                 break;
276         }
277         DataView dataView = new DataView(this);
278         dataView.setName(name);
279         File JavaDoc file = dataView.getFile();
280         File JavaDoc newFile = new File JavaDoc(file.getParentFile(), name + ".view.xml");
281         dataView.setFile(newFile);
282
283         dataViews.add(dataView);
284         return dataView;
285     }
286
287     public Map JavaDoc removeDataView(DataView dataView) {
288         Map JavaDoc removingObjEntityViews = new HashMap JavaDoc();
289         for (Iterator JavaDoc j = dataView.getObjEntityViews().iterator(); j.hasNext();) {
290             ObjEntityView view = (ObjEntityView) j.next();
291             ObjEntity entity = view.getObjEntity();
292             if (entity != null) {
293                 removingObjEntityViews.put(view, new Integer JavaDoc(entity
294                         .getIndexOfObjEntityView(view)));
295
296                 entity.removeObjEntityView(view);
297             }
298         }
299         dataViews.remove(dataView);
300         return removingObjEntityViews;
301     }
302
303     private void load() throws DVModelerException {
304         SAXBuilder builder = new SAXBuilder();
305         try {
306             projectDocument = builder.build(projectFile);
307         }
308         catch (JDOMException ex) {
309             throw new DVModelerException("Failed to parse Cayenne project file: "
310                     + projectFile, ex);
311         }
312         catch (IOException JavaDoc ex) {
313             throw new DVModelerException("Failed to parse Cayenne project file: "
314                     + projectFile, ex);
315         }
316
317         Element root = projectDocument.getRootElement();
318         if (!"domains".equals(root.getName()))
319             throw new DVModelerException("Root element "
320                     + root.getName()
321                     + " is invalid, file: "
322                     + projectFile);
323
324         List JavaDoc domains = root.getChildren("domain");
325         for (Iterator JavaDoc i = domains.iterator(); i.hasNext();) {
326             Element domain = (Element) i.next();
327
328             List JavaDoc maps = domain.getChildren("map");
329             for (Iterator JavaDoc j = maps.iterator(); j.hasNext();) {
330                 Element map = (Element) j.next();
331                 String JavaDoc name = map.getAttributeValue("name");
332                 String JavaDoc location = map.getAttributeValue("location");
333                 boolean loading = true;
334                 for (Iterator JavaDoc itr = dataMaps.iterator(); itr.hasNext();) {
335                     DataMap nextDataMap = (DataMap) itr.next();
336                     if (nextDataMap.getName().equalsIgnoreCase(name)) {
337                         if (!nextDataMap.getFile().getName().equalsIgnoreCase(location)) {
338                             loadErrors.add("<b>"
339                                     + name
340                                     + "</b><br>"
341                                     + "Data Map with this name already exists"
342                                     + " in the Cayenne project<br><br>");
343                             break;
344                         }
345                         else {
346                             loading = false;
347                             break;
348                         }
349                     }
350                 }
351                 if (loading == true) {
352                     loadDataMap(name, location);
353                 }
354             }
355             objEntities = (ObjEntity[]) objEntityMap.values().toArray(new ObjEntity[] {});
356         }
357         objEntitiesNames.clear();
358
359         List JavaDoc views = root.getChildren("view");
360         for (Iterator JavaDoc j = views.iterator(); j.hasNext();) {
361             Element view = (Element) j.next();
362             String JavaDoc name = view.getAttributeValue("name");
363             String JavaDoc location = view.getAttributeValue("location");
364             boolean loading = true;
365             for (Iterator JavaDoc itr = dataViews.iterator(); itr.hasNext();) {
366                 DataView nextDataView = (DataView) itr.next();
367                 if (nextDataView.getName().equalsIgnoreCase(name)) {
368                     if (!nextDataView.getFile().getName().equalsIgnoreCase(location)) {
369                         loadErrors.add("<b>"
370                                 + name
371                                 + "</b><br>"
372                                 + "Data View with this name already exists"
373                                 + " in the Cayenne project<br><br>");
374                         break;
375                     }
376                     else {
377                         loading = false;
378                         break;
379                     }
380                 }
381             }
382             if (loading == true) {
383                 loadDataView(name, location);
384             }
385         }
386         objEntityViewsNames.clear();
387
388         Set JavaDoc keysTemp = fieldLookupsTemp.keySet();
389         for (Iterator JavaDoc j = keysTemp.iterator(); j.hasNext();) {
390             ObjEntityViewField field = (ObjEntityViewField) j.next();
391             ObjEntityView fieldView = field.getObjEntityView();
392             DataView fieldDataView = fieldView.getDataView();
393             String JavaDoc fieldPath = "<b>" + fieldDataView + "." + fieldView + "</b><br>";
394
395             String JavaDoc[] lookupNames = (String JavaDoc[]) fieldLookupsTemp.get(field);
396             String JavaDoc lookupViewName = lookupNames[0];
397             String JavaDoc lookupFieldName = lookupNames[1];
398             ObjRelationship relationship = field.getObjRelationship();
399             ObjEntity targetObjEntity = relationship.getTargetObjEntity();
400             if (targetObjEntity != null) {
401                 for (Iterator JavaDoc itr = targetObjEntity.getObjEntityViews().iterator(); itr
402                         .hasNext();) {
403                     ObjEntityView view = (ObjEntityView) itr.next();
404                     if (view.getName().equals(lookupViewName)) {
405                         field.getLookup().setLookupObjEntityView(view);
406                         break;
407                     }
408                 }
409                 if (field.getLookup().getLookupObjEntityView() != null) {
410                     ObjEntityView lookupView = field.getLookup().getLookupObjEntityView();
411                     if (lookupFieldName != null) {
412                         for (Iterator JavaDoc k = lookupView.getObjEntityViewFields().iterator(); k
413                                 .hasNext();) {
414                             ObjEntityViewField lookupField = (ObjEntityViewField) k
415                                     .next();
416                             if (lookupField.getName().equals(lookupFieldName)) {
417                                 field.getLookup().setLookupField(lookupField);
418                                 break;
419                             }
420                         }
421                         if (field.getLookup().getLookupField() == null) {
422                             loadErrors.add(fieldPath
423                                     + " Lookup ObjEntity View \""
424                                     + lookupViewName
425                                     + "\" has no field with the name \""
426                                     + lookupFieldName
427                                     + "\"<br><br>");
428                         }
429                     }
430                     else {
431                         loadErrors.add(fieldPath
432                                 + " Lookup has no attribute \"field-name\"<br><br>");
433                     }
434                 }
435                 else {
436                     loadErrors.add(fieldPath
437                             + " ObjEntity target of the ObjRelationship \""
438                             + relationship.getName()
439                             + "\" has no ObjEntity View with the name \""
440                             + lookupViewName
441                             + "\"<br><br>");
442                 }
443
444             }
445             else {
446                 loadErrors.add(fieldPath
447                         + " ObjRelationship for the field (\""
448                         + relationship.getName()
449                         + "\") has no ObjEntity target<br><br>");
450             }
451         }
452
453         fieldLookupsTemp = null;
454     }
455
456     private void loadDataMap(String JavaDoc name, String JavaDoc location) throws DVModelerException {
457         File JavaDoc file = getFileInProjectDirectory(location);
458         if (file == null)
459             return;
460
461         SAXBuilder builder = new SAXBuilder();
462         Document doc;
463         try {
464             doc = builder.build(file);
465             Element elem = doc.getRootElement();
466             if (elem.getName().equals("data-map")) {
467                 String JavaDoc dataMapName = (name != null ? name : location);
468                 DataMap dataMap = new DataMap(this, dataMapName, file);
469                 dataMap.setName(dataMapName);
470                 List JavaDoc elements = elem.getChildren("obj-entity");
471                 Iterator JavaDoc it = elements.iterator();
472                 while (it.hasNext()) {
473                     try {
474                         Element element = (Element) it.next();
475                         ObjEntity entity = new ObjEntity(dataMap, element);
476                         if (objEntitiesNames.add(entity.getName()) == false) {
477                             String JavaDoc entityPath = "<b>"
478                                     + dataMap.getName()
479                                     + "."
480                                     + entity.getName()
481                                     + "</b><br>";
482                             loadErrors.add(entityPath
483                                     + "ObjEntity \""
484                                     + entity.getName()
485                                     + "\" already exists in the Cayenne project<br><br>");
486                         }
487                         loadErrors.addAll(entity.getLoadErrors());
488                         objEntityMap.put(entity.getName(), entity);
489
490                     }
491                     catch (DVModelerException ex) {
492                         loadErrors.add(ex.getMessage());
493                     }
494                 }
495                 elements = elem.getChildren("obj-relationship");
496                 it = elements.iterator();
497                 while (it.hasNext()) {
498                     Element element = (Element) it.next();
499                     ObjRelationship objRelationship = new ObjRelationship(
500                             dataMap,
501                             element);
502                     dataMap.addObjRelationship(objRelationship);
503                 }
504                 dataMaps.add(dataMap);
505             }
506         }
507         catch (JDOMException e) {
508             throw new DVModelerException("Failed to parse data map file: " + file, e);
509         }
510         catch (IOException JavaDoc ex) {
511             throw new DVModelerException("Failed to parse Cayennne project file: "
512                     + projectFile, ex);
513         }
514
515     }
516
517     private void loadDataView(String JavaDoc name, String JavaDoc location) throws DVModelerException {
518         File JavaDoc file = getFileInProjectDirectory(location);
519         if (file == null)
520             return;
521
522         SAXBuilder builder = new SAXBuilder();
523         Document doc;
524         try {
525             doc = builder.build(file);
526             Element elem = doc.getRootElement();
527             if (elem.getName().equals("data-view")) {
528                 String JavaDoc dataViewName = (name != null ? name : location);
529
530                 DataView dataView = new DataView(this, dataViewName, file);
531
532                 List JavaDoc elements = elem.getChildren("obj-entity-view");
533                 Iterator JavaDoc itr = elements.iterator();
534                 while (itr.hasNext()) {
535                     Element element = (Element) itr.next();
536                     ObjEntityView objEntityView = new ObjEntityView(
537                             this,
538                             dataView,
539                             element);
540                     if (objEntityViewsNames.add(objEntityView.getName()) == false) {
541                         String JavaDoc path = "<b>"
542                                 + dataView.getName()
543                                 + "."
544                                 + objEntityView.getName()
545                                 + "</b><br>";
546                         loadErrors.add(path
547                                 + "ObjEntity View \""
548                                 + objEntityView.getName()
549                                 + "\" already exists in the Cayenne project<br><br>");
550                     }
551                     loadErrors.addAll(objEntityView.getLoadErrors());
552                 }
553                 dataViews.add(dataView);
554             }
555         }
556         catch (JDOMException e) {
557             throw new DVModelerException("Failed to parse data view file: " + file, e);
558         }
559         catch (IOException JavaDoc ex) {
560             throw new DVModelerException("Failed to parse Cayenne project file: "
561                     + projectFile, ex);
562         }
563     }
564
565     private File JavaDoc getFileInProjectDirectory(String JavaDoc location) {
566         if (location == null)
567             return null;
568         File JavaDoc f = new File JavaDoc(projectDirectory, location);
569         if (f.isFile() && f.canRead())
570             return f;
571         else
572             return null;
573     }
574
575     /*
576      * This method is called from ObjEntityViewField constructor.
577      */

578     public void putFieldLookup(
579             ObjEntityViewField field,
580             String JavaDoc lookupViewName,
581             String JavaDoc lookupFieldName) {
582         fieldLookupsTemp.put(field, new String JavaDoc[] {
583                 lookupViewName, lookupFieldName
584         });
585     }
586
587 }
Popular Tags