1 56 57 package org.objectstyle.cayenne.dataview.dvmodeler; 58 59 import java.io.BufferedWriter ; 60 import java.io.File ; 61 import java.io.FileOutputStream ; 62 import java.io.IOException ; 63 import java.io.OutputStreamWriter ; 64 import java.util.ArrayList ; 65 import java.util.Collections ; 66 import java.util.HashMap ; 67 import java.util.HashSet ; 68 import java.util.Iterator ; 69 import java.util.List ; 70 import java.util.Map ; 71 import java.util.Set ; 72 import java.util.TreeMap ; 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 88 89 public class CayenneProject { 90 91 public static String DATAVIEW_FILE_SUFFIX = ".view.xml"; 92 private File projectFile; 93 private File projectDirectory; 94 private Document projectDocument; 95 private List dataMaps = new ArrayList (); 96 private List readOnlyDataMaps = Collections.unmodifiableList(dataMaps); 97 private List dataViews = new ArrayList (); 98 private Map objEntityMap = new TreeMap (); 99 private Map fieldLookupsTemp = new HashMap (); 100 private ObjEntity[] objEntities; 101 private List loadErrors = new ArrayList (); 102 private List saveErrors = new ArrayList (); 103 private Map dataViewsElements = new HashMap (); 104 private Set objEntitiesNames = new HashSet (); 105 private Set objEntityViewsNames = new HashSet (); 106 107 public CayenneProject(File projectFile) throws DVModelerException { 108 if (projectFile == null || !projectFile.isFile() || !projectFile.canRead()) 109 throw new IllegalArgumentException (projectFile + " is invalid."); 110 111 this.projectFile = projectFile; 112 projectDirectory = projectFile.getParentFile(); 113 114 load(); 115 } 116 117 118 public File getProjectDirectory() { 119 return projectDirectory; 120 } 121 122 public List getLoadErrors() { 123 return Collections.unmodifiableList(loadErrors); 124 } 125 126 public List getSaveErrors() { 127 return Collections.unmodifiableList(saveErrors); 128 } 129 130 public List getDataMaps() { 131 return readOnlyDataMaps; 132 } 133 134 public List 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 i = dataViews.iterator(); i.hasNext();) { 147 DataView dataView = (DataView) i.next(); 148 String dataViewName = dataView.getName(); 149 String location = dataView.getFile().getName(); 150 List builtDataViews = dataViews.subList(0, dataViews.indexOf(dataView)); 151 for (Iterator 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 views = dataView.getObjEntityViews(); 185 for (Iterator j = views.iterator(); j.hasNext();) { 186 ObjEntityView view = (ObjEntityView) j.next(); 187 if (objEntityViewsNames.add(view.getName()) == false) { 188 String 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 { 203 Element root = projectDocument.getRootElement(); 204 List views = root.getChildren("view"); 205 views.clear(); 206 XMLOutputter out = new XMLOutputter(); 207 out.setFormat(Format.getPrettyFormat()); 208 209 Set dataViewsElementsKeys = dataViewsElements.keySet(); 210 for (Iterator i = dataViewsElementsKeys.iterator(); i.hasNext();) { 211 DataView dataView = (DataView) i.next(); 212 String dataViewName = dataView.getName(); 213 File 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 (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 OutputStreamWriter dataViewFileWriter = new OutputStreamWriter ( 230 new FileOutputStream (dataViewFile), 231 "UTF-8"); 232 233 BufferedWriter dataViewWriter = new BufferedWriter (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 ("Cannot save data view " 243 + dataViewName 244 + "to file " 245 + dataViewFile); 246 } 247 } 248 249 OutputStreamWriter fw = new OutputStreamWriter ( 251 new FileOutputStream (projectFile), 252 "UTF-8"); 253 254 out.output(projectDocument, fw); 255 fw.close(); 256 } 257 258 public ObjEntity getObjEntity(String name) { 259 return (ObjEntity) objEntityMap.get(name); 260 } 261 262 public DataView createDataView() { 263 String nameRoot = "dataview"; 264 String 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 file = dataView.getFile(); 280 File newFile = new File (file.getParentFile(), name + ".view.xml"); 281 dataView.setFile(newFile); 282 283 dataViews.add(dataView); 284 return dataView; 285 } 286 287 public Map removeDataView(DataView dataView) { 288 Map removingObjEntityViews = new HashMap (); 289 for (Iterator 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 (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 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 domains = root.getChildren("domain"); 325 for (Iterator i = domains.iterator(); i.hasNext();) { 326 Element domain = (Element) i.next(); 327 328 List maps = domain.getChildren("map"); 329 for (Iterator j = maps.iterator(); j.hasNext();) { 330 Element map = (Element) j.next(); 331 String name = map.getAttributeValue("name"); 332 String location = map.getAttributeValue("location"); 333 boolean loading = true; 334 for (Iterator 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 views = root.getChildren("view"); 360 for (Iterator j = views.iterator(); j.hasNext();) { 361 Element view = (Element) j.next(); 362 String name = view.getAttributeValue("name"); 363 String location = view.getAttributeValue("location"); 364 boolean loading = true; 365 for (Iterator 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 keysTemp = fieldLookupsTemp.keySet(); 389 for (Iterator j = keysTemp.iterator(); j.hasNext();) { 390 ObjEntityViewField field = (ObjEntityViewField) j.next(); 391 ObjEntityView fieldView = field.getObjEntityView(); 392 DataView fieldDataView = fieldView.getDataView(); 393 String fieldPath = "<b>" + fieldDataView + "." + fieldView + "</b><br>"; 394 395 String [] lookupNames = (String []) fieldLookupsTemp.get(field); 396 String lookupViewName = lookupNames[0]; 397 String lookupFieldName = lookupNames[1]; 398 ObjRelationship relationship = field.getObjRelationship(); 399 ObjEntity targetObjEntity = relationship.getTargetObjEntity(); 400 if (targetObjEntity != null) { 401 for (Iterator 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 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 name, String location) throws DVModelerException { 457 File 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 dataMapName = (name != null ? name : location); 468 DataMap dataMap = new DataMap(this, dataMapName, file); 469 dataMap.setName(dataMapName); 470 List elements = elem.getChildren("obj-entity"); 471 Iterator 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 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 ex) { 511 throw new DVModelerException("Failed to parse Cayennne project file: " 512 + projectFile, ex); 513 } 514 515 } 516 517 private void loadDataView(String name, String location) throws DVModelerException { 518 File 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 dataViewName = (name != null ? name : location); 529 530 DataView dataView = new DataView(this, dataViewName, file); 531 532 List elements = elem.getChildren("obj-entity-view"); 533 Iterator 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 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 ex) { 560 throw new DVModelerException("Failed to parse Cayenne project file: " 561 + projectFile, ex); 562 } 563 } 564 565 private File getFileInProjectDirectory(String location) { 566 if (location == null) 567 return null; 568 File f = new File (projectDirectory, location); 569 if (f.isFile() && f.canRead()) 570 return f; 571 else 572 return null; 573 } 574 575 578 public void putFieldLookup( 579 ObjEntityViewField field, 580 String lookupViewName, 581 String lookupFieldName) { 582 fieldLookupsTemp.put(field, new String [] { 583 lookupViewName, lookupFieldName 584 }); 585 } 586 587 } | Popular Tags |