1 29 30 package com.genimen.djeneric.repository.util; 31 32 import java.io.BufferedInputStream ; 33 import java.io.IOException ; 34 import java.io.InputStream ; 35 import java.util.ArrayList ; 36 import java.util.HashMap ; 37 import java.util.Iterator ; 38 39 import javax.xml.parsers.DocumentBuilderFactory ; 40 import javax.xml.parsers.ParserConfigurationException ; 41 import javax.xml.transform.TransformerException ; 42 43 import org.apache.xpath.XPathAPI; 44 import org.w3c.dom.Document ; 45 import org.w3c.dom.Element ; 46 import org.w3c.dom.Node ; 47 import org.w3c.dom.NodeList ; 48 import org.w3c.dom.traversal.NodeIterator; 49 import org.xml.sax.InputSource ; 50 import org.xml.sax.SAXException ; 51 52 import com.genimen.djeneric.language.Messages; 53 import com.genimen.djeneric.repository.DjAssociation; 54 import com.genimen.djeneric.repository.DjExtent; 55 import com.genimen.djeneric.repository.DjList; 56 import com.genimen.djeneric.repository.DjObject; 57 import com.genimen.djeneric.repository.DjRelation; 58 import com.genimen.djeneric.repository.DjSession; 59 import com.genimen.djeneric.repository.DjUid; 60 import com.genimen.djeneric.repository.exceptions.CanNotDeleteException; 61 import com.genimen.djeneric.repository.exceptions.CatalogException; 62 import com.genimen.djeneric.repository.exceptions.DjenericException; 63 import com.genimen.djeneric.repository.exceptions.ObjectNotDefinedException; 64 import com.genimen.djeneric.structure.ExtentUsage; 65 import com.genimen.djeneric.structure.RelationUsage; 66 import com.genimen.djeneric.util.DjBase64; 67 import com.genimen.djeneric.util.DjLogger; 68 import com.genimen.djeneric.util.DjStatusDisplayer; 69 70 89 public class DjObjectImporter 90 { 91 DjSession _session; 92 DjList _created = new DjList(); 93 DjList _deleted = new DjList(); 94 DjList _updated = new DjList(); 95 HashMap _createdOids = new HashMap (); 96 Document _xmlDoc; 97 DjStatusDisplayer _statusDisplayer = null; 98 HashMap _uids; 99 HashMap _uidsReversed; 100 HashMap _objectidToExternalObject; 101 HashMap _structs; 102 DjUid[] _unresolved; 103 104 public DjObjectImporter(DjSession session) 105 { 106 _session = session; 107 } 108 109 public void load(InputStream stream, boolean mergeDetails) throws SAXException , IOException , 110 ParserConfigurationException , TransformerException , DjenericException 111 { 112 InputSource is = new InputSource (new BufferedInputStream (stream)); 113 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); 114 115 setStatus(Messages.getString("ObjectImporter.ParseInput")); 116 _xmlDoc = dfactory.newDocumentBuilder().parse(is); 117 118 _uids = getUids(); 119 _uidsReversed = getReversedMap(_uids); 120 _objectidToExternalObject = new HashMap (); 121 122 setStatus(Messages.getString("ObjectImporter.FetchStructures")); 123 _structs = getStructures(); 124 precreateObjects(mergeDetails); 125 } 126 127 public DjUid[] resolve() throws TransformerException , DjenericException 128 { 129 134 _unresolved = resolveUids(); 135 136 return _unresolved; 137 } 138 139 145 public HashMap getInteral2ExternalMapping() 146 { 147 return _objectidToExternalObject; 148 } 149 150 public void apply() throws TransformerException , DjenericException 151 { 152 if (resolveUids().length > 0) throw new ImportAbortedException("Not all external objects were resolved"); 153 154 157 updateProperties(); 158 setStatus(Messages.getString("ObjectImporter.completed")); 159 } 160 161 protected HashMap getReversedMap(HashMap uids) 162 { 163 HashMap result = new HashMap (uids.size()); 164 Iterator it = uids.keySet().iterator(); 165 while (it.hasNext()) 166 { 167 Object key = it.next(); 168 result.put(uids.get(key), key); 169 } 170 return result; 171 } 172 173 protected void updateProperties() throws TransformerException , DjenericException 174 { 175 NodeList lst = XPathAPI.selectNodeList(_xmlDoc, "/djenericexport/object"); 176 177 for (int i = 0; i < lst.getLength(); i++) 178 { 179 int pct = (int) (((double) i / (double) lst.getLength()) * 100); 180 if (i % 10 == 0) setStatus(Messages.getString("ObjectImporter.Import", String.valueOf(pct))); 181 182 Element object = (Element ) lst.item(i); 183 updateProperties(object); 184 } 185 } 186 187 protected void updateProperties(Element objectElement) throws DjenericException, TransformerException 188 { 189 Long objectid = new Long (objectElement.getAttribute("id")); 190 DjObject object = (DjObject) _objectidToExternalObject.get(objectid); 191 if (object == null) throw new DjenericException("Internal error: object with internal id " + objectid + " missing"); 192 193 NodeList lst = XPathAPI.selectNodeList(objectElement, "property"); 194 195 for (int i = 0; i < lst.getLength(); i++) 196 { 197 Element prop = (Element ) lst.item(i); 198 String name = prop.getAttribute("name"); 199 String type = prop.getAttribute("type"); 200 201 if ("uidptr".equals(type)) 202 { 203 Long id = new Long (prop.getFirstChild().getNodeValue()); 204 DjObject master = (DjObject) _objectidToExternalObject.get(id); 205 if (master == null) throw new DjenericException("Internal error: object with internal id " + id + " missing"); 206 207 object.set(name, master); 208 } 209 else if ("text".equals(type)) object.setString(name, prop.getFirstChild().getNodeValue()); 210 else if ("simple".equals(type)) object.setString(name, prop.getFirstChild().getNodeValue()); 211 else if ("byte".equals(type)) 212 { 213 String uu = prop.getFirstChild().getNodeValue(); 214 byte[] bytes = DjBase64.decode(uu); 215 object.setBytes(name, bytes); 216 } 217 } 218 if (object.isModified() && !_createdOids.containsKey(new Long (object.getObjectId()))) _updated.add(object); 219 } 220 221 protected void precreateObjects(boolean mergeDetails) throws TransformerException , DjenericException 222 { 223 NodeList lst = XPathAPI.selectNodeList(_xmlDoc, "/djenericexport/object"); 224 225 for (int i = 0; i < lst.getLength(); i++) 226 { 227 int pct = (int) (((double) i / (double) lst.getLength()) * 100); 228 if (i % 10 == 0) setStatus(Messages.getString("ObjectImporter.LoadAndCreate", String.valueOf(pct))); 229 Element object = (Element ) lst.item(i); 230 if ("true".equals(object.getAttribute("rootobject"))) 231 { 232 processRootObject(object, mergeDetails); 233 } 234 else 235 { 236 createOrLoadObject(object); 237 } 238 } 239 } 240 241 protected void createOrLoadObject(Element object) throws DjenericException 242 { 243 Long internalId = new Long (object.getAttribute("id")); 244 DjUid uid = (DjUid) _uids.get(internalId); 245 246 if (uid.getPropertyCount() == 0) 247 { 248 DjLogger.log("Warning: extent " + uid.getExtent().getName() + " had no UID defined at the time of export"); 249 DjLogger.log(" object will be created without checking for prior existence"); 250 createNewObject(object, internalId); 251 } 252 else 253 { 254 try 255 { 256 DjObject existingObject = _session.getObject(uid); 257 _objectidToExternalObject.put(internalId, existingObject); 258 } 259 catch (ObjectNotDefinedException onde) 260 { 261 createNewObject(object, internalId); 262 } 263 } 264 } 265 266 protected void createNewObject(Element object, Long internalId) throws DjenericException 267 { 268 DjObject newObject = _session.createObject(object.getAttribute("extent")); 269 _objectidToExternalObject.put(internalId, newObject); 270 _created.add(newObject); 271 _createdOids.put(new Long (newObject.getObjectId()), newObject); 272 } 273 274 protected void processRootObject(Element object, boolean mergeDetails) throws TransformerException , DjenericException 275 { 276 DjUid uid = createUid(object, _uids); 277 if (uid.getPropertyCount() == 0) 278 { 279 DjLogger.log("Warning: extent " + uid.getExtent().getName() + " had no UID defined at the time of export"); 280 DjLogger.log(" object will be created without checking for prior existence"); 281 Long internalId = new Long (object.getAttribute("id")); 282 createNewObject(object, internalId); 283 } 284 else 285 { 286 try 287 { 288 DjObject existingObject = _session.getObject(uid); 289 _objectidToExternalObject.put(new Long (object.getAttribute("id")), existingObject); 290 ExtentUsage structure = (ExtentUsage) _structs.get(new Long (object.getAttribute("structure"))); 291 if (structure == null) throw new CatalogException("Error in import structure; invalid structure ptr: " 292 + object.getAttribute("structure")); 293 294 if (!mergeDetails) cleanupDetails(existingObject, structure); 295 } 296 catch (ObjectNotDefinedException onde) 297 { 298 createOrLoadObject(object); 299 } 300 } 301 } 302 303 protected void cleanupDetails(DjObject existingObject, ExtentUsage structure) throws CanNotDeleteException, 304 DjenericException 305 { 306 for (int i = 0; i < structure.getDetailRelationCount(); i++) 307 { 308 RelationUsage relus = structure.getDetailRelation(i); 309 String relationName = relus.getRelation().getName(); 310 DjAssociation assoc = existingObject.getDetailAssociationByName(relationName, relus.getDetail().getExtent()); 311 DjList details = assoc.getObjects(); 312 for (int del = 0; del < details.size(); del++) 313 { 314 DjObject toBeCleaned = details.getDjenericObjectAt(del); 315 boolean mustDie = !_uidsReversed.containsKey(toBeCleaned.getUID()); 316 317 cleanupDetails(toBeCleaned, relus.getDetail()); 318 319 if (mustDie) 320 { 321 if (!toBeCleaned.isMarkedForDelete()) _deleted.add(toBeCleaned); 322 toBeCleaned.markForDelete(); 323 } 324 } 325 } 326 } 327 328 protected DjUid[] resolveUids() throws DjenericException 329 { 330 Iterator it = _uids.keySet().iterator(); 331 ArrayList unresolved = new ArrayList (); 332 333 while (it.hasNext()) 334 { 335 DjUid uid = (DjUid) _uids.get(it.next()); 336 337 if (!_objectidToExternalObject.containsKey(new Long (uid.getAssociatedObjectid()))) 338 { 339 try 340 { 341 DjObject object = _session.getObject(uid); 342 _objectidToExternalObject.put(new Long (uid.getAssociatedObjectid()), object); 343 } 344 catch (ObjectNotDefinedException onde) 345 { 346 unresolved.add(uid); 347 } 348 } 349 } 350 return (DjUid[]) unresolved.toArray(new DjUid[0]); 351 } 352 353 protected HashMap getUids() throws TransformerException , DjenericException 354 { 355 NodeList lst = XPathAPI.selectNodeList(_xmlDoc, "/djenericexport/uid"); 356 HashMap result = new HashMap (); 357 358 int uidCount = lst.getLength(); 359 for (int i = 0; i < uidCount; i++) 360 { 361 int pct = (int) (((double) i / (double) uidCount) * 100); 362 if (i % 10 == 0) setStatus(Messages.getString("ObjectImporter.FetchUids", String.valueOf(uidCount), String 363 .valueOf(pct))); 364 365 Element elem = (Element ) lst.item(i); 366 DjUid uid = createUid(elem, result); 367 result.put(new Long (uid.getAssociatedObjectid()), uid); 368 } 369 return result; 370 } 371 372 protected DjUid createUid(Element elem, HashMap existingUids) throws TransformerException , DjenericException 375 { 376 DjExtent extent = _session.getPersistenceManager().getExtent(elem.getAttribute("extent")); 377 DjUid uid = new DjUid(extent); 378 uid.setAssociatedObjectid(Long.parseLong(elem.getAttribute("id"))); 379 380 NodeList children = elem.getChildNodes(); 381 for (int i = 0; i < children.getLength(); i++) 382 { 383 Node child = children.item(i); 384 if (!(child instanceof Element )) continue; 385 386 Element childElement = (Element ) child; 387 String elementName = childElement.getNodeName(); 388 if ("property".equals(elementName)) 389 { 390 String name = childElement.getAttribute("name"); 391 String type = childElement.getAttribute("type"); 392 393 if (extent.getProperty(name).isPartOfUID()) 394 { 395 if ("uid".equals(type)) 396 { 397 NodeList nl = childElement.getChildNodes(); 398 Element u = null; 399 400 for (int x = 0; x < nl.getLength(); x++) 401 if (nl.item(x) instanceof Element ) 402 { 403 u = (Element ) nl.item(x); 404 break; 405 } 406 407 uid.setProperty(name, createUid(u, existingUids)); 408 } 409 if ("uidptr".equals(type)) 410 { 411 Long id = new Long (childElement.getFirstChild().getNodeValue()); 412 DjUid refuid = (DjUid) existingUids.get(id); 413 if (refuid == null) throw new CatalogException("Error in import structure: invalid uidptr: " + id); 414 415 uid.setProperty(name, refuid); 416 } 417 else if ("text".equals(type)) uid.setProperty(name, childElement.getFirstChild().getNodeValue()); 418 } 419 } 420 else if ("descr".equals(elementName)) 421 { 422 uid.setDescriptor(childElement.getFirstChild().getNodeValue()); 423 } 424 } 425 return uid; 426 } 427 428 protected HashMap getStructures() throws TransformerException , DjenericException 429 { 430 NodeIterator it = XPathAPI.selectNodeIterator(_xmlDoc, "/djenericexport/structure"); 431 HashMap result = new HashMap (); 432 433 Element elem = (Element ) it.nextNode(); 434 while (elem != null) 435 { 436 ExtentUsage struct = createStructure(elem); 437 result.put(new Long (elem.getAttribute("id")), struct); 438 elem = (Element ) it.nextNode(); 439 } 440 return result; 441 } 442 443 protected ExtentUsage createStructure(Element elem) throws TransformerException , DjenericException 444 { 445 ExtentUsage struct = new ExtentUsage(_session.getPersistenceManager().getExtent(elem.getAttribute("extent"))); 446 447 NodeIterator it = XPathAPI.selectNodeIterator(elem, "detail"); 448 449 Element detail = (Element ) it.nextNode(); 450 while (detail != null) 451 { 452 buildDetailStruct(struct, detail); 453 detail = (Element ) it.nextNode(); 454 } 455 456 return struct; 457 } 458 459 protected void buildDetailStruct(ExtentUsage master, Element detailElem) throws TransformerException , 460 DjenericException 461 { 462 DjExtent extent = _session.getPersistenceManager().getExtent(detailElem.getAttribute("extent")); 463 ExtentUsage detail = new ExtentUsage(extent); 464 String relationName = detailElem.getAttribute("relation"); 465 466 DjRelation relation = master.getExtent().getDetailRelation(relationName); 467 master.addDetail(detail, relation); 468 469 NodeIterator it = XPathAPI.selectNodeIterator(detailElem, "detail"); 471 472 detailElem = (Element ) it.nextNode(); 473 while (detailElem != null) 474 { 475 buildDetailStruct(detail, detailElem); 476 detailElem = (Element ) it.nextNode(); 477 } 478 } 479 480 protected void setStatus(String msg) 481 { 482 if (_statusDisplayer != null) _statusDisplayer.setStatusMessageNow(msg, true); 483 } 484 485 public DjList getCreated() 486 { 487 return _created; 488 } 489 490 public DjList getDeleted() 491 { 492 return _deleted; 493 } 494 495 public DjList getUpdated() 496 { 497 return _updated; 498 } 499 500 public DjStatusDisplayer getStatusDisplayer() 501 { 502 return _statusDisplayer; 503 } 504 505 public void setStatusDisplayer(DjStatusDisplayer statusDisplayer) 506 { 507 _statusDisplayer = statusDisplayer; 508 } 509 510 } 511 | Popular Tags |