001/* 002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Thierry Delprat 016 */ 017package org.nuxeo.apidoc.search; 018 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.List; 024import java.util.Map; 025 026import org.apache.commons.lang.text.StrBuilder; 027import org.nuxeo.apidoc.adapters.BaseNuxeoArtifactDocAdapter; 028import org.nuxeo.apidoc.adapters.BundleGroupDocAdapter; 029import org.nuxeo.apidoc.adapters.BundleInfoDocAdapter; 030import org.nuxeo.apidoc.adapters.ComponentInfoDocAdapter; 031import org.nuxeo.apidoc.adapters.ExtensionInfoDocAdapter; 032import org.nuxeo.apidoc.adapters.ExtensionPointInfoDocAdapter; 033import org.nuxeo.apidoc.adapters.ServiceInfoDocAdapter; 034import org.nuxeo.apidoc.api.BundleGroup; 035import org.nuxeo.apidoc.api.BundleInfo; 036import org.nuxeo.apidoc.api.ComponentInfo; 037import org.nuxeo.apidoc.api.DocumentationItem; 038import org.nuxeo.apidoc.api.ExtensionInfo; 039import org.nuxeo.apidoc.api.ExtensionPointInfo; 040import org.nuxeo.apidoc.api.NuxeoArtifact; 041import org.nuxeo.apidoc.api.QueryHelper; 042import org.nuxeo.apidoc.api.ServiceInfo; 043import org.nuxeo.apidoc.repository.RepositoryDistributionSnapshot; 044import org.nuxeo.apidoc.snapshot.DistributionSnapshot; 045import org.nuxeo.apidoc.snapshot.SnapshotManager; 046import org.nuxeo.ecm.core.api.CoreSession; 047import org.nuxeo.ecm.core.api.DocumentModel; 048import org.nuxeo.ecm.core.api.DocumentModelList; 049import org.nuxeo.ecm.core.query.sql.NXQL; 050import org.nuxeo.runtime.api.Framework; 051 052public class ArtifactSearcherImpl implements ArtifactSearcher { 053 054 protected NuxeoArtifact mapDoc2Artifact(DocumentModel doc) { 055 NuxeoArtifact artifact = null; 056 057 if (doc.getType().equals(BundleGroup.TYPE_NAME)) { 058 artifact = new BundleGroupDocAdapter(doc); 059 } else if (doc.getType().equals(BundleInfo.TYPE_NAME)) { 060 artifact = new BundleInfoDocAdapter(doc); 061 } else if (doc.getType().equals(ComponentInfo.TYPE_NAME)) { 062 artifact = new ComponentInfoDocAdapter(doc); 063 } else if (doc.getType().equals(ExtensionPointInfo.TYPE_NAME)) { 064 artifact = new ExtensionPointInfoDocAdapter(doc); 065 } else if (doc.getType().equals(ExtensionInfo.TYPE_NAME)) { 066 artifact = new ExtensionInfoDocAdapter(doc); 067 } else if (doc.getType().equals(DistributionSnapshot.TYPE_NAME)) { 068 artifact = new RepositoryDistributionSnapshot(doc); 069 } else if (doc.getType().equals(ServiceInfo.TYPE_NAME)) { 070 artifact = new ServiceInfoDocAdapter(doc); 071 } 072 073 return artifact; 074 } 075 076 @Override 077 public List<NuxeoArtifact> searchArtifact(CoreSession session, String fulltext) { 078 List<NuxeoArtifact> result = new ArrayList<NuxeoArtifact>(); 079 StrBuilder q = new StrBuilder("SELECT * FROM Document WHERE " + NXQL.ECM_PRIMARYTYPE + " IN ('"); 080 q.appendWithSeparators(Arrays.asList(BundleGroup.TYPE_NAME, BundleInfo.TYPE_NAME, ComponentInfo.TYPE_NAME, 081 ExtensionPointInfo.TYPE_NAME, ExtensionInfo.TYPE_NAME, DistributionSnapshot.TYPE_NAME, 082 ServiceInfo.TYPE_NAME), "', '"); 083 q.append("')"); 084 String query = q.toString(); 085 if (fulltext != null) { 086 query += " AND " + NXQL.ECM_FULLTEXT + " = " + NXQL.escapeString(fulltext); 087 } 088 DocumentModelList docs = session.query(query); 089 for (DocumentModel doc : docs) { 090 NuxeoArtifact artifact = mapDoc2Artifact(doc); 091 if (artifact != null) { 092 result.add(artifact); 093 } 094 } 095 return result; 096 } 097 098 @Override 099 public List<DocumentationItem> searchDocumentation(CoreSession session, String distribId, String fulltext, 100 String targetType) { 101 DistributionSnapshot snap = Framework.getLocalService(SnapshotManager.class).getSnapshot(distribId, session); 102 DocumentModel dist = ((RepositoryDistributionSnapshot) snap).getDoc(); 103 String query = QueryHelper.select(DocumentationItem.TYPE_NAME, dist, NXQL.ECM_FULLTEXT, fulltext); 104 if (targetType != null) { 105 query += " AND " + DocumentationItem.PROP_TARGET_TYPE + " = " + NXQL.escapeString(targetType); 106 } 107 DocumentModelList docs = session.query(query); 108 List<DocumentationItem> result = new ArrayList<DocumentationItem>(); 109 for (DocumentModel doc : docs) { 110 DocumentationItem docItem = doc.getAdapter(DocumentationItem.class); 111 if (docItem != null) { 112 result.add(docItem); 113 } 114 } 115 return result; 116 } 117 118 @Override 119 public List<NuxeoArtifact> filterArtifact(CoreSession session, String distribId, String type, String fulltext) { 120 List<NuxeoArtifact> result = new ArrayList<NuxeoArtifact>(); 121 122 List<NuxeoArtifact> matchingArtifacts = searchArtifact(session, fulltext); 123 List<DocumentationItem> matchingDocumentationItems = searchDocumentation(session, distribId, fulltext, null); 124 125 Map<String, ArtifactWithWeight> sortMap = new HashMap<String, ArtifactWithWeight>(); 126 127 for (NuxeoArtifact matchingArtifact : matchingArtifacts) { 128 NuxeoArtifact resultArtifact = resolveInTree(session, distribId, matchingArtifact, type); 129 if (resultArtifact != null) { 130 if (sortMap.containsKey(resultArtifact.getId())) { 131 sortMap.get(resultArtifact.getId()).addHit(); 132 } else { 133 sortMap.put(resultArtifact.getId(), new ArtifactWithWeight(resultArtifact)); 134 } 135 } 136 } 137 138 for (DocumentationItem matchingDocumentationItem : matchingDocumentationItems) { 139 NuxeoArtifact resultArtifact = resolveInTree(session, distribId, matchingDocumentationItem, type); 140 if (resultArtifact != null) { 141 if (sortMap.containsKey(resultArtifact.getId())) { 142 sortMap.get(resultArtifact.getId()).addHit(); 143 } else { 144 sortMap.put(resultArtifact.getId(), new ArtifactWithWeight(resultArtifact)); 145 } 146 } 147 } 148 149 List<ArtifactWithWeight> artifacts = new ArrayList<ArtifactWithWeight>(sortMap.values()); 150 Collections.sort(artifacts); 151 152 for (ArtifactWithWeight item : artifacts) { 153 result.add(item.getArtifact()); 154 } 155 return result; 156 } 157 158 protected NuxeoArtifact resolveInTree(CoreSession session, String distribId, NuxeoArtifact matchingArtifact, 159 String searchedType) { 160 String cType = matchingArtifact.getArtifactType(); 161 if (cType.equals(searchedType)) { 162 return matchingArtifact; 163 } 164 BaseNuxeoArtifactDocAdapter docAdapter = (BaseNuxeoArtifactDocAdapter) matchingArtifact; 165 DocumentModel doc = docAdapter.getDoc(); 166 List<DocumentModel> parents = session.getParentDocuments(doc.getRef()); 167 Collections.reverse(parents); 168 for (DocumentModel parent : parents) { 169 if (parent.getType().equals(searchedType)) { 170 return mapDoc2Artifact(parent); 171 } 172 } 173 return null; 174 } 175 176 protected NuxeoArtifact resolveInTree(CoreSession session, String distribId, 177 DocumentationItem matchingDocumentationItem, String searchedType) { 178 DistributionSnapshot snap = Framework.getLocalService(SnapshotManager.class).getSnapshot(distribId, session); 179 String targetId = matchingDocumentationItem.getTarget(); 180 String targetType = matchingDocumentationItem.getTargetType(); 181 NuxeoArtifact artifact; 182 if (targetType.equals(BundleGroup.TYPE_NAME)) { 183 artifact = snap.getBundleGroup(targetId); 184 } else if (targetType.equals(BundleInfo.TYPE_NAME)) { 185 artifact = snap.getBundle(targetId); 186 } else if (targetType.equals(ComponentInfo.TYPE_NAME)) { 187 artifact = snap.getComponent(targetId); 188 } else if (targetType.equals(ExtensionPointInfo.TYPE_NAME)) { 189 artifact = snap.getExtensionPoint(targetId); 190 } else if (targetType.equals(ExtensionInfo.TYPE_NAME)) { 191 artifact = snap.getContribution(targetId); 192 } else if (targetType.equals(ServiceInfo.TYPE_NAME)) { 193 artifact = snap.getService(targetId); 194 } else { 195 artifact = null; 196 } 197 return resolveInTree(session, distribId, artifact, searchedType); 198 } 199 200}