1 17 package org.alfresco.service.cmr.repository; 18 19 import java.io.Serializable ; 20 import java.io.StringReader ; 21 import java.io.UnsupportedEncodingException ; 22 import java.net.URLEncoder ; 23 import java.text.MessageFormat ; 24 import java.util.ArrayList ; 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.Set ; 28 29 import org.alfresco.model.ContentModel; 30 import org.alfresco.repo.security.permissions.AccessDeniedException; 31 import org.alfresco.repo.template.LuceneSearchResultsMap; 32 import org.alfresco.repo.template.NamePathResultsMap; 33 import org.alfresco.repo.template.SavedSearchResultsMap; 34 import org.alfresco.repo.template.XPathResultsMap; 35 import org.alfresco.service.ServiceRegistry; 36 import org.alfresco.service.cmr.dictionary.DictionaryService; 37 import org.alfresco.service.cmr.lock.LockStatus; 38 import org.alfresco.service.namespace.QName; 39 import org.alfresco.service.namespace.QNameMap; 40 import org.alfresco.service.namespace.RegexQNamePattern; 41 import org.apache.commons.logging.Log; 42 import org.apache.commons.logging.LogFactory; 43 import org.springframework.util.StringUtils; 44 import org.xml.sax.InputSource ; 45 46 import freemarker.ext.dom.NodeModel; 47 48 60 public final class TemplateNode implements Serializable 61 { 62 private static final long serialVersionUID = 1234390333739034171L; 63 64 private static Log logger = LogFactory.getLog(TemplateNode.class); 65 66 private final static String NAMESPACE_BEGIN = "" + QName.NAMESPACE_BEGIN; 67 private final static String CONTENT_DEFAULT_URL = "/download/direct/{0}/{1}/{2}/{3}"; 68 private final static String CONTENT_PROP_URL = "/download/direct/{0}/{1}/{2}/{3}?property={4}"; 69 70 71 private List <TemplateNode> children = null; 72 73 74 private Map <String , List <TemplateNode>> assocs = null; 75 76 77 private NodeRef nodeRef; 78 private String name; 79 private QName type; 80 private String path; 81 private String id; 82 private Set <QName> aspects = null; 83 private QNameMap<String , Object > properties; 84 private boolean propsRetrieved = false; 85 private ServiceRegistry services = null; 86 private Boolean isDocument = null; 87 private Boolean isContainer = null; 88 private String displayPath = null; 89 private String mimetype = null; 90 private Long size = null; 91 private TemplateImageResolver imageResolver = null; 92 private TemplateNode parent = null; 93 94 95 102 public TemplateNode(NodeRef nodeRef, ServiceRegistry services, TemplateImageResolver resolver) 103 { 104 if (nodeRef == null) 105 { 106 throw new IllegalArgumentException ("NodeRef must be supplied."); 107 } 108 109 if (services == null) 110 { 111 throw new IllegalArgumentException ("The ServiceRegistry must be supplied."); 112 } 113 114 this.nodeRef = nodeRef; 115 this.id = nodeRef.getId(); 116 this.services = services; 117 this.imageResolver = resolver; 118 119 this.properties = new QNameMap<String , Object >(this.services.getNamespaceService()); 120 } 121 122 125 public String getId() 126 { 127 return this.id; 128 } 129 130 133 public NodeRef getNodeRef() 134 { 135 return this.nodeRef; 136 } 137 138 141 public QName getType() 142 { 143 if (this.type == null) 144 { 145 this.type = this.services.getNodeService().getType(this.nodeRef); 146 } 147 148 return type; 149 } 150 151 154 public String getName() 155 { 156 if (this.name == null) 157 { 158 this.name = (String )getProperties().get("cm:name"); 160 161 if (this.name == null) 163 { 164 ChildAssociationRef parentRef = this.services.getNodeService().getPrimaryParent(this.nodeRef); 165 if (parentRef != null && parentRef.getQName() != null) 166 { 167 this.name = parentRef.getQName().getLocalName(); 168 } 169 else 170 { 171 this.name = ""; 172 } 173 } 174 } 175 176 return this.name; 177 } 178 179 182 public List <TemplateNode> getChildren() 183 { 184 if (this.children == null) 185 { 186 List <ChildAssociationRef> childRefs = this.services.getNodeService().getChildAssocs(this.nodeRef); 187 this.children = new ArrayList <TemplateNode>(childRefs.size()); 188 for (ChildAssociationRef ref : childRefs) 189 { 190 TemplateNode child = new TemplateNode(ref.getChildRef(), this.services, this.imageResolver); 192 this.children.add(child); 193 } 194 } 195 196 return this.children; 197 } 198 199 202 public Map getChildByNamePath() 203 { 204 return new NamePathResultsMap(this, this.services); 205 } 206 207 211 public Map getChildrenByXPath() 212 { 213 return new XPathResultsMap(this, this.services); 214 } 215 216 220 public Map getChildrenBySavedSearch() 221 { 222 return new SavedSearchResultsMap(this, this.services); 223 } 224 225 229 public Map getChildrenByLuceneSearch() 230 { 231 return new LuceneSearchResultsMap(this, this.services); 232 } 233 234 237 public Map <String , List <TemplateNode>> getAssocs() 238 { 239 if (this.assocs == null) 240 { 241 List <AssociationRef> refs = this.services.getNodeService().getTargetAssocs(this.nodeRef, RegexQNamePattern.MATCH_ALL); 242 this.assocs = new QNameMap<String , List <TemplateNode>>(this.services.getNamespaceService()); 243 for (AssociationRef ref : refs) 244 { 245 String qname = ref.getTypeQName().toString(); 246 List <TemplateNode> nodes = assocs.get(qname); 247 if (nodes == null) 248 { 249 nodes = new ArrayList <TemplateNode>(4); 251 this.assocs.put(ref.getTypeQName().toString(), nodes); 252 } 253 nodes.add( new TemplateNode(ref.getTargetRef(), this.services, this.imageResolver) ); 254 } 255 } 256 257 return this.assocs; 258 } 259 260 263 public Map <String , Object > getProperties() 264 { 265 if (this.propsRetrieved == false) 266 { 267 Map <QName, Serializable > props = this.services.getNodeService().getProperties(this.nodeRef); 268 269 for (QName qname : props.keySet()) 270 { 271 Serializable propValue = props.get(qname); 272 if (propValue instanceof NodeRef) 273 { 274 propValue = new TemplateNode(((NodeRef)propValue), this.services, this.imageResolver); 277 } 278 else if (propValue instanceof ContentData) 279 { 280 propValue = new TemplateContentData((ContentData)propValue, qname); 283 } 284 this.properties.put(qname.toString(), propValue); 285 } 286 287 this.propsRetrieved = true; 288 } 289 290 return this.properties; 291 } 292 293 296 public boolean getIsContainer() 297 { 298 if (isContainer == null) 299 { 300 DictionaryService dd = this.services.getDictionaryService(); 301 isContainer = Boolean.valueOf( (dd.isSubClass(getType(), ContentModel.TYPE_FOLDER) == true && 302 dd.isSubClass(getType(), ContentModel.TYPE_SYSTEM_FOLDER) == false) ); 303 } 304 305 return isContainer.booleanValue(); 306 } 307 308 311 public boolean getIsDocument() 312 { 313 if (isDocument == null) 314 { 315 DictionaryService dd = this.services.getDictionaryService(); 316 isDocument = Boolean.valueOf(dd.isSubClass(getType(), ContentModel.TYPE_CONTENT)); 317 } 318 319 return isDocument.booleanValue(); 320 } 321 322 325 public Set <QName> getAspects() 326 { 327 if (this.aspects == null) 328 { 329 this.aspects = this.services.getNodeService().getAspects(this.nodeRef); 330 } 331 332 return this.aspects; 333 } 334 335 340 public boolean hasAspect(String aspect) 341 { 342 if (this.aspects == null) 343 { 344 this.aspects = this.services.getNodeService().getAspects(this.nodeRef); 345 } 346 347 if (aspect.startsWith(NAMESPACE_BEGIN)) 348 { 349 return aspects.contains((QName.createQName(aspect))); 350 } 351 else 352 { 353 boolean found = false; 354 for (QName qname : this.aspects) 355 { 356 if (qname.toPrefixString(this.services.getNamespaceService()).equals(aspect)) 357 { 358 found = true; 359 break; 360 } 361 } 362 return found; 363 } 364 } 365 366 369 public NodeModel getXmlNodeModel() 370 { 371 try 372 { 373 return NodeModel.parse(new InputSource (new StringReader (getContent()))); 374 } 375 catch (Throwable err) 376 { 377 if (logger.isDebugEnabled()) 378 logger.debug(err.getMessage(), err); 379 380 return null; 381 } 382 } 383 384 387 public String getDisplayPath() 388 { 389 if (displayPath == null) 390 { 391 try 392 { 393 displayPath = this.services.getNodeService().getPath(this.nodeRef).toDisplayPath(this.services.getNodeService()); 394 } 395 catch (AccessDeniedException err) 396 { 397 displayPath = ""; 398 } 399 } 400 401 return displayPath; 402 } 403 404 407 public String getIcon16() 408 { 409 if (this.imageResolver != null) 410 { 411 if (getIsDocument()) 412 { 413 return this.imageResolver.resolveImagePathForName(getName(), true); 414 } 415 else 416 { 417 return "/images/icons/space_small.gif"; 418 } 419 } 420 else 421 { 422 return "/images/filetypes/_default.gif"; 423 } 424 } 425 426 429 public String getIcon32() 430 { 431 if (this.imageResolver != null) 432 { 433 if (getIsDocument()) 434 { 435 return this.imageResolver.resolveImagePathForName(getName(), false); 436 } 437 else 438 { 439 String icon = (String )getProperties().get("app:icon"); 440 if (icon != null) 441 { 442 return "/images/icons/" + icon + ".gif"; 443 } 444 else 445 { 446 return "/images/icons/space-icon-default.gif"; 447 } 448 } 449 } 450 else 451 { 452 return "/images/filetypes32/_default.gif"; 453 } 454 } 455 456 459 public boolean getIsLocked() 460 { 461 boolean locked = false; 462 463 if (getAspects().contains(ContentModel.ASPECT_LOCKABLE)) 464 { 465 LockStatus lockStatus = this.services.getLockService().getLockStatus(this.nodeRef); 466 if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER) 467 { 468 locked = true; 469 } 470 } 471 472 return locked; 473 } 474 475 478 public TemplateNode getParent() 479 { 480 if (parent == null) 481 { 482 NodeRef parentRef = this.services.getNodeService().getPrimaryParent(nodeRef).getParentRef(); 483 if (parentRef != null) 485 { 486 parent = new TemplateNode(parentRef, this.services, this.imageResolver); 487 } 488 } 489 490 return parent; 491 } 492 493 497 public String getContent() 498 { 499 ContentService contentService = this.services.getContentService(); 500 ContentReader reader = contentService.getReader(this.nodeRef, ContentModel.PROP_CONTENT); 501 return (reader != null && reader.exists()) ? reader.getContentString() : ""; 502 } 503 504 508 public String getUrl() 509 { 510 try 511 { 512 return MessageFormat.format(CONTENT_DEFAULT_URL, new Object [] { 513 nodeRef.getStoreRef().getProtocol(), 514 nodeRef.getStoreRef().getIdentifier(), 515 nodeRef.getId(), 516 StringUtils.replace(URLEncoder.encode(getName(), "UTF-8"), "+", "%20") } ); 517 } 518 catch (UnsupportedEncodingException err) 519 { 520 throw new TemplateException("Failed to encode content URL for node: " + nodeRef, err); 521 } 522 } 523 524 528 public String getMimetype() 529 { 530 if (mimetype == null) 531 { 532 TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); 533 if (content != null) 534 { 535 mimetype = content.getMimetype(); 536 } 537 } 538 539 return mimetype; 540 } 541 542 546 public long getSize() 547 { 548 if (size == null) 549 { 550 TemplateContentData content = (TemplateContentData)this.getProperties().get(ContentModel.PROP_CONTENT); 551 if (content != null) 552 { 553 size = content.getSize(); 554 } 555 } 556 557 return size != null ? size.longValue() : 0L; 558 } 559 560 563 public TemplateImageResolver getImageResolver() 564 { 565 return this.imageResolver; 566 } 567 568 571 public String toString() 572 { 573 if (this.services.getNodeService().exists(nodeRef)) 574 { 575 return "Node Type: " + getType() + 576 "\nNode Properties: " + this.getProperties().toString() + 577 "\nNode Aspects: " + this.getAspects().toString(); 578 } 579 else 580 { 581 return "Node no longer exists: " + nodeRef; 582 } 583 } 584 585 586 589 public class TemplateContentData implements Serializable 590 { 591 597 public TemplateContentData(ContentData contentData, QName property) 598 { 599 this.contentData = contentData; 600 this.property = property; 601 } 602 603 606 public String getContent() 607 { 608 ContentService contentService = services.getContentService(); 609 ContentReader reader = contentService.getReader(nodeRef, property); 610 611 return (reader != null && reader.exists()) ? reader.getContentString() : ""; 612 } 613 614 617 public String getUrl() 618 { 619 try 620 { 621 return MessageFormat.format(CONTENT_PROP_URL, new Object [] { 622 nodeRef.getStoreRef().getProtocol(), 623 nodeRef.getStoreRef().getIdentifier(), 624 nodeRef.getId(), 625 StringUtils.replace(URLEncoder.encode(getName(), "UTF-8"), "+", "%20"), 626 StringUtils.replace(URLEncoder.encode(property.toString(), "UTF-8"), "+", "%20") } ); 627 } 628 catch (UnsupportedEncodingException err) 629 { 630 throw new TemplateException("Failed to encode content URL for node: " + nodeRef, err); 631 } 632 } 633 634 public long getSize() 635 { 636 return contentData.getSize(); 637 } 638 639 public String getMimetype() 640 { 641 return contentData.getMimetype(); 642 } 643 644 private ContentData contentData; 645 private QName property; 646 } 647 } | Popular Tags |