/* * DrakkarKeel - An Enterprise Collaborative Search Platform * * The contents of this file are subject under the terms described in the * DRAKKARKEEL_LICENSE file included in this distribution; you may not use this * file except in compliance with the License. * * 2013-2014 DrakkarKeel Platform. */ package drakkar.mast.retrieval; import drakkar.oar.DocumentMetaData; import drakkar.oar.facade.event.FacadeDesktopListener; import drakkar.oar.security.DrakkarSecurity; import static drakkar.oar.util.KeyMessage.*; import drakkar.oar.util.KeySearchable; import drakkar.oar.util.OutputMonitor; import drakkar.oar.util.Utilities; import drakkar.mast.IndexException; import drakkar.mast.SearchException; import static drakkar.mast.retrieval.FileIndexable.*; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.store.FSDirectory; import pl.infovide.SVNIndexUpdater.Index; import pl.infovide.SVNIndexUpdater.IndexRepositoryList; import pl.infovide.SVNIndexer.ConfigReaderException; import pl.infovide.SVNInfo.ConfProviderException; import pl.infovide.SVNInfo.ConfigurationProvider; import pl.infovide.SVNInfo.ConfigurationProviderSearch; import pl.infovide.SVNSearcher.IndexSearcherSVN; import pl.infovide.SVNSearcher.SearchResultBean; import pl.infovide.SVNSearcher.SearchResultEntry; /** * Contexto para indexar y buscar en repositorios SVN */ public class SVNContext extends CVSContextable { private Index index; private ConfigurationProvider provider; private IndexRepositoryList indexList; long indexedDocs = 0; String message = null; int loadedDocs = 0; Properties properties; private IndexSearcherSVN searcher; private SearchResultBean searchResultBean; /** * * @param listener */ public SVNContext(FacadeDesktopListener listener) { super(listener); defaultIndexPath = "./index/svn/"; } /** * */ public SVNContext() { defaultIndexPath = "./index/svn/"; } /** * {@inheritDoc} */ public long makeIndex() throws IndexException { if (safeToBuildIndex(new File(this.properties.getProperty("indexPath")), MAKE_INDEX)) { ConfigurationProvider.setProp(getProperties()); try { this.indexedDocs = build(); } catch (ConfigReaderException ex) { OutputMonitor.printStream("", ex); } message = "SVNIndexer finished"; OutputMonitor.printLine(message, OutputMonitor.INFORMATION_MESSAGE); this.notifyTaskProgress(INFORMATION_MESSAGE, message); } else { message = "Is not safe to build index in the path selected"; OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } return indexedDocs; } /** * {@inheritDoc} */ public boolean loadIndex(File indexPath) throws IOException, IndexException { IndexReader reader = null; boolean flag = false; if (!indexPath.isDirectory() || !indexPath.exists() || indexPath == null || IndexReader.indexExists(FSDirectory.open(indexPath)) == false) { message = "Not found index in default index path"; OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); throw new IndexException(message); } else { reader = IndexReader.open(FSDirectory.open(indexPath)); loadedDocs = reader.numDocs(); reader.close(); message = "Loading SVN index..."; OutputMonitor.printLine(message, OutputMonitor.INFORMATION_MESSAGE); this.notifyTaskProgress(INFORMATION_MESSAGE, message); try { Thread.sleep(2000); } catch (InterruptedException ex) { message = "Error loading index: " + ex.toString(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } message = "Total of documents of the index: " + loadedDocs; OutputMonitor.printLine(message, OutputMonitor.INFORMATION_MESSAGE); this.notifyTaskProgress(INFORMATION_MESSAGE, message); flag = true; this.notifyLoadedDocument(loadedDocs); } return flag; } /** * {@inheritDoc} */ public boolean loadIndex() throws IndexException, IOException { IndexReader reader = null; File defaultFile = new File(this.defaultIndexPath); boolean flag = false; if (!defaultFile.isDirectory() || !defaultFile.exists() || defaultFile == null || IndexReader.indexExists(FSDirectory.open(defaultFile)) == false) { message = "Not found index in default index path"; OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); throw new IndexException(message); } else { reader = IndexReader.open(FSDirectory.open(defaultFile)); loadedDocs = reader.numDocs(); reader.close(); message = "Loading SVN index..."; OutputMonitor.printLine(message, OutputMonitor.INFORMATION_MESSAGE); this.notifyTaskProgress(INFORMATION_MESSAGE, message); try { Thread.sleep(2000); } catch (InterruptedException ex) { message = "Error loading index: " + ex.toString(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } message = "Total of documents of the index: " + loadedDocs; OutputMonitor.printLine(message, OutputMonitor.INFORMATION_MESSAGE); this.notifyTaskProgress(INFORMATION_MESSAGE, message); flag = true; this.notifyLoadedDocument(loadedDocs); } return flag; } private boolean safeToBuildIndex(File indexPath, int operation) throws IndexException { boolean flag = true; try { String idxpath = indexPath.getPath(); File dir = indexPath.getParentFile(); if (!dir.exists()) { if (!dir.mkdirs()) { //ensure that the index folder exists flag = false; message = "Could not create the index folders at: " + dir.getPath() + ".\n" + "Aborting indexing process."; OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); throw new IndexException(message); } } else if (IndexReader.indexExists(FSDirectory.open(indexPath))) { switch (operation) { case MAKE_INDEX: message = "Overwriting index " + idxpath + "\n"; OutputMonitor.printLine(message, OutputMonitor.INFORMATION_MESSAGE); this.notifyTaskProgress(INFORMATION_MESSAGE, message); Utilities.deleteFiles(indexPath); flag = true; break; case ADD_INDEX: message = "Appending new files to index " + idxpath + "\n"; OutputMonitor.printLine(message, OutputMonitor.INFORMATION_MESSAGE); this.notifyTaskProgress(INFORMATION_MESSAGE, message); flag = true; break; default: message = "Not building index " + idxpath + "\n"; OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); flag = false; throw new IndexException(message); } } else if (operation == ADD_INDEX) { flag = false; message = "Not exist Lucene index in this address" + indexPath; this.notifyTaskProgress(ERROR_MESSAGE, message); throw new IndexException(message); } } catch (IOException ex) { OutputMonitor.printStream("", ex); } return flag; } private long build() throws ConfigReaderException { provider = new ConfigurationProvider(); try { provider.getConfiguration(); } catch (ConfProviderException e) { message = "SVNIndexer failed:" + e.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } catch (FileNotFoundException e) { message = "SVNIndexer failed:" + e.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } catch (IOException e) { message = "SVNIndexer failed:" + e.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } index = new Index(); //finding existed index or create new in given directory try { index.prepareIndex(provider.getIndexPath()); } catch (IOException ex) { message = "SVNIndexer failed. Index is not prepared:" + ex.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } message = "Indexing to: " + provider.getIndexPath(); OutputMonitor.printLine(message, OutputMonitor.INFORMATION_MESSAGE); this.notifyTaskProgress(INFORMATION_MESSAGE, message); indexList = new IndexRepositoryList(provider.getIndexPath()); try { indexList.setIndexRepository(provider.getUrl(), provider.getUser(), DrakkarSecurity.decryptPassword(provider.getPassword()), provider.getDirectPath()); indexList.updateIndexedRepositories(provider.getUser(), DrakkarSecurity.decryptPassword(provider.getPassword())); int countIndexed = 0; try { boolean load = loadIndex(new File(provider.getIndexPath())); if (load) { countIndexed = loadedDocs; } } catch (IndexException ex) { OutputMonitor.printStream("", ex); } this.notifyIndexedDocument(countIndexed); return countIndexed; } catch (IOException ex) { message = "SVNIndexer failed:" + ex.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } catch (ConfigReaderException e) { message = "SVNIndexer failed:" + e.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } catch (ClassNotFoundException e) { message = "SVNIndexer failed:" + e.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } return 0; } /** * * @return */ public Properties getProperties() { return properties; } /** * * @param properties */ public void setProperties(Properties properties) { this.properties = properties; } @Override public ArrayList<DocumentMetaData> search(String query, String sort, String fileType, String date, String user, boolean onfileBody) throws SearchException { ArrayList<DocumentMetaData> listResults = new ArrayList<DocumentMetaData>(); ConfigurationProviderSearch.setProperties(properties); ConfigurationProviderSearch prov = new ConfigurationProviderSearch(); try { prov.getConfiguration(properties); } catch (ConfProviderException ex) { ex.printStackTrace(); } String indexDirectory = prov.getIndexPath(); String urlRegexp = prov.getUrlRegexp(); String urlReplacement = prov.getUrlReplacement(); searcher = new IndexSearcherSVN(indexDirectory, properties); searchResultBean = new SearchResultBean(); long before = System.currentTimeMillis(); this.searchResultBean.setSort(sort); StringBuffer finallQuery = null; if (query != null) { finallQuery = constructQueryString(query, fileType, date, onfileBody, searchResultBean); } if (finallQuery.toString() == null || finallQuery.toString().equals("") || finallQuery.toString().trim().equals("")) { message = "Query empty"; OutputMonitor.printLine(message, OutputMonitor.INFORMATION_MESSAGE); this.notifyTaskProgress(INFORMATION_MESSAGE, message); } /*Getting phrase from all query */ String simpleQuery = makePhraseFromQuery(query); Object[] res = null; try { res = searcher.search(finallQuery.toString(), user, sort, true); } catch (OutOfMemoryError e) { message = "Server isn't prepared for that amount of results.\n Try query which gives less results. More info in logs." + e.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } catch (BooleanQuery.TooManyClauses e) { message = "SVN Searcher configuration isn't prepared for this amount of clauses.\n " + "Increas \'maxClouseCount\' property in your properties file\n" + e.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } catch (RuntimeException e) { message = "Please use other criterion of sort, this one is not served in this index.\n " + e.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); // all other exceptions are logged only for application administrator. SVNSearcher user see only one type of message. } catch (Exception e) { message = "SVNSearcher isn't configured correctly. Please contact with administrator - more details in SVNSearcher logs. " + e.getMessage(); OutputMonitor.printLine(message, OutputMonitor.ERROR_MESSAGE); this.notifyTaskProgress(ERROR_MESSAGE, message); } @SuppressWarnings("unchecked") ArrayList<SearchResultEntry> result = (ArrayList<SearchResultEntry>) res[0]; Integer numberOfDocuments = (Integer) res[1]; Float searchTime = (Float) res[2]; Integer numberOfFoundDocuments = (Integer) res[3]; analyzeQuery(simpleQuery, result, urlRegexp, urlReplacement); /// @li Creating Bean with all results if (res[3] != null) { this.searchResultBean.setSearchTime(searchTime); } long after = System.currentTimeMillis(); this.searchResultBean.setAllTime(new Float((float) (after - before) / 1000f)); this.searchResultBean.setSimplePhrase(simpleQuery); this.searchResultBean.setResult(result); this.searchResultBean.setNumberOfAllDocuments(numberOfDocuments.intValue()); this.searchResultBean.setNumberOfFoundDocuments(numberOfFoundDocuments.intValue()); listResults = saveDocumentMetadata(searchResultBean.getResult()); return listResults; } /** * This method checks if 'query' comes from Advanced Searching site. If yes * and advanced options was used, then add to query special characters * ("+Name" or "+Type" and put 'query phrase' into '(' ')' ). Result of this * parsing is written as 'QueryString' in result bean. * * @param request Request for the servlet * @param searchResultBean Bean which stores result and information about * one searching process * @return Final query which is parsed query if request was from * AdvancedSearching site, or returns 'search' field if there was no * advanced option used. */ private StringBuffer constructQueryString(String query, String fileType, String date, boolean fileBody, SearchResultBean searchResultBean) { StringBuffer finallQuery = new StringBuffer(); boolean advancedSearch = fileBody; /* * Parsing Date to format : +Date[yyyymmdd TO yyymmdd] */ if (date != null && !date.equals("") && !date.equals("ALL")) { Date today = new Date(System.currentTimeMillis()); java.text.SimpleDateFormat todaySimple = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z"); String todayS = todaySimple.format(today); String[] tableToday = todayS.split(" "); int y = Integer.parseInt(tableToday[0].substring(0, 4)); int m = Integer.parseInt(tableToday[0].substring(5, 7)); int d = Integer.parseInt(tableToday[0].substring(8, 10)); int yFrom = y; int mFrom = m; if (date.equals("1MON")) { mFrom = m - 1; if (mFrom <= 0) { mFrom = 12 + mFrom; yFrom -= 1; } } else if (date.equals("3MON")) { mFrom = m - 3; if (mFrom <= 0) { mFrom = 12 + mFrom; yFrom -= 1; } } else if (date.equals("6MON")) { mFrom = m - 6; if (mFrom <= 0) { mFrom = 12 + mFrom; yFrom -= 1; } } else if (date.equals("12MON")) { mFrom = m - 12; if (mFrom <= 0) { mFrom = 12 + mFrom; yFrom -= 1; } } String dToday = ("" + d).length() < 2 ? ("0" + d) : ("" + d); String mToday = ("" + m).length() < 2 ? ("0" + m) : ("" + m); String mFromS = ("" + mFrom).length() < 2 ? ("0" + mFrom) : ("" + mFrom); String fromString = ("" + yFrom) + mFromS + dToday; String todayString = ("" + y) + mToday + dToday; finallQuery.append(" +Date:[" + fromString + " TO " + todayString + "] "); advancedSearch = true; } if ((fileType != null) && (!fileType.equals(""))) { if (!fileType.equals("ALL")) { finallQuery.append(" +Type:" + fileType); advancedSearch = true; searchResultBean.setFileType(fileType); } } else { /* Cleanup empty string from parameter */ searchResultBean.setFileType(null); } if (advancedSearch && query != null && !(query.trim().equals(""))) { //if (fileBody != null && fileBody.equals("true")) { if (fileBody) { finallQuery.append(" +FileBody:(" + query + ")"); } else { finallQuery.append(" +(" + query + ")"); } } else { finallQuery.append(query); } searchResultBean.setQueryString(finallQuery.toString().trim()); return finallQuery; } /** * This method parse 'phrase' (equals to text from 'search' field in web * site form) from given query. This 'phrase' is needed for field 'search' * in AdvancedSearching site and for find (and bold) key words in found * files. * * @param search Text from 'search' field in web site form. * @return If there was no advanced options used, then returns given * 'search'. In other was takes 'phrase' between '(' and ')'. */ private String makePhraseFromQuery(String search) { int lstart = search.indexOf("("); int lend = search.lastIndexOf(")"); String simplePhrase = ""; if (lstart != -1 && lend != -1 && lstart <= lend) { simplePhrase = search.substring(lstart + 1, lend); } else { simplePhrase = search; } return simplePhrase; } private void analyzeQuery(String simpleQuery, ArrayList<SearchResultEntry> result, String urlRegexp, String urlReplacement) { //cleaning special characters String[] tmpQuery = simpleQuery.split(" "); ArrayList<String> withNoSpecial = new ArrayList<String>(); for (String string : tmpQuery) { string = string.replaceAll(" ", ""); string = string.replaceAll("\\{", ""); string = string.replaceAll("\\}", ""); string = string.replaceAll("\\[", ""); string = string.replaceAll("\\]", ""); if (string.length() != 0) { withNoSpecial.add(string); } } // end cleaning String[] splitedQuery = new String[withNoSpecial.size()]; splitedQuery = withNoSpecial.toArray(splitedQuery); ArrayList<String> boldStrings = new ArrayList<String>(); boolean inQuote = false; String boldString = ""; boolean ifMinusChar = false; /// @li Analyze user query // eg: +Name:/clients/lafarge +Type:XLS +(lafarge) for (int i = 0; i < splitedQuery.length; ++i) { if (splitedQuery[i] == null || splitedQuery[i].length() == 0 || splitedQuery[i].equals("")) { continue; } if (splitedQuery[i].equals("\t") || splitedQuery[i].equals("\n") || splitedQuery[i].equals(" ") || splitedQuery[i].equals("\r") || splitedQuery[i].equals("\b") || splitedQuery[i].equals("\f")) { continue; } splitedQuery[i] = splitedQuery[i].trim(); if (inQuote == false && (splitedQuery[i].equals("AND") == true || splitedQuery[i].equals("OR") == true || splitedQuery[i].equals("NOT") == true || splitedQuery[i].equals("TO") == true)) { continue; } if (splitedQuery[i].length() >= 3) { if (splitedQuery[i].charAt(0) == '\"' && (splitedQuery[i].charAt(splitedQuery[i].length() - 1) == '\"')) { boldStrings.add(splitedQuery[i].substring(1, splitedQuery[i].length() - 1)); ifMinusChar = false; continue; } } if (inQuote == false) { if (splitedQuery[i].charAt(0) == '-') { ifMinusChar = true; splitedQuery[i] = splitedQuery[i].replace('-', ' ').trim(); continue; } else if (splitedQuery[i].charAt(0) == '+') { ifMinusChar = false; splitedQuery[i] = splitedQuery[i].replace('+', ' ').trim(); continue; } } if (splitedQuery[i].charAt(0) == '\"') { inQuote = true; boldString = splitedQuery[i].replace('\"', ' ').trim(); continue; } if (splitedQuery[i].indexOf(':') >= 0) { if (!(splitedQuery[i].indexOf("\\:") >= 0)) { inQuote = true; boldString = splitedQuery[i].substring(splitedQuery[i].indexOf(':'), splitedQuery[i].length()); continue; } } if (splitedQuery[i].charAt(splitedQuery[i].length() - 1) == '\"') { inQuote = false; if (boldString.length() > 0) { if (boldString.charAt(boldString.length() - 1) != ' ') { boldString += " "; } } boldString += splitedQuery[i].substring(0, splitedQuery[i].length() - 1); if (ifMinusChar == false) { boldStrings.add(boldString); } ifMinusChar = false; continue; } if (inQuote == true) { boldString += " " + splitedQuery[i] + " "; continue; } if (splitedQuery[i].length() != 0 && splitedQuery[i].charAt(0) == '(') { splitedQuery[i] = splitedQuery[i].substring(1, splitedQuery[i].length()); } if (splitedQuery[i].length() != 0 && splitedQuery[i].charAt(splitedQuery[i].length() - 1) == ')') { splitedQuery[i] = splitedQuery[i].substring(0, splitedQuery[i].length() - 1); } if (splitedQuery[i].length() != 0 && splitedQuery[i].charAt(0) == '[') { splitedQuery[i] = splitedQuery[i].substring(1, splitedQuery[i].length()); } if (splitedQuery[i].length() != 0 && splitedQuery[i].charAt(splitedQuery[i].length() - 1) == ']') { splitedQuery[i] = splitedQuery[i].substring(0, splitedQuery[i].length() - 1); } if (splitedQuery[i].length() != 0 && splitedQuery[i].charAt(0) == '{') { splitedQuery[i] = splitedQuery[i].substring(1, splitedQuery[i].length()); } if (splitedQuery[i].length() != 0 && splitedQuery[i].charAt(splitedQuery[i].length() - 1) == '}') { splitedQuery[i] = splitedQuery[i].substring(0, splitedQuery[i].length() - 1); } if (ifMinusChar == false) { boldStrings.add(splitedQuery[i]); } ifMinusChar = false; } shrinkingContent(boldStrings, result, urlRegexp, urlReplacement); } private void shrinkingContent(ArrayList<String> boldStrings, ArrayList<SearchResultEntry> result, String urlRegexp, String urlReplacement) { /// this variable decide to put '...' on the end of each file body, or not. boolean isEndOfBody = false; /// @li Documents content shrinking for (int i = 0; i < result.size(); ++i) { isEndOfBody = false; SearchResultEntry entry = result.get(i); String fileBody = entry.getFileBody(); String name = entry.getFileName().replaceAll(urlRegexp, urlReplacement); entry.setFileName(name); int from = 0, to = 0; if (fileBody != null) { Pattern pattern = null; Matcher matcher = null; if (boldStrings.size() > 0) { try { pattern = Pattern.compile("(?i)\\b" + boldStrings.get(0) + "\\b"); matcher = pattern.matcher(fileBody); } catch (PatternSyntaxException e) { this.searchResultBean.setError("Incorrect query syntax: " + e.getMessage()); } if (pattern != null && matcher != null && matcher.find() == true) { if (matcher.start() + 300 / 2 >= fileBody.length()) { to = fileBody.length(); isEndOfBody = true; } else { to = matcher.start() + 300 / 2; } if (matcher.start() - 300 / 2 <= 0) { from = 0; if ((to + 300 / 2 - matcher.start()) >= fileBody.length()) { to = fileBody.length(); isEndOfBody = true; } else { to += 300 / 2 - matcher.start(); } } else { from = matcher.start() - 300 / 2; if (matcher.start() + 300 / 2 >= fileBody.length()) { from -= 300 / 2 - (fileBody.length() - matcher.start()); if (from < 0) { from = 0; } } } } else { from = 0; if (fileBody.length() <= 600 / 2) { to = fileBody.length(); isEndOfBody = true; } else { to = 600 / 2; } } } else { if (300 <= fileBody.length()) { to = 300; } else { to = fileBody.length(); isEndOfBody = true; } } fileBody = fileBody.substring(from, to); fileBody = fileBody.replaceAll("&", "&"); fileBody = fileBody.replaceAll("<", "<"); fileBody = fileBody.replaceAll(">", ">"); fileBody = fileBody.replaceAll("\"", """); fileBody = fileBody.replaceAll("'", "'"); // @INFO: this part of code, can be not optimize. /// @li Bolder for key word. for (int ii = 0; ii < boldStrings.size(); ++ii) { StringBuffer temp = new StringBuffer(fileBody.length()); try { pattern = Pattern.compile("(?i)\\b" + boldStrings.get(ii) + "\\b"); } catch (PatternSyntaxException e) { continue; } matcher = pattern.matcher(fileBody); int start2 = 0; while (true) { if (matcher.find() == false) { if (start2 != fileBody.length()) { temp.append(fileBody.substring(start2, fileBody.length())); } start2 = fileBody.length(); break; } temp.append(fileBody.substring(start2, matcher.start())); temp.append("<b>" + fileBody.substring(matcher.start(), matcher.end()) + "</b>"); start2 = matcher.end(); } fileBody = temp.toString(); } /* * Start - Making endLines in equal intervals ('lineLenght') */ fileBody = fileBody.replaceAll("\n", " "); fileBody = fileBody.replaceAll("([ \t\n\r\f]*<BR>)+", ""); int lineLenght = 70; for (; lineLenght < fileBody.length(); lineLenght += 70) { /// how long can be word for find space after them at the end of each line. int maxWordLength = 20; int li2 = 0; /// looking for space - line should be ended when space or ';' or ',' /// but if 'maxWordLength' is shorter than iterator on last word in line, then the word is ended /// with no space on the end. for (; li2 < maxWordLength; li2++) { if (fileBody.length() > (li2 + lineLenght + 1)) { char checkedChar = fileBody.charAt(li2 + lineLenght); if (checkedChar == ' ' || checkedChar == ';' || checkedChar == ',') { lineLenght = lineLenght + li2; break; } } } String beforeString = fileBody.substring(0, lineLenght); String afterString = fileBody.substring(lineLenght); fileBody = beforeString + "<BR>" + afterString; } /* * End */ if (!isEndOfBody) { fileBody = fileBody + "..."; } entry.setFileBody(fileBody); } else { entry.setFileBody(""); } String pom = name; pom = pom.toLowerCase(); String auth = entry.getAuthor(); if (auth != null) { auth = auth.toLowerCase(); } entry.setBoldName(name); for (int ii = 0; ii < boldStrings.size(); ++ii) { String pom2 = boldStrings.get(ii).toLowerCase(); if (pom.lastIndexOf(pom2) > 0) { entry.setBoldName(name.substring(0, pom.lastIndexOf(pom2)) + "<b>" + name.substring(pom.lastIndexOf(pom2), pom.lastIndexOf(pom2) + pom2.length()) + "</b>" + name.substring((pom.lastIndexOf(pom2) + pom2.length()))); } pom2 = boldStrings.get(ii).toLowerCase(); if (auth != null && auth.equals(pom2)) { entry.setAuthor("<b>" + entry.getAuthor() + "</b>"); } } } } private ArrayList<DocumentMetaData> saveDocumentMetadata(ArrayList<SearchResultEntry> result) { DocumentMetaData metaData; ArrayList<DocumentMetaData> list = new ArrayList<DocumentMetaData>(); String name, path, synthesis, author, type = null; String lastModified= null; float size = 0; int numberIndex; int idsearcher = KeySearchable.SVN_SEARCHER; double score; for (int i = 0; i < result.size(); i++) { SearchResultEntry searchResultEntry = result.get(i); name = searchResultEntry.getShortFileName(); author = searchResultEntry.getAuthor(); lastModified = DateFormat.getDateInstance().format(searchResultEntry.getLastModified()); path = searchResultEntry.getFileName(); synthesis = "Last commit by: " + searchResultEntry.getAuthor() + "\n" + "\n" + "Last commit date: " + searchResultEntry.getLastModified() + "\n" + "\n" + "Comment to commit: " + searchResultEntry.getComment() + "\n" + "\n" + "Body: " + searchResultEntry.getFileBody(); score = searchResultEntry.getHitScore(); numberIndex = searchResultEntry.getNumber();//not good.... type = searchResultEntry.getType(); //todo el numberindex y size estan en cero metaData = new DocumentMetaData(author, lastModified, name, path, size, synthesis, type, numberIndex, score, idsearcher); list.add(metaData); } return list; } }