1 17 package org.alfresco.repo.search.impl; 18 19 import java.io.Serializable ; 20 import java.util.ArrayList ; 21 import java.util.Collections ; 22 import java.util.Comparator ; 23 import java.util.HashSet ; 24 import java.util.List ; 25 26 import org.alfresco.repo.search.DocumentNavigator; 27 import org.alfresco.repo.search.NodeServiceXPath; 28 import org.alfresco.service.cmr.dictionary.DictionaryService; 29 import org.alfresco.service.cmr.repository.ChildAssociationRef; 30 import org.alfresco.service.cmr.repository.NodeRef; 31 import org.alfresco.service.cmr.repository.NodeService; 32 import org.alfresco.service.cmr.repository.XPathException; 33 import org.alfresco.service.cmr.search.QueryParameterDefinition; 34 import org.alfresco.service.cmr.search.SearchService; 35 import org.alfresco.service.namespace.NamespacePrefixResolver; 36 import org.alfresco.service.namespace.QName; 37 import org.jaxen.JaxenException; 38 39 51 public class NodeSearcher 52 { 53 private NodeService nodeService; 54 55 private DictionaryService dictionaryService; 56 57 private SearchService searchService; 58 59 public NodeSearcher(NodeService nodeService, DictionaryService dictionaryService, SearchService searchService) 60 { 61 this.nodeService = nodeService; 62 this.dictionaryService = dictionaryService; 63 this.searchService = searchService; 64 } 65 66 69 public synchronized List <NodeRef> selectNodes(NodeRef contextNodeRef, String xpathIn, 70 QueryParameterDefinition[] paramDefs, NamespacePrefixResolver namespacePrefixResolver, 71 boolean followAllParentLinks, String language) 72 { 73 try 74 { 75 String xpath = xpathIn; 76 boolean useJCRXPath = language.equalsIgnoreCase(SearchService.LANGUAGE_JCR_XPATH); 77 78 List <AttributeOrder> order = null; 79 80 if (useJCRXPath) 82 { 83 order = new ArrayList <AttributeOrder>(); 84 xpath = xpath.replaceAll("element\\(\\s*(\\*|\\w*:\\w*)\\s*,\\s*(\\*|\\w*:\\w*)\\s*\\)", 86 "$1[subtypeOf(\"$2\")]"); 87 String split[] = xpath.split("order\\s*by\\s*", 2); 88 xpath = split[0]; 89 90 if (split.length > 1 && split[1].length() > 0) 91 { 92 String clauses[] = split[1].split("\\s,\\s"); 93 94 for (String clause : clauses) 95 { 96 if (clause.startsWith("@")) 97 { 98 String attribute = clause.replaceFirst("@(\\p{Alpha}[\\w:]*)(?:\\s+(.*))?", "$1"); 99 String sort = clause.replaceFirst("@(\\p{Alpha}[\\w:]*)(?:\\s+(.*))?", "$2"); 100 101 if (sort.length() == 0) 102 { 103 sort = "ascending"; 104 } 105 106 QName attributeQName = QName.createQName(attribute, namespacePrefixResolver); 107 order.add(new AttributeOrder(attributeQName, sort.equalsIgnoreCase("ascending"))); 108 } 109 else if (clause.startsWith("jcr:score")) 110 { 111 } 113 else 114 { 115 throw new IllegalArgumentException ("Malformed order by expression " + split[1]); 116 } 117 } 118 119 } 120 121 } 122 123 DocumentNavigator documentNavigator = new DocumentNavigator(dictionaryService, nodeService, searchService, 124 namespacePrefixResolver, followAllParentLinks, useJCRXPath); 125 NodeServiceXPath nsXPath = new NodeServiceXPath(xpath, documentNavigator, paramDefs); 126 for (String prefix : namespacePrefixResolver.getPrefixes()) 127 { 128 nsXPath.addNamespace(prefix, namespacePrefixResolver.getNamespaceURI(prefix)); 129 } 130 List list = nsXPath.selectNodes(nodeService.getPrimaryParent(contextNodeRef)); 131 HashSet <NodeRef> unique = new HashSet <NodeRef>(list.size()); 132 for (Object o : list) 133 { 134 if (o instanceof ChildAssociationRef) 135 { 136 unique.add(((ChildAssociationRef) o).getChildRef()); 137 } 138 else if (o instanceof DocumentNavigator.Property) 139 { 140 unique.add(((DocumentNavigator.Property) o).parent); 141 } 142 else 143 { 144 throw new XPathException("Xpath expression must only select nodes"); 145 } 146 } 147 148 List <NodeRef> answer = new ArrayList <NodeRef>(unique.size()); 149 answer.addAll(unique); 150 if (order != null) 151 { 152 orderNodes(answer, order); 153 for(NodeRef node : answer) 154 { 155 StringBuffer buffer = new StringBuffer (); 156 for (AttributeOrder attOrd : order) 157 { 158 buffer.append(" ").append(nodeService.getProperty(node, attOrd.attribute)); 159 } 160 } 161 } 162 return answer; 163 } 164 catch (JaxenException e) 165 { 166 throw new XPathException("Error executing xpath: \n" + " xpath: " + xpathIn, e); 167 } 168 } 169 170 private void orderNodes(List <NodeRef> answer, List <AttributeOrder> order) 171 { 172 Collections.sort(answer, new NodeRefComparator(nodeService, order)); 173 } 174 175 static class NodeRefComparator implements Comparator <NodeRef> 176 { 177 List <AttributeOrder> order; 178 NodeService nodeService; 179 180 NodeRefComparator(NodeService nodeService, List <AttributeOrder> order) 181 { 182 this.nodeService = nodeService; 183 this.order = order; 184 } 185 186 @SuppressWarnings ("unchecked") 187 public int compare(NodeRef n1, NodeRef n2) 188 { 189 for (AttributeOrder attributeOrder : order) 190 { 191 Serializable o1 = nodeService.getProperty(n1, attributeOrder.attribute); 192 Serializable o2 = nodeService.getProperty(n2, attributeOrder.attribute); 193 194 if (o1 == null) 195 { 196 if (o2 == null) 197 { 198 continue; 199 } 200 else 201 { 202 return attributeOrder.ascending ? -1 : 1; 203 } 204 } 205 else 206 { 207 if (o2 == null) 208 { 209 return attributeOrder.ascending ? 1 : -1; 210 } 211 else 212 { 213 if ((o1 instanceof Comparable ) && (o2 instanceof Comparable )) 214 { 215 return (attributeOrder.ascending ? 1 : -1) * ((Comparable )o1).compareTo((Comparable ) o2); 216 } 217 else 218 { 219 continue; 220 } 221 } 222 } 223 224 } 225 return 0; 226 } 227 } 228 229 232 public List <Serializable > selectProperties(NodeRef contextNodeRef, String xpath, 233 QueryParameterDefinition[] paramDefs, NamespacePrefixResolver namespacePrefixResolver, 234 boolean followAllParentLinks, String language) 235 { 236 try 237 { 238 boolean useJCRXPath = language.equalsIgnoreCase(SearchService.LANGUAGE_JCR_XPATH); 239 240 DocumentNavigator documentNavigator = new DocumentNavigator(dictionaryService, nodeService, searchService, 241 namespacePrefixResolver, followAllParentLinks, useJCRXPath); 242 NodeServiceXPath nsXPath = new NodeServiceXPath(xpath, documentNavigator, paramDefs); 243 for (String prefix : namespacePrefixResolver.getPrefixes()) 244 { 245 nsXPath.addNamespace(prefix, namespacePrefixResolver.getNamespaceURI(prefix)); 246 } 247 List list = nsXPath.selectNodes(nodeService.getPrimaryParent(contextNodeRef)); 248 List <Serializable > answer = new ArrayList <Serializable >(list.size()); 249 for (Object o : list) 250 { 251 if (!(o instanceof DocumentNavigator.Property)) 252 { 253 throw new XPathException("Xpath expression must only select nodes"); 254 } 255 answer.add(((DocumentNavigator.Property) o).value); 256 } 257 return answer; 258 } 259 catch (JaxenException e) 260 { 261 throw new XPathException("Error executing xpath", e); 262 } 263 } 264 265 private static class AttributeOrder 266 { 267 QName attribute; 268 269 boolean ascending; 270 271 AttributeOrder(QName attribute, boolean ascending) 272 { 273 this.attribute = attribute; 274 this.ascending = ascending; 275 } 276 } 277 } 278 | Popular Tags |