001package org.deepamehta.plugins.littlehelpers; 002 003import de.deepamehta.core.RelatedTopic; 004import java.util.logging.Logger; 005import java.util.List; 006 007import javax.ws.rs.GET; 008import javax.ws.rs.Path; 009import javax.ws.rs.PathParam; 010import javax.ws.rs.Produces; 011import javax.ws.rs.Consumes; 012 013import de.deepamehta.core.Topic; 014import de.deepamehta.core.TopicType; 015 016import de.deepamehta.core.osgi.PluginActivator; 017import de.deepamehta.core.service.Inject; 018import de.deepamehta.plugins.workspaces.WorkspacesService; 019import java.util.ArrayList; 020import javax.ws.rs.core.MediaType; 021 022 023/** 024 * @author Malte Reißig (<malte@mikromedia.de>) 025 * @website http://github.com/mukil/dm4-littlehelpers 026 * @version 0.1.0 - compatible with DeepaMehta 4.5 027 * 028 */ 029 030@Path("/helpers") 031@Consumes(MediaType.APPLICATION_JSON) 032@Produces(MediaType.APPLICATION_JSON) 033public class LittleHelpersPlugin extends PluginActivator implements LittleHelpersService { 034 035 private Logger log = Logger.getLogger(getClass().getName()); 036 037 // --- DeepaMehta Standard URIs 038 039 /** private final static String CHILD_URI = "dm4.core.child"; 040 private final static String PARENT_URI = "dm4.core.parent"; 041 private final static String AGGREGATION = "dm4.core.aggregation"; **/ 042 043 @Inject WorkspacesService wsService; 044 045 @GET 046 @Override 047 @Path("/suggest/topics/{input}") 048 public List<SuggestionViewModel> getTopicSuggestions(@PathParam("input") String query) { 049 if(query == null || query.length() < 2) throw new IllegalArgumentException("To receive " 050 + "suggestions, please provide at least two characters."); 051 List<SuggestionViewModel> suggestions = new ArrayList<SuggestionViewModel>(); 052 // three explicit search for topicmap name, usernames and note-titles ### add IndexMode.FULLTEXT_KEY ? 053 List<Topic> results = getTopicSuggestions(query, "dm4.topicmaps.name"); 054 results.addAll(getTopicSuggestions(query, "dm4.notes.title")); 055 results.addAll(getTopicSuggestions(query, "dm4.accesscontrol.username")); 056 // append the results of a generic fulltext search 057 List<Topic> naives = dms.searchTopics(query + "*", null); 058 if (naives != null) { 059 log.info("Naive search " + naives.size() + " length"); 060 results.addAll(naives); 061 } 062 // 063 log.info("> Checking for searchable units.. in " + results.size() ); 064 List<Topic> new_results = findSearchableUnits(results); 065 for (Topic t : new_results) { 066 log.fine("Suggesting \"" + t.getSimpleValue() + "\" topics (workspace=" + wsService.getAssignedWorkspace(t.getId())+ ")"); 067 suggestions.add(new SuggestionViewModel(t, wsService.getAssignedWorkspace(t.getId()))); 068 } 069 log.info("Suggesting " + suggestions.size() + " topics for input: " + query); 070 return suggestions; 071 } 072 073 @GET 074 @Override 075 @Path("/suggest/topics/{input}/{typeUri}") 076 public List<Topic> getTopicSuggestions(@PathParam("input") String query, 077 @PathParam("typeUri") String typeUri) { 078 return dms.searchTopics(query + "*", typeUri); 079 } 080 081 // -- 082 // --- Helper Methods taken from the WebclientPlugin.java by Jörg Richter 083 // -- 084 085 private List<Topic> findSearchableUnits(List<? extends Topic> topics) { 086 List<Topic> searchableUnits = new ArrayList<Topic>(); 087 for (Topic topic : topics) { 088 if (searchableAsUnit(topic)) { 089 searchableUnits.add(topic); 090 } else { 091 List<RelatedTopic> parentTopics = topic.getRelatedTopics((String) null, "dm4.core.child", 092 "dm4.core.parent", null, 0).getItems(); 093 if (parentTopics.isEmpty()) { 094 searchableUnits.add(topic); 095 } else { 096 searchableUnits.addAll(findSearchableUnits(parentTopics)); 097 } 098 } 099 } 100 return searchableUnits; 101 } 102 103 private boolean searchableAsUnit(Topic topic) { 104 TopicType topicType = dms.getTopicType(topic.getTypeUri()); 105 Boolean searchableAsUnit = (Boolean) getViewConfig(topicType, "searchable_as_unit"); 106 return searchableAsUnit != null ? searchableAsUnit.booleanValue() : false; // default is false 107 } 108 109 /** 110 * Read out a view configuration setting. 111 * <p> 112 * Compare to client-side counterpart: function get_view_config() in webclient.js 113 * 114 * @param topicType The topic type whose view configuration is read out. 115 * @param setting Last component of the setting URI, e.g. "icon". 116 * 117 * @return The setting value, or <code>null</code> if there is no such setting 118 */ 119 private Object getViewConfig(TopicType topicType, String setting) { 120 return topicType.getViewConfig("dm4.webclient.view_config", "dm4.webclient." + setting); 121 } 122 123}