package ecologylab.bigsemantics.actions; import java.io.IOException; import java.util.HashMap; import java.util.List; import ecologylab.appframework.types.prefs.Pref; import ecologylab.bigsemantics.actions.SemanticAction; import ecologylab.bigsemantics.actions.SemanticActionStandardMethods; import ecologylab.bigsemantics.collecting.DownloadStatus; import ecologylab.bigsemantics.gui.InteractiveSpace; import ecologylab.bigsemantics.metadata.Metadata; import ecologylab.bigsemantics.metadata.builtins.Clipping; import ecologylab.bigsemantics.metadata.builtins.RichDocument; import ecologylab.bigsemantics.metadata.builtins.Document; import ecologylab.bigsemantics.metadata.builtins.DocumentClosure; import ecologylab.bigsemantics.metadata.builtins.ImageClipping; import ecologylab.bigsemantics.metadata.builtins.TextClipping; import ecologylab.bigsemantics.model.text.TermWithScore; import ecologylab.generic.Continuation; /** * */ /** * @author andruid, rhema * This semantic action visualizes clippings of a compound document. * For now, we visualize one clipping. */ // // public class VisualizeClippings extends SemanticAction implements SemanticActionStandardMethods { public VisualizeClippings() { } @Override public String getActionName() { return VISUALIZE_CLIPPINGS; } //need a score function for text that I can also use for clippings... public double scoreTextAtPoint(String text, int x, int y) { if(!Pref.lookupBoolean(Metadata.USE_SEMANTIC_SEARCH_PREF)) return 0; //just idf //TermDictionary.getTermForUnsafeWord("sanity") //getTermsFromInteractiveSpace //with InteractiveSpace interactiveSpace = sessionScope.getInteractiveSpace(); TermWithScore[] terms = interactiveSpace.getTermScoresAtPoint(x, y); //should add somet sort of stemming here or something... :( HashMap<String, TermWithScore> termHash = new HashMap<String, TermWithScore>(); for(TermWithScore term: terms) { // debug(term.getWord()); termHash.put(term.getWord(), term); } String[] words = text.split(" "); double score = 0; for(String word : words) { word = word.replaceAll("[^A-Za-z]", ""); word = word.toLowerCase(); // debug("Does the hash contain:"+word+"?"); if(termHash.containsKey(word)) { score += termHash.get(word).getScore(); // debug("yes"); } else { // debug("no"); } } return score; } public String gistForTextAndPosition(int x, int y, int numWords, String text) { //debug("make gist at "+x+","+y+" with "+numWords+" and the text "+text); String[] words = text.split(" "); double bestScore = -1; String bestGist = ""; for(int wordOffset=0; wordOffset<Math.min(words.length, numWords+words.length); wordOffset++) { String wholeGist = ""; int wordCount = 0; //this should be repeated with different indexes //calkins1942@gmail.com for(int i=wordOffset; i<words.length; i++) { String word = words[i]; if(wordCount > 0) wholeGist += " "; wholeGist += word; wordCount++; if(wordCount >= numWords) break; } ///add up total score here... double gScore = scoreTextAtPoint(wholeGist, x, y); //debug("check dist:"+wholeGist +" gets the score:"+gScore); if(gScore > bestScore) { bestScore = gScore; bestGist = wholeGist; } } return bestGist; } @Override public void handleError() { } enum SelectionMethod { FIFO,SITUATED_SIMILARITY } //TODO add arguments: // selection method: default fifo // filters: text only, picture only.... // number of clippings added default 1... for searches mainly. // max_extent: //method for display. Currently using FIFO. Also add filters: like text only @Override public Object perform(Object obj) throws IOException { if (sessionScope.isService()) { return null; } InteractiveSpace interactiveSpace = sessionScope.getInteractiveSpace(); Document sourceDocument = resolveSourceDocument(); DocumentClosure closure = documentParser.getDocumentClosure(); SelectionMethod selectionMethod = SelectionMethod.FIFO; if (closure.isDnd() && interactiveSpace != null) { debug("This is a drop. Finding clippings to visualize."); //TODO make something that waits for images to be downloaded RichDocument compoundSource = null; if(sourceDocument instanceof RichDocument) { compoundSource = (RichDocument) sourceDocument; } TextClipping bestTextClipping = null; ImageClipping bestImageClipping = null; double bestTextClippingScore = -1; List<Clipping> clippings = compoundSource.getClippings(); if(clippings != null) { for (Clipping clipping : clippings) { if (clipping instanceof TextClipping) { /* //debug("Found text clipping"); if(selectionMethod == SelectionMethod.FIFO) { if(bestTextClipping == null) { bestTextClipping = (TextClipping)clipping; } } */ double textClippingScore = scoreTextAtPoint(((TextClipping)clipping).getText(), closure.getDndPoint().getX(), closure.getDndPoint().getY()); if(textClippingScore > bestTextClippingScore)//tbd, normalize on lenght { bestTextClippingScore = textClippingScore; bestTextClipping = (TextClipping) clipping; } } else if(clipping instanceof ImageClipping) { //debug("Found image clipping"); if(selectionMethod == SelectionMethod.FIFO) { if(bestImageClipping == null) { bestImageClipping = (ImageClipping)clipping; } } } } //TODO: Handle piles et cetera if(bestImageClipping != null && bestImageClipping.getMedia() != null) { //try to download or make closure et cetera... sessionScope.getOrConstructImage(bestImageClipping.getMedia().getLocation()); DocumentClosure bestImageClippingClosure = bestImageClipping.getMedia().getOrConstructClosure(); bestImageClippingClosure.addContinuation(new DropImageContinuation(bestImageClipping)); bestImageClippingClosure.setDndPoint(closure.getDndPoint()); bestImageClippingClosure.queueDownload(); if(bestImageClipping.getMedia().getDownloadStatus() == DownloadStatus.DOWNLOAD_DONE) { debug("image already exists"); interactiveSpace.createAndAddClipping((ImageClipping)bestImageClipping, closure.getDndPoint().getX(), closure.getDndPoint().getY()); } return null; } if(bestTextClipping != null) { //preprocess at this point to make smaller... TextClipping gistWithContext = (TextClipping)bestTextClipping; gistWithContext.setText(gistForTextAndPosition(closure.getDndPoint().getX(),closure.getDndPoint().getY(),10,gistWithContext.getText())); interactiveSpace.createAndAddClipping(gistWithContext, closure.getDndPoint().getX(), closure.getDndPoint().getY()); return null; } } else { debug("No clippings were found. Nothing visualized."); } debug("J"); } else { debug("Ignore because not a drop"); } return null; } class DropImageContinuation implements Continuation<DocumentClosure> { ImageClipping bestImageClipping; public DropImageContinuation() { super(); } public DropImageContinuation(ImageClipping imageClipping) { super(); bestImageClipping = imageClipping; } @Override public void callback(DocumentClosure o) { //debug("Here is the url for the document that should be showing up as the source:"+bestImageClipping.getSourceDoc().getLocation()); // debug(""+bestImageClipping.getSourceDoc().setTitle(title)); //TODO we may want to download all of the images first before picking one. //for now, we assume that we just display anything that uses this as its continuation. //bestImageClipping.getSourceDoc().setTitle("SWIINGERS ARE FUNNY!!!"); //bestImageClipping.setSourceDoc(sessionScope.getOrConstructDocument((bestImageClipping.getSourceDoc().getDownloadLocation()))); if(bestImageClipping.getSourceDoc() == null) debug("There is no source document for this image"); InteractiveSpace interactiveSpace = sessionScope.getInteractiveSpace(); interactiveSpace.createAndAddClipping((ImageClipping)bestImageClipping, o.getDndPoint().getX(), o.getDndPoint().getY()); debug("Dropped image"); } } }