/** Test Going betwwen a NodeRef and a version, path pair. */ public void testTranslate() { String avmPath = "main:/"; int version = 2; NodeRef nodeRef = AVMNodeConverter.ToNodeRef(version, avmPath); System.out.println(nodeRef); Pair<Integer, String> backOut = AVMNodeConverter.ToAVMVersionPath(nodeRef); assertEquals(2, backOut.getFirst().intValue()); assertEquals(avmPath, backOut.getSecond()); avmPath = "main:/fista/mista/wisticuff"; version = -1; nodeRef = AVMNodeConverter.ToNodeRef(version, avmPath); System.out.println(nodeRef); backOut = AVMNodeConverter.ToAVMVersionPath(nodeRef); assertEquals(-1, backOut.getFirst().intValue()); assertEquals(avmPath, backOut.getSecond()); }
/** * @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node) */ public boolean evaluate(final Node node) { FacesContext facesContext = FacesContext.getCurrentInstance(); AVMService avmService = Repository.getServiceRegistry(facesContext).getAVMService(); Pair<Integer, String> p = AVMNodeConverter.ToAVMVersionPath(node.getNodeRef()); AVMNodeDescriptor nodeDesc = avmService.lookup(-1, p.getSecond()); // don't allow action if its a 'layeredfolder' and a primary indirection return !(nodeDesc.getType() == AVMNodeType.LAYERED_DIRECTORY && nodeDesc.isPrimary()); }
/** * Returns the Ticket in the form used for HTTP Basic Authentication. This should be added as the * value to a HTTP Request Header with key Authorization */ public String getAsHTTPAuthorization() { // Build from the Username and Password Pair<String, String> userPass = getAsUsernameAndPassword(); Credentials credentials = new UsernamePasswordCredentials(userPass.getFirst(), userPass.getSecond()); // Encode it into the required format String credentialsEncoded = Base64.encodeBytes(credentials.toString().getBytes(utf8), Base64.DONT_BREAK_LINES); // Mark it as Basic, and we're done return "Basic " + credentialsEncoded; }
private String getAclTenant(long aclId) { List<Long> nodeIds = aclDAO.getADMNodesByAcl(aclId, 1); if (nodeIds.size() == 0) { return null; } nodeDAO.setCheckNodeConsistency(); Pair<Long, NodeRef> nodePair = nodeDAO.getNodePair(nodeIds.get(0)); if (nodePair == null) { return null; } return tenantService.getDomain(nodePair.getSecond().getStoreRef().getIdentifier()); }
/** * Helper method to set all values associated with the {@link #setChildNodeName(String) child node * name}. * * @param dictionaryService the service that determines how the CRC values are generated. If this * is <tt>null</tt> then the CRC values are generated assuming that positive enforcement of * the name constraint is required. * @param childNodeName the child node name */ public void setChildNodeNameAll( DictionaryService dictionaryService, QName typeQName, String childNodeName) { ParameterCheck.mandatory("childNodeName", childNodeName); if (dictionaryService != null) { ParameterCheck.mandatory("typeQName", typeQName); Pair<String, Long> childNameUnique = ChildAssocEntity.getChildNameUnique(dictionaryService, typeQName, childNodeName); this.childNodeName = childNameUnique.getFirst(); this.childNodeNameCrc = childNameUnique.getSecond(); } else { String childNameNewLower = childNodeName.toLowerCase(); this.childNodeName = ChildAssocEntity.getChildNodeNameShort(childNameNewLower); this.childNodeNameCrc = ChildAssocEntity.getChildNodeNameCrc(childNameNewLower); } }
/** * Executes a solr query for statistics * * @param searchParameters StatsParameters * @return SolrStatsResult */ public SolrStatsResult executeStatsQuery(final StatsParameters searchParameters) { if (repositoryState.isBootstrapping()) { throw new AlfrescoRuntimeException( "SOLR stats queries can not be executed while the repository is bootstrapping"); } try { StoreRef store = extractStoreRef(searchParameters); SolrStoreMappingWrapper mapping = extractMapping(store); Locale locale = extractLocale(searchParameters); Pair<HttpClient, String> httpClientAndBaseUrl = mapping.getHttpClientAndBaseUrl(); HttpClient httpClient = httpClientAndBaseUrl.getFirst(); String url = buildStatsUrl(searchParameters, httpClientAndBaseUrl.getSecond(), locale); JSONObject body = buildStatsBody(searchParameters, tenantService.getCurrentUserDomain(), locale); if (httpClient == null) { throw new AlfrescoRuntimeException("No http client for store " + store.toString()); } return (SolrStatsResult) postSolrQuery( httpClient, url, body, new SolrJsonProcessor<SolrStatsResult>() { @Override public SolrStatsResult getResult(JSONObject json) { return new SolrStatsResult(json, searchParameters.isDateSearch()); } }); } catch (UnsupportedEncodingException e) { throw new LuceneQueryParserException("stats", e); } catch (HttpException e) { throw new LuceneQueryParserException("stats", e); } catch (IOException e) { throw new LuceneQueryParserException("stats", e); } catch (JSONException e) { throw new LuceneQueryParserException("stats", e); } }
public ResultSet executeQuery(final SearchParameters searchParameters, String language) { if (repositoryState.isBootstrapping()) { throw new AlfrescoRuntimeException( "SOLR queries can not be executed while the repository is bootstrapping"); } try { StoreRef store = extractStoreRef(searchParameters); SolrStoreMappingWrapper mapping = extractMapping(store); Locale locale = extractLocale(searchParameters); URLCodec encoder = new URLCodec(); StringBuilder url = new StringBuilder(); Pair<HttpClient, String> httpClientAndBaseUrl = mapping.getHttpClientAndBaseUrl(); HttpClient httpClient = httpClientAndBaseUrl.getFirst(); url.append(httpClientAndBaseUrl.getSecond()); String languageUrlFragment = extractLanguageFragment(language); url.append("/").append(languageUrlFragment); // Send the query in JSON only // url.append("?q="); // url.append(encoder.encode(searchParameters.getQuery(), "UTF-8")); url.append("?wt=").append(encoder.encode("json", "UTF-8")); url.append("&fl=").append(encoder.encode("DBID,score", "UTF-8")); if ((searchParameters.getStores().size() > 1) || (mapping.isSharded())) { boolean requiresSeparator = false; url.append("&shards="); for (StoreRef storeRef : searchParameters.getStores()) { SolrStoreMappingWrapper storeMapping = extractMapping(storeRef); if (requiresSeparator) { url.append(','); } else { requiresSeparator = true; } url.append(storeMapping.getShards()); } } // Emulate old limiting behaviour and metadata final LimitBy limitBy; int maxResults = -1; if (searchParameters.getMaxItems() >= 0) { maxResults = searchParameters.getMaxItems(); limitBy = LimitBy.FINAL_SIZE; } else if (searchParameters.getLimitBy() == LimitBy.FINAL_SIZE && searchParameters.getLimit() >= 0) { maxResults = searchParameters.getLimit(); limitBy = LimitBy.FINAL_SIZE; } else { maxResults = searchParameters.getMaxPermissionChecks(); if (maxResults < 0) { maxResults = maximumResultsFromUnlimitedQuery; } limitBy = LimitBy.NUMBER_OF_PERMISSION_EVALUATIONS; } url.append("&rows=").append(String.valueOf(maxResults)); url.append("&df=").append(encoder.encode(searchParameters.getDefaultFieldName(), "UTF-8")); url.append("&start=").append(encoder.encode("" + searchParameters.getSkipCount(), "UTF-8")); url.append("&locale="); url.append(encoder.encode(locale.toString(), "UTF-8")); url.append("&") .append(SearchParameters.ALTERNATIVE_DICTIONARY) .append("=") .append(alternativeDictionary); for (String paramName : searchParameters.getExtraParameters().keySet()) { url.append("&") .append(paramName) .append("=") .append(searchParameters.getExtraParameters().get(paramName)); } StringBuffer sortBuffer = buildSortParameters(searchParameters, encoder); url.append(sortBuffer); if (searchParameters.getPermissionEvaluation() != PermissionEvaluationMode.NONE) { url.append("&fq=").append(encoder.encode("{!afts}AUTHORITY_FILTER_FROM_JSON", "UTF-8")); } if (searchParameters.getExcludeTenantFilter() == false) { url.append("&fq=").append(encoder.encode("{!afts}TENANT_FILTER_FROM_JSON", "UTF-8")); } if (searchParameters.getFieldFacets().size() > 0) { url.append("&facet=").append(encoder.encode("true", "UTF-8")); for (FieldFacet facet : searchParameters.getFieldFacets()) { url.append("&facet.field=").append(encoder.encode(facet.getField(), "UTF-8")); if (facet.getEnumMethodCacheMinDF() != 0) { url.append("&") .append( encoder.encode("f." + facet.getField() + ".facet.enum.cache.minDf", "UTF-8")) .append("=") .append(encoder.encode("" + facet.getEnumMethodCacheMinDF(), "UTF-8")); } url.append("&") .append(encoder.encode("f." + facet.getField() + ".facet.limit", "UTF-8")) .append("=") .append(encoder.encode("" + facet.getLimit(), "UTF-8")); if (facet.getMethod() != null) { url.append("&") .append(encoder.encode("f." + facet.getField() + ".facet.method", "UTF-8")) .append("=") .append( encoder.encode( facet.getMethod() == FieldFacetMethod.ENUM ? "enum" : "fc", "UTF-8")); } if (facet.getMinCount() != 0) { url.append("&") .append(encoder.encode("f." + facet.getField() + ".facet.mincount", "UTF-8")) .append("=") .append(encoder.encode("" + facet.getMinCount(), "UTF-8")); } if (facet.getOffset() != 0) { url.append("&") .append(encoder.encode("f." + facet.getField() + ".facet.offset", "UTF-8")) .append("=") .append(encoder.encode("" + facet.getOffset(), "UTF-8")); } if (facet.getPrefix() != null) { url.append("&") .append(encoder.encode("f." + facet.getField() + ".facet.prefix", "UTF-8")) .append("=") .append(encoder.encode("" + facet.getPrefix(), "UTF-8")); } if (facet.getSort() != null) { url.append("&") .append(encoder.encode("f." + facet.getField() + ".facet.sort", "UTF-8")) .append("=") .append( encoder.encode( facet.getSort() == FieldFacetSort.COUNT ? "count" : "index", "UTF-8")); } } for (String facetQuery : searchParameters.getFacetQueries()) { url.append("&facet.query=").append(encoder.encode("{!afts}" + facetQuery, "UTF-8")); } } // end of field facets final String searchTerm = searchParameters.getSearchTerm(); String spellCheckQueryStr = null; if (searchTerm != null && searchParameters.isSpellCheck()) { StringBuilder builder = new StringBuilder(); builder.append("&spellcheck.q=").append(encoder.encode(searchTerm, "UTF-8")); builder.append("&spellcheck=").append(encoder.encode("true", "UTF-8")); spellCheckQueryStr = builder.toString(); url.append(spellCheckQueryStr); } JSONObject body = new JSONObject(); body.put("query", searchParameters.getQuery()); // Authorities go over as is - and tenant mangling and query building takes place on the SOLR // side Set<String> allAuthorisations = permissionService.getAuthorisations(); boolean includeGroups = includeGroupsForRoleAdmin ? true : !allAuthorisations.contains(PermissionService.ADMINISTRATOR_AUTHORITY); JSONArray authorities = new JSONArray(); for (String authority : allAuthorisations) { if (includeGroups) { authorities.put(authority); } else { if (AuthorityType.getAuthorityType(authority) != AuthorityType.GROUP) { authorities.put(authority); } } } body.put("authorities", authorities); body.put("anyDenyDenies", anyDenyDenies); JSONArray tenants = new JSONArray(); tenants.put(tenantService.getCurrentUserDomain()); body.put("tenants", tenants); JSONArray locales = new JSONArray(); for (Locale currentLocale : searchParameters.getLocales()) { locales.put(DefaultTypeConverter.INSTANCE.convert(String.class, currentLocale)); } if (locales.length() == 0) { locales.put(I18NUtil.getLocale()); } body.put("locales", locales); JSONArray templates = new JSONArray(); for (String templateName : searchParameters.getQueryTemplates().keySet()) { JSONObject template = new JSONObject(); template.put("name", templateName); template.put("template", searchParameters.getQueryTemplates().get(templateName)); templates.put(template); } body.put("templates", templates); JSONArray allAttributes = new JSONArray(); for (String attribute : searchParameters.getAllAttributes()) { allAttributes.put(attribute); } body.put("allAttributes", allAttributes); body.put("defaultFTSOperator", searchParameters.getDefaultFTSOperator()); body.put("defaultFTSFieldOperator", searchParameters.getDefaultFTSFieldOperator()); body.put("queryConsistency", searchParameters.getQueryConsistency()); if (searchParameters.getMlAnalaysisMode() != null) { body.put("mlAnalaysisMode", searchParameters.getMlAnalaysisMode().toString()); } body.put("defaultNamespace", searchParameters.getNamespace()); JSONArray textAttributes = new JSONArray(); for (String attribute : searchParameters.getTextAttributes()) { textAttributes.put(attribute); } body.put("textAttributes", textAttributes); final int maximumResults = maxResults; // just needed for the final parameter return (ResultSet) postSolrQuery( httpClient, url.toString(), body, new SolrJsonProcessor<SolrJSONResultSet>() { @Override public SolrJSONResultSet getResult(JSONObject json) { return new SolrJSONResultSet( json, searchParameters, nodeService, nodeDAO, limitBy, maximumResults); } }, spellCheckQueryStr); } catch (UnsupportedEncodingException e) { throw new LuceneQueryParserException("", e); } catch (HttpException e) { throw new LuceneQueryParserException("", e); } catch (IOException e) { throw new LuceneQueryParserException("", e); } catch (JSONException e) { throw new LuceneQueryParserException("", e); } }
public List<Pair<String, Integer>> getTopTerms(String field, int count) { ClosingIndexSearcher searcher = null; try { LinkedList<Pair<String, Integer>> answer = new LinkedList<Pair<String, Integer>>(); searcher = getSearcher(indexer); IndexReader reader = searcher.getIndexReader(); TermEnum terms = reader.terms(new Term(field, "")); do { Term term = terms.term(); if (term != null) { if (!term.field().equals(field)) { break; } int freq = terms.docFreq(); Pair<String, Integer> pair = new Pair<String, Integer>(term.text(), Integer.valueOf(freq)); if (answer.size() < count) { if (answer.size() == 0) { answer.add(pair); } else if (answer.get(answer.size() - 1).getSecond().compareTo(pair.getSecond()) >= 0) { answer.add(pair); } else { for (ListIterator<Pair<String, Integer>> it = answer.listIterator(); it.hasNext(); /**/ ) { Pair<String, Integer> test = it.next(); if (test.getSecond().compareTo(pair.getSecond()) < 0) { it.previous(); it.add(pair); break; } } } } else if (answer.get(count - 1).getSecond().compareTo(pair.getSecond()) < 0) { for (ListIterator<Pair<String, Integer>> it = answer.listIterator(); it.hasNext(); /**/ ) { Pair<String, Integer> test = it.next(); if (test.getSecond().compareTo(pair.getSecond()) < 0) { it.previous(); it.add(pair); break; } } answer.removeLast(); } else { // off the end } } } while (terms.next()); terms.close(); return answer; } catch (IOException e) { throw new SearcherException(e); } finally { if (searcher != null) { try { searcher.close(); } catch (IOException e) { throw new SearcherException(e); } } } }
/** {@inheritDoc} */ public void getNodesMetadata( NodeMetaDataParameters nodeMetaDataParameters, MetaDataResultsFilter resultFilter, NodeMetaDataQueryCallback callback) { if (false == enabled) { return; } NodeMetaDataQueryRowHandler rowHandler = new NodeMetaDataQueryRowHandler(callback); boolean includeType = (resultFilter == null ? true : resultFilter.getIncludeType()); boolean includeProperties = (resultFilter == null ? true : resultFilter.getIncludeProperties()); boolean includeAspects = (resultFilter == null ? true : resultFilter.getIncludeAspects()); boolean includePaths = (resultFilter == null ? true : resultFilter.getIncludePaths()); boolean includeNodeRef = (resultFilter == null ? true : resultFilter.getIncludeNodeRef()); boolean includeParentAssociations = (resultFilter == null ? true : resultFilter.getIncludeParentAssociations()); boolean includeChildAssociations = (resultFilter == null ? true : resultFilter.getIncludeChildAssociations()); boolean includeOwner = (resultFilter == null ? true : resultFilter.getIncludeOwner()); boolean includeChildIds = (resultFilter == null ? true : resultFilter.getIncludeChildIds()); boolean includeTxnId = (resultFilter == null ? true : resultFilter.getIncludeTxnId()); List<Long> nodeIds = preCacheNodes(nodeMetaDataParameters); for (Long nodeId : nodeIds) { Status status = nodeDAO.getNodeIdStatus(nodeId); if (status == null) { // We've been called with the ID of a purged node, probably due to processing a transaction // with a // cascading delete. Fine to skip and assume it will be processed in a transaction. // See org.alfresco.solr.tracker.CoreTracker.updateDescendantAuxDocs(NodeMetaData, boolean, // SolrIndexSearcher) continue; } NodeRef nodeRef = status.getNodeRef(); NodeMetaData nodeMetaData = new NodeMetaData(); nodeMetaData.setNodeId(nodeId); if (includeNodeRef) { nodeMetaData.setNodeRef(tenantService.getBaseName(nodeRef, true)); } if (includeTxnId) { nodeMetaData.setTxnId(status.getDbTxnId()); } if (status.isDeleted()) { rowHandler.processResult(nodeMetaData); continue; } Map<QName, Serializable> props = null; Set<QName> aspects = null; nodeMetaData.setAclId(nodeDAO.getNodeAclId(nodeId)); if (includeType) { QName nodeType = getNodeType(nodeId); if (nodeType != null) { nodeMetaData.setNodeType(nodeType); } else { throw new AlfrescoRuntimeException("Nodes with no type are ignored by SOLR"); } } if (includeProperties) { if (props == null) { props = getProperties(nodeId); } nodeMetaData.setProperties(props); } else { nodeMetaData.setProperties(Collections.<QName, Serializable>emptyMap()); } if (includeAspects || includePaths || includeParentAssociations) { aspects = getNodeAspects(nodeId); } nodeMetaData.setAspects(aspects); boolean ignoreLargeMetadata = (typeIndexFilter.shouldBeIgnored(getNodeType(nodeId)) || aspectIndexFilter.shouldBeIgnored(getNodeAspects(nodeId))); if (!ignoreLargeMetadata && (typeIndexFilter.isIgnorePathsForSpecificTypes() || aspectIndexFilter.isIgnorePathsForSpecificAspects())) { // check if parent should be ignored final List<Long> parentIds = new LinkedList<Long>(); nodeDAO.getParentAssocs( nodeId, null, null, true, new ChildAssocRefQueryCallback() { @Override public boolean preLoadNodes() { return false; } @Override public boolean orderResults() { return false; } @Override public boolean handle( Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair) { parentIds.add(parentNodePair.getFirst()); return false; } @Override public void done() {} }); if (!parentIds.isEmpty()) { Long parentId = parentIds.iterator().next(); if (typeIndexFilter.isIgnorePathsForSpecificTypes()) { QName parentType = getNodeType(parentId); ignoreLargeMetadata = typeIndexFilter.shouldBeIgnored(parentType); } if (!ignoreLargeMetadata && aspectIndexFilter.isIgnorePathsForSpecificAspects()) { ignoreLargeMetadata = aspectIndexFilter.shouldBeIgnored(getNodeAspects(parentId)); } } } CategoryPaths categoryPaths = new CategoryPaths( new ArrayList<Pair<Path, QName>>(), new ArrayList<ChildAssociationRef>()); if (!ignoreLargeMetadata && (includePaths || includeParentAssociations)) { if (props == null) { props = getProperties(nodeId); } categoryPaths = getCategoryPaths(status.getNodeRef(), aspects, props); } if (includePaths && !ignoreLargeMetadata) { if (props == null) { props = getProperties(nodeId); } List<Path> directPaths = nodeDAO.getPaths(new Pair<Long, NodeRef>(nodeId, status.getNodeRef()), false); Collection<Pair<Path, QName>> paths = new ArrayList<Pair<Path, QName>>(directPaths.size() + categoryPaths.getPaths().size()); for (Path path : directPaths) { paths.add(new Pair<Path, QName>(path.getBaseNamePath(tenantService), null)); } for (Pair<Path, QName> catPair : categoryPaths.getPaths()) { paths.add( new Pair<Path, QName>( catPair.getFirst().getBaseNamePath(tenantService), catPair.getSecond())); } nodeMetaData.setPaths(paths); // Calculate name path Collection<Collection<String>> namePaths = new ArrayList<Collection<String>>(2); nodeMetaData.setNamePaths(namePaths); for (Pair<Path, QName> catPair : paths) { Path path = catPair.getFirst(); boolean added = false; List<String> namePath = new ArrayList<String>(path.size()); NEXT_ELEMENT: for (Path.Element pathElement : path) { if (!(pathElement instanceof ChildAssocElement)) { // This is some path element that is terminal to a cm:name path break; } ChildAssocElement pathChildAssocElement = (ChildAssocElement) pathElement; NodeRef childNodeRef = pathChildAssocElement.getRef().getChildRef(); Pair<Long, NodeRef> childNodePair = nodeDAO.getNodePair(childNodeRef); if (childNodePair == null) { // Gone break; } Long childNodeId = childNodePair.getFirst(); String childNodeName = (String) nodeDAO.getNodeProperty(childNodeId, ContentModel.PROP_NAME); if (childNodeName == null) { // We have hit a non-name node, which acts as a root for cm:name // DH: There is no particular constraint here. This is just a decision made. namePath.clear(); // We have to continue down the path as there could be a name path lower down continue NEXT_ELEMENT; } // We can finally add the name to the path namePath.add(childNodeName); // Add the path if this is the first entry in the name path if (!added) { namePaths.add(namePath); added = true; } } } } nodeMetaData.setTenantDomain(tenantService.getDomain(nodeRef.getStoreRef().getIdentifier())); if (includeChildAssociations) { final List<ChildAssociationRef> childAssocs = new ArrayList<ChildAssociationRef>(100); nodeDAO.getChildAssocs( nodeId, null, null, null, null, null, new ChildAssocRefQueryCallback() { @Override public boolean preLoadNodes() { return false; } @Override public boolean orderResults() { return false; } @Override public boolean handle( Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair) { boolean addCurrentChildAssoc = true; if (typeIndexFilter.isIgnorePathsForSpecificTypes()) { QName nodeType = nodeDAO.getNodeType(childNodePair.getFirst()); addCurrentChildAssoc = !typeIndexFilter.shouldBeIgnored(nodeType); } if (!addCurrentChildAssoc && aspectIndexFilter.isIgnorePathsForSpecificAspects()) { addCurrentChildAssoc = !aspectIndexFilter.shouldBeIgnored(getNodeAspects(childNodePair.getFirst())); } if (addCurrentChildAssoc) { childAssocs.add(tenantService.getBaseName(childAssocPair.getSecond(), true)); } return true; } @Override public void done() {} }); nodeMetaData.setChildAssocs(childAssocs); } if (includeChildIds) { final List<Long> childIds = new ArrayList<Long>(100); nodeDAO.getChildAssocs( nodeId, null, null, null, null, null, new ChildAssocRefQueryCallback() { @Override public boolean preLoadNodes() { return false; } @Override public boolean orderResults() { return false; } @Override public boolean handle( Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair) { boolean addCurrentId = true; if (typeIndexFilter.isIgnorePathsForSpecificTypes()) { QName nodeType = nodeDAO.getNodeType(childNodePair.getFirst()); addCurrentId = !typeIndexFilter.shouldBeIgnored(nodeType); } if (!addCurrentId) { addCurrentId = !aspectIndexFilter.shouldBeIgnored(getNodeAspects(childNodePair.getFirst())); } if (addCurrentId) { childIds.add(childNodePair.getFirst()); } return true; } @Override public void done() {} }); nodeMetaData.setChildIds(childIds); } if (includeParentAssociations && !ignoreLargeMetadata) { final List<ChildAssociationRef> parentAssocs = new ArrayList<ChildAssociationRef>(100); nodeDAO.getParentAssocs( nodeId, null, null, null, new ChildAssocRefQueryCallback() { @Override public boolean preLoadNodes() { return false; } @Override public boolean orderResults() { return false; } @Override public boolean handle( Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> childNodePair) { parentAssocs.add(tenantService.getBaseName(childAssocPair.getSecond(), true)); return true; } @Override public void done() {} }); for (ChildAssociationRef ref : categoryPaths.getCategoryParents()) { parentAssocs.add(tenantService.getBaseName(ref, true)); } CRC32 crc = new CRC32(); for (ChildAssociationRef car : parentAssocs) { try { crc.update(car.toString().getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { throw new RuntimeException("UTF-8 encoding is not supported"); } } nodeMetaData.setParentAssocs(parentAssocs, crc.getValue()); // TODO non-child associations // Collection<Pair<Long, AssociationRef>> sourceAssocs = // nodeDAO.getSourceNodeAssocs(nodeId); // Collection<Pair<Long, AssociationRef>> targetAssocs = // nodeDAO.getTargetNodeAssocs(nodeId); // // nodeMetaData.setAssocs(); } if (includeOwner) { // cached in OwnableService nodeMetaData.setOwner(ownableService.getOwner(status.getNodeRef())); } rowHandler.processResult(nodeMetaData); } }