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