From 4ba00bca9c51eeba003b2e5cfb5351e55c4db26a Mon Sep 17 00:00:00 2001 From: ajermakovics Date: Tue, 23 Aug 2011 22:58:21 +0100 Subject: [PATCH] initial source commit --- instasearch.feature/.project | 17 + instasearch.feature/build.properties | 2 + instasearch.feature/epl-v10.html | 257 ++++ instasearch.feature/feature.xml | 62 + instasearch.site/.project | 17 + instasearch.site/favicon.ico | Bin 0 -> 1406 bytes instasearch.site/index.html | 21 + instasearch.site/site.xml | 18 + instasearch/.classpath | 9 + instasearch/.project | 28 + instasearch/EclipsePreferences.epf | 894 +++++++++++++ instasearch/META-INF/MANIFEST.MF | 33 + instasearch/build.properties | 10 + instasearch/icons/binary.gif | Bin 0 -> 366 bytes instasearch/icons/close.gif | Bin 0 -> 73 bytes instasearch/icons/collapseall.gif | Bin 0 -> 157 bytes instasearch/icons/dates.gif | Bin 0 -> 181 bytes instasearch/icons/down_arrow.gif | Bin 0 -> 52 bytes instasearch/icons/expandall.gif | Bin 0 -> 164 bytes instasearch/icons/filter.gif | Bin 0 -> 211 bytes instasearch/icons/lightbulb.gif | Bin 0 -> 553 bytes instasearch/icons/lucene.gif | Bin 0 -> 335 bytes instasearch/icons/refresh.gif | Bin 0 -> 330 bytes instasearch/icons/remove.gif | Bin 0 -> 163 bytes instasearch/icons/remove_inactive.gif | Bin 0 -> 159 bytes instasearch/icons/sample.gif | Bin 0 -> 983 bytes instasearch/icons/search.gif | Bin 0 -> 347 bytes instasearch/icons/search_results.gif | Bin 0 -> 360 bytes instasearch/icons/syncdb.gif | Bin 0 -> 362 bytes instasearch/icons/update.gif | Bin 0 -> 336 bytes instasearch/icons/web.gif | Bin 0 -> 362 bytes instasearch/icons/workingsets.gif | Bin 0 -> 366 bytes instasearch/lib/lucene-highlighter-1.9.1.jar | Bin 0 -> 24482 bytes instasearch/plugin.properties | 3 + instasearch/plugin.xml | 223 ++++ .../src/it/unibz/instasearch/InstaSearch.java | 126 ++ .../unibz/instasearch/InstaSearchPlugin.java | 353 +++++ .../unibz/instasearch/InstaSearchStartup.java | 42 + .../actions/BuildIndexActionDelegate.java | 24 + .../actions/CheckUpdatesActionDelegate.java | 34 + .../actions/CollapseAllActionDelegate.java | 14 + .../actions/DeleteIndexActionDelegate.java | 24 + .../actions/ExpandAllActionDelegate.java | 14 + .../IncrementalSearchActionDelegate.java | 27 + .../actions/InstaSearchActionDelegate.java | 43 + .../instasearch/actions/OpenSearchDialog.java | 31 + .../actions/PreferencesAction.java | 21 + .../actions/ShowExceptionAction.java | 58 + .../actions/ShowInstaSearchAction.java | 56 + .../actions/VisitHomePageActionDelegate.java | 32 + .../it/unibz/instasearch/indexing/Field.java | 58 + .../instasearch/indexing/FileAnalyzer.java | 83 ++ .../indexing/LengthNormSimilarity.java | 40 + .../instasearch/indexing/QueryAnalyzer.java | 61 + .../indexing/ResourceCollector.java | 104 ++ .../instasearch/indexing/SearchQuery.java | 189 +++ .../instasearch/indexing/SearchResult.java | 59 + .../instasearch/indexing/SearchResultDoc.java | 278 ++++ .../unibz/instasearch/indexing/Searcher.java | 487 +++++++ .../instasearch/indexing/StorageIndexer.java | 393 ++++++ .../indexing/WorkspaceIndexer.java | 503 +++++++ .../indexing/WorkspaceIndexerJDT.java | 468 +++++++ .../indexing/querying/CSVExpander.java | 51 + .../querying/CurrentProjectSetter.java | 55 + .../querying/FieldAliasConverter.java | 90 ++ .../indexing/querying/FileNameSearcher.java | 54 + .../indexing/querying/FilterSetter.java | 113 ++ .../indexing/querying/FolderSearcher.java | 94 ++ .../querying/LastTermQueryPrefixer.java | 75 ++ .../indexing/querying/LowercaseConverter.java | 87 ++ .../querying/ModifiedTimeConverter.java | 134 ++ .../indexing/querying/PhraseSearcher.java | 64 + .../indexing/querying/QueryFuzzifier.java | 86 ++ .../indexing/querying/QueryVisitor.java | 103 ++ .../querying/UppercaseNameExpander.java | 56 + .../indexing/querying/VisitableQuery.java | 133 ++ .../indexing/querying/WorkingSetExpander.java | 52 + .../tokenizers/CamelCaseTokenizer.java | 39 + .../tokenizers/DotSplitTokenizer.java | 40 + .../tokenizers/TermSplitTokenizer.java | 118 ++ .../tokenizers/WordSplitTokenizer.java | 35 + .../tokenizers/standard/CharStream.java | 115 ++ .../tokenizers/standard/FastCharStream.java | 120 ++ .../tokenizers/standard/ParseException.java | 187 +++ .../indexing/tokenizers/standard/ReadMe.txt | 3 + .../standard/StandardTokenizer.java | 209 +++ .../tokenizers/standard/StandardTokenizer.jj | 166 +++ .../standard/StandardTokenizerConstants.java | 58 + .../StandardTokenizerTokenManager.java | 1161 +++++++++++++++++ .../indexing/tokenizers/standard/Token.java | 131 ++ .../tokenizers/standard/TokenMgrError.java | 147 +++ .../instasearch/jobs/CheckUpdatesJob.java | 244 ++++ .../instasearch/jobs/DeleteIndexJob.java | 70 + .../instasearch/jobs/IndexUpdateJob.java | 255 ++++ .../unibz/instasearch/jobs/IndexingJob.java | 59 + .../instasearch/jobs/UpdatePluginJob.java | 78 ++ .../prefs/InstaSearchPreferencePage.java | 320 +++++ .../prefs/PreferenceConstants.java | 45 + .../prefs/PreferenceInitializer.java | 102 ++ .../instasearch/ui/DropdownMenuProvider.java | 87 ++ .../unibz/instasearch/ui/InstaSearchPage.java | 334 +++++ .../unibz/instasearch/ui/InstaSearchUI.java | 183 +++ .../unibz/instasearch/ui/InstaSearchView.java | 686 ++++++++++ .../instasearch/ui/MatchHighlightJob.java | 322 +++++ .../instasearch/ui/ReportErrorDialog.java | 215 +++ .../instasearch/ui/ResultContentProvider.java | 609 +++++++++ .../instasearch/ui/ResultLabelProvider.java | 255 ++++ .../ui/SearchContentProposalProvider.java | 199 +++ .../it/unibz/instasearch/ui/SearchJob.java | 152 +++ .../instasearch/ui/SearchViewControl.java | 546 ++++++++ .../ui/StyledTextContentAdapter.java | 77 ++ .../instasearch/indexing/SearcherTest.java | 186 +++ .../instasearch/indexing/TestSearcher.java | 36 + .../instasearch/indexing/TestStorage.java | 60 + 114 files changed, 14112 insertions(+) create mode 100755 instasearch.feature/.project create mode 100755 instasearch.feature/build.properties create mode 100755 instasearch.feature/epl-v10.html create mode 100755 instasearch.feature/feature.xml create mode 100755 instasearch.site/.project create mode 100755 instasearch.site/favicon.ico create mode 100755 instasearch.site/index.html create mode 100755 instasearch.site/site.xml create mode 100755 instasearch/.classpath create mode 100755 instasearch/.project create mode 100755 instasearch/EclipsePreferences.epf create mode 100755 instasearch/META-INF/MANIFEST.MF create mode 100755 instasearch/build.properties create mode 100755 instasearch/icons/binary.gif create mode 100755 instasearch/icons/close.gif create mode 100755 instasearch/icons/collapseall.gif create mode 100755 instasearch/icons/dates.gif create mode 100755 instasearch/icons/down_arrow.gif create mode 100755 instasearch/icons/expandall.gif create mode 100755 instasearch/icons/filter.gif create mode 100755 instasearch/icons/lightbulb.gif create mode 100755 instasearch/icons/lucene.gif create mode 100755 instasearch/icons/refresh.gif create mode 100755 instasearch/icons/remove.gif create mode 100755 instasearch/icons/remove_inactive.gif create mode 100755 instasearch/icons/sample.gif create mode 100755 instasearch/icons/search.gif create mode 100755 instasearch/icons/search_results.gif create mode 100755 instasearch/icons/syncdb.gif create mode 100755 instasearch/icons/update.gif create mode 100755 instasearch/icons/web.gif create mode 100755 instasearch/icons/workingsets.gif create mode 100755 instasearch/lib/lucene-highlighter-1.9.1.jar create mode 100755 instasearch/plugin.properties create mode 100755 instasearch/plugin.xml create mode 100755 instasearch/src/it/unibz/instasearch/InstaSearch.java create mode 100755 instasearch/src/it/unibz/instasearch/InstaSearchPlugin.java create mode 100755 instasearch/src/it/unibz/instasearch/InstaSearchStartup.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/BuildIndexActionDelegate.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/CheckUpdatesActionDelegate.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/CollapseAllActionDelegate.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/DeleteIndexActionDelegate.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/ExpandAllActionDelegate.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/IncrementalSearchActionDelegate.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/InstaSearchActionDelegate.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/OpenSearchDialog.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/PreferencesAction.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/ShowExceptionAction.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/ShowInstaSearchAction.java create mode 100755 instasearch/src/it/unibz/instasearch/actions/VisitHomePageActionDelegate.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/Field.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/FileAnalyzer.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/LengthNormSimilarity.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/QueryAnalyzer.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/ResourceCollector.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/SearchQuery.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/SearchResult.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/SearchResultDoc.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/Searcher.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/StorageIndexer.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/WorkspaceIndexer.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/WorkspaceIndexerJDT.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/CSVExpander.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/CurrentProjectSetter.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/FieldAliasConverter.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/FileNameSearcher.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/FilterSetter.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/FolderSearcher.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/LastTermQueryPrefixer.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/LowercaseConverter.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/ModifiedTimeConverter.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/PhraseSearcher.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/QueryFuzzifier.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/QueryVisitor.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/UppercaseNameExpander.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/VisitableQuery.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/querying/WorkingSetExpander.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/CamelCaseTokenizer.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/DotSplitTokenizer.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/TermSplitTokenizer.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/WordSplitTokenizer.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/CharStream.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/FastCharStream.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/ParseException.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/ReadMe.txt create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizer.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizer.jj create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizerConstants.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizerTokenManager.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/Token.java create mode 100755 instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/TokenMgrError.java create mode 100755 instasearch/src/it/unibz/instasearch/jobs/CheckUpdatesJob.java create mode 100755 instasearch/src/it/unibz/instasearch/jobs/DeleteIndexJob.java create mode 100755 instasearch/src/it/unibz/instasearch/jobs/IndexUpdateJob.java create mode 100755 instasearch/src/it/unibz/instasearch/jobs/IndexingJob.java create mode 100755 instasearch/src/it/unibz/instasearch/jobs/UpdatePluginJob.java create mode 100755 instasearch/src/it/unibz/instasearch/prefs/InstaSearchPreferencePage.java create mode 100755 instasearch/src/it/unibz/instasearch/prefs/PreferenceConstants.java create mode 100755 instasearch/src/it/unibz/instasearch/prefs/PreferenceInitializer.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/DropdownMenuProvider.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/InstaSearchPage.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/InstaSearchUI.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/InstaSearchView.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/MatchHighlightJob.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/ReportErrorDialog.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/ResultContentProvider.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/ResultLabelProvider.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/SearchContentProposalProvider.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/SearchJob.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/SearchViewControl.java create mode 100755 instasearch/src/it/unibz/instasearch/ui/StyledTextContentAdapter.java create mode 100755 instasearch/test/it/unibz/instasearch/indexing/SearcherTest.java create mode 100755 instasearch/test/it/unibz/instasearch/indexing/TestSearcher.java create mode 100755 instasearch/test/it/unibz/instasearch/indexing/TestStorage.java diff --git a/instasearch.feature/.project b/instasearch.feature/.project new file mode 100755 index 0000000..e71a898 --- /dev/null +++ b/instasearch.feature/.project @@ -0,0 +1,17 @@ + + + instasearch.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/instasearch.feature/build.properties b/instasearch.feature/build.properties new file mode 100755 index 0000000..18f4711 --- /dev/null +++ b/instasearch.feature/build.properties @@ -0,0 +1,2 @@ +bin.includes = feature.xml,\ + epl-v10.html diff --git a/instasearch.feature/epl-v10.html b/instasearch.feature/epl-v10.html new file mode 100755 index 0000000..f3e303d --- /dev/null +++ b/instasearch.feature/epl-v10.html @@ -0,0 +1,257 @@ + + + + +Eclipse Public License - Version 1.0 + + + + +

Eclipse Public License - v 1.0

+ +

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE +PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR +DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS +AGREEMENT.

+ +

1. DEFINITIONS

+ +

"Contribution" means:

+ +

a) in the case of the initial Contributor, the initial +code and documentation distributed under this Agreement, and

+

b) in the case of each subsequent Contributor:

+

i) changes to the Program, and

+

ii) additions to the Program;

+

where such changes and/or additions to the Program +originate from and are distributed by that particular Contributor. A +Contribution 'originates' from a Contributor if it was added to the +Program by such Contributor itself or anyone acting on such +Contributor's behalf. Contributions do not include additions to the +Program which: (i) are separate modules of software distributed in +conjunction with the Program under their own license agreement, and (ii) +are not derivative works of the Program.

+ +

"Contributor" means any person or entity that distributes +the Program.

+ +

"Licensed Patents" mean patent claims licensable by a +Contributor which are necessarily infringed by the use or sale of its +Contribution alone or when combined with the Program.

+ +

"Program" means the Contributions distributed in accordance +with this Agreement.

+ +

"Recipient" means anyone who receives the Program under +this Agreement, including all Contributors.

+ +

2. GRANT OF RIGHTS

+ +

a) Subject to the terms of this Agreement, each +Contributor hereby grants Recipient a non-exclusive, worldwide, +royalty-free copyright license to reproduce, prepare derivative works +of, publicly display, publicly perform, distribute and sublicense the +Contribution of such Contributor, if any, and such derivative works, in +source code and object code form.

+ +

b) Subject to the terms of this Agreement, each +Contributor hereby grants Recipient a non-exclusive, worldwide, +royalty-free patent license under Licensed Patents to make, use, sell, +offer to sell, import and otherwise transfer the Contribution of such +Contributor, if any, in source code and object code form. This patent +license shall apply to the combination of the Contribution and the +Program if, at the time the Contribution is added by the Contributor, +such addition of the Contribution causes such combination to be covered +by the Licensed Patents. The patent license shall not apply to any other +combinations which include the Contribution. No hardware per se is +licensed hereunder.

+ +

c) Recipient understands that although each Contributor +grants the licenses to its Contributions set forth herein, no assurances +are provided by any Contributor that the Program does not infringe the +patent or other intellectual property rights of any other entity. Each +Contributor disclaims any liability to Recipient for claims brought by +any other entity based on infringement of intellectual property rights +or otherwise. As a condition to exercising the rights and licenses +granted hereunder, each Recipient hereby assumes sole responsibility to +secure any other intellectual property rights needed, if any. For +example, if a third party patent license is required to allow Recipient +to distribute the Program, it is Recipient's responsibility to acquire +that license before distributing the Program.

+ +

d) Each Contributor represents that to its knowledge it +has sufficient copyright rights in its Contribution, if any, to grant +the copyright license set forth in this Agreement.

+ +

3. REQUIREMENTS

+ +

A Contributor may choose to distribute the Program in object code +form under its own license agreement, provided that:

+ +

a) it complies with the terms and conditions of this +Agreement; and

+ +

b) its license agreement:

+ +

i) effectively disclaims on behalf of all Contributors +all warranties and conditions, express and implied, including warranties +or conditions of title and non-infringement, and implied warranties or +conditions of merchantability and fitness for a particular purpose;

+ +

ii) effectively excludes on behalf of all Contributors +all liability for damages, including direct, indirect, special, +incidental and consequential damages, such as lost profits;

+ +

iii) states that any provisions which differ from this +Agreement are offered by that Contributor alone and not by any other +party; and

+ +

iv) states that source code for the Program is available +from such Contributor, and informs licensees how to obtain it in a +reasonable manner on or through a medium customarily used for software +exchange.

+ +

When the Program is made available in source code form:

+ +

a) it must be made available under this Agreement; and

+ +

b) a copy of this Agreement must be included with each +copy of the Program.

+ +

Contributors may not remove or alter any copyright notices contained +within the Program.

+ +

Each Contributor must identify itself as the originator of its +Contribution, if any, in a manner that reasonably allows subsequent +Recipients to identify the originator of the Contribution.

+ +

4. COMMERCIAL DISTRIBUTION

+ +

Commercial distributors of software may accept certain +responsibilities with respect to end users, business partners and the +like. While this license is intended to facilitate the commercial use of +the Program, the Contributor who includes the Program in a commercial +product offering should do so in a manner which does not create +potential liability for other Contributors. Therefore, if a Contributor +includes the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and +indemnify every other Contributor ("Indemnified Contributor") +against any losses, damages and costs (collectively "Losses") +arising from claims, lawsuits and other legal actions brought by a third +party against the Indemnified Contributor to the extent caused by the +acts or omissions of such Commercial Contributor in connection with its +distribution of the Program in a commercial product offering. The +obligations in this section do not apply to any claims or Losses +relating to any actual or alleged intellectual property infringement. In +order to qualify, an Indemnified Contributor must: a) promptly notify +the Commercial Contributor in writing of such claim, and b) allow the +Commercial Contributor to control, and cooperate with the Commercial +Contributor in, the defense and any related settlement negotiations. The +Indemnified Contributor may participate in any such claim at its own +expense.

+ +

For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those +performance claims and warranties, and if a court requires any other +Contributor to pay any damages as a result, the Commercial Contributor +must pay those damages.

+ +

5. NO WARRANTY

+ +

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS +PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, +ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY +OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely +responsible for determining the appropriateness of using and +distributing the Program and assumes all risks associated with its +exercise of rights under this Agreement , including but not limited to +the risks and costs of program errors, compliance with applicable laws, +damage to or loss of data, programs or equipment, and unavailability or +interruption of operations.

+ +

6. DISCLAIMER OF LIABILITY

+ +

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT +NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING +WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR +DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED +HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

+ +

7. GENERAL

+ +

If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further action +by the parties hereto, such provision shall be reformed to the minimum +extent necessary to make such provision valid and enforceable.

+ +

If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other +software or hardware) infringes such Recipient's patent(s), then such +Recipient's rights granted under Section 2(b) shall terminate as of the +date such litigation is filed.

+ +

All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of time +after becoming aware of such noncompliance. If all Recipient's rights +under this Agreement terminate, Recipient agrees to cease use and +distribution of the Program as soon as reasonably practicable. However, +Recipient's obligations under this Agreement and any licenses granted by +Recipient relating to the Program shall continue and survive.

+ +

Everyone is permitted to copy and distribute copies of this +Agreement, but in order to avoid inconsistency the Agreement is +copyrighted and may only be modified in the following manner. The +Agreement Steward reserves the right to publish new versions (including +revisions) of this Agreement from time to time. No one other than the +Agreement Steward has the right to modify this Agreement. The Eclipse +Foundation is the initial Agreement Steward. The Eclipse Foundation may +assign the responsibility to serve as the Agreement Steward to a +suitable separate entity. Each new version of the Agreement will be +given a distinguishing version number. The Program (including +Contributions) may always be distributed subject to the version of the +Agreement under which it was received. In addition, after a new version +of the Agreement is published, Contributor may elect to distribute the +Program (including its Contributions) under the new version. Except as +expressly stated in Sections 2(a) and 2(b) above, Recipient receives no +rights or licenses to the intellectual property of any Contributor under +this Agreement, whether expressly, by implication, estoppel or +otherwise. All rights in the Program not expressly granted under this +Agreement are reserved.

+ +

This Agreement is governed by the laws of the State of New York and +the intellectual property laws of the United States of America. No party +to this Agreement will bring a legal action under this Agreement more +than one year after the cause of action arose. Each party waives its +rights to a jury trial in any resulting litigation.

+ + + + \ No newline at end of file diff --git a/instasearch.feature/feature.xml b/instasearch.feature/feature.xml new file mode 100755 index 0000000..f445ff7 --- /dev/null +++ b/instasearch.feature/feature.xml @@ -0,0 +1,62 @@ + + + + + Eclipse plug-in for doing quick search in workspace files using +a search engine. Shows search results instantly as you type. +http://code.google.com/a/eclipselabs.org/p/instasearch/ + + + + Copyright (C) 2009 Andrejs Jermakovics + + + + This program and the accompanying materials +are made available under the terms of the Eclipse Public License +v1.0 +which accompanies this distribution, and is available at + +http://www.eclipse.org/org/documents/epl-v10.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instasearch.site/.project b/instasearch.site/.project new file mode 100755 index 0000000..b76c37f --- /dev/null +++ b/instasearch.site/.project @@ -0,0 +1,17 @@ + + + instasearch.site + + + + + + org.eclipse.pde.UpdateSiteBuilder + + + + + + org.eclipse.pde.UpdateSiteNature + + diff --git a/instasearch.site/favicon.ico b/instasearch.site/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..2820bf35fa9e9dd17e05387056018d15d89cb691 GIT binary patch literal 1406 zcmeH{yH8VL6u^Hig(5y~Q9CaG%ehes z)qqP7MXjLx|H9q-jRyY==WadX{OxwZ%Y{3gTof)fcM08G9?Wv(zAgl~8u~#~n?cjV zAlKSMTz?$l?w2ghUl(YJPSZBKi1+gx-l;h{re^7$p6BV!v-J6N`ZC|~Khe><`U&(H z^k;tw3mDIW7?KD4Lk#LK8F~>WWDFCY`OR=}gwarh$g444k3@+^V#Iv+crz9!5lb-M z^MJSUB<~VQQqMa{ji;DMPLNKeN#}A*zMtg7fRB&iUOtTmSQM8Nicy?EaRUENV3ViO zQ(v{F#I&pHJsuG@Q&_6UTk%$ zl~)M$$&pI4EYfOoRIW9vX3nnxwF+8 + + + + +InstaSearch Update Site + + +This is the InstaSearch update site location.
+Please install using Eclipse Marketplace (how-to)
+
+Update site: +
  • +http://code.inf.unibz.it/instasearch/downloads/ +
  • +
    +
    +Alternatively you grab the latest plugin jar file and put it in the eclipse/dropins folder:
    +plugins/ + + diff --git a/instasearch.site/site.xml b/instasearch.site/site.xml new file mode 100755 index 0000000..9c523f2 --- /dev/null +++ b/instasearch.site/site.xml @@ -0,0 +1,18 @@ + + + + InstaSearch Eclipse Plug-in Update Site + + + + + + + + + + InstaSearch Plug-in + + + + diff --git a/instasearch/.classpath b/instasearch/.classpath new file mode 100755 index 0000000..71a6632 --- /dev/null +++ b/instasearch/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/instasearch/.project b/instasearch/.project new file mode 100755 index 0000000..eccd252 --- /dev/null +++ b/instasearch/.project @@ -0,0 +1,28 @@ + + + instasearch + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/instasearch/EclipsePreferences.epf b/instasearch/EclipsePreferences.epf new file mode 100755 index 0000000..89f5a09 --- /dev/null +++ b/instasearch/EclipsePreferences.epf @@ -0,0 +1,894 @@ +#Tue Aug 17 10:23:07 BST 2010 +/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_parentheses_in_expressions=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/type=org.eclipse.equinox.p2.extensionlocation.artifactRepository +/instance/org.eclipse.team.ui/org.eclipse.team.ui.first_time=false +/instance/org.eclipse.ant.ui/useQuickDiffPrefPage=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_subversive_0.7_update-site_/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_buckminster_updates/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/description= +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.director_rollback/version=1.0.0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_releases_ganymede/enabled=true +/instance/org.eclipse.ui.workbench/resourcetypes=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/name=The Eclipse Project Updates +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_extras/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/suffix=content.xml +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_private_constructors=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_emft_updates_/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.continuation_indentation=2 +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.max_detail_length=10000000 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +/instance/org.eclipse.debug.ui/Expressions.detail.orientation=Variables.detail.orientation.underneath +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/name=file\:Memory Analyzer Update Site +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462/name=artifact listener file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/.eclipseextension +/instance/org.eclipse.mylyn.context.core/mylyn.attention.migrated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +/instance/org.eclipse.jdt.ui/useAnnotationsPrefPage=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__www.eclipse.org_modeling_emft_?project\=search\#search/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +/instance/org.eclipse.jdt.ui/formatter_profile=_Formatter Java Style +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_override_annotations=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_191_data_listener_-1789306462_/isSystem=true +/instance/org.eclipse.debug.ui/preferredDetailPanes=DefaultDetailPane\:DefaultDetailPane| +/instance/org.eclipse.jdt.ui/spelling_locale=en_GB +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951_/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/configuration/org.eclipse.osgi/bundles/337/data/listener_1925729951/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/type=org.eclipse.equinox.p2.updatesite.artifactRepository +/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_191_data_listener_-1789306462_/name=artifact listener file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/.eclipseextension +@org.eclipse.jdt.core=3.6.0.v_A58 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_epp_updates_1.0_/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_gmf_update-site_releases_site.xml/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +/instance/org.eclipse.jdt.ui/sp_cleanup.sort_members=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_gef_update-site_releases_site.xml/url=http\://download.eclipse.org/tools/gef/update-site/releases/site.xml +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__ucdetector.sourceforge.net_update/name=UCDetector update site +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_cdt_releases_ganymede/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/provider= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/description= +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/url=http\://download.eclipse.org/tools/ajdt/34/update +/instance/org.eclipse.core.resources/refresh.enabled=true +/instance/org.eclipse.debug.ui/preferredTargets=default\:default| +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/description= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JRE_SRC=C\:/Program Files/Java/jdk1.6.0_07/src.zip +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/suffix=artifacts.xml +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_releases_ganymede/version=1 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__www.eclipse.org_modeling_emft_updates_/url=http\://www.eclipse.org/modeling/emft/updates/ +/instance/org.eclipse.pde.core/saved_platform0=C\:\\Program Files\\eclipse-SDK-3.4-win32\\eclipse +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__eclipse.org_tptp_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__www.eclipse.org_modeling_emft_?project\=search\#search/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/suffix=artifacts.xml +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_gmf_update-site_releases_site.xml/url=http\://download.eclipse.org/modeling/gmf/update-site/releases/site.xml +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_194_data_listener_1925729951_/version=1.0.0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_dltk_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse/version=1.0.0 +/instance/org.eclipse.jdt.ui/org.eclipse.ajdt.ui.editor.outline.PointcutFilter=true +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.internal.ui.PackageExplorer.HideInnerClassFilesFilter=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_emft_updates_/isSystem=false +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.editor.tab.width= +/instance/org.eclipse.jdt.ui/breadcrumb.org.eclipse.jdt.ui.JavaPerspective=true +/instance/org.eclipse.equinox.p2.ui.sdk/enabled=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_rt_rap_update-site/url=http\://download.eclipse.org/rt/rap/update-site +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462_/name=metadata listener file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/.eclipseextension +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.make_variable_declarations_final=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_buckminster_updates/url=http\://download.eclipse.org/tools/buckminster/updates +/instance/org.eclipse.core.resources/version=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951_/version=1.0.0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_/name=Bundle pool +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.javadoclocations.migrated=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_birt_update-site_2.3/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_imports=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_releases_ganymede/description= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_webtools_updates/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_releases_ganymede/name=Ganymede Update Site +/instance/org.eclipse.jdt.ui/sp_cleanup.make_type_abstract_if_missing_method=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/name=download cache +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_191_data_listener_-1789306462_/suffix=artifacts.xml +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/name=Memory Analyzer Artifacts +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_e3.4/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.ECLIPSE_HOME=C\:/Program Files/eclipse-SDK-3.4-win32/eclipse +/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +/instance/org.eclipse.jdt.ui/fontPropagated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/enabled=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_xref_update/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__ucdetector.sourceforge.net_update/suffix=content.xml +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/type=org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/url=http\://findbugs.cs.umd.edu/eclipse +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/name=C\:\\Program Files\\eclipse-SDK-3.4-win32\\eclipse\\.eclipseextension +/instance/org.eclipse.ui.workbench/ENABLED_DECORATORS=org.eclipse.jdt.ui.override.decorator\:true,org.eclipse.jdt.ui.interface.decorator\:false,org.eclipse.jdt.ui.buildpath.decorator\:true,org.eclipse.mylyn.context.ui.decorator.interest\:true,org.eclipse.mylyn.tasks.ui.decorators.task\:true,org.eclipse.mylyn.team.ui.changeset.decorator\:true,org.eclipse.team.cvs.ui.decorator\:true,org.eclipse.ui.LinkedResourceDecorator\:true,org.eclipse.ui.VirtualResourceDecorator\:true,org.eclipse.ui.ContentTypeDecorator\:true,org.eclipse.ui.ResourceFilterDecorator\:false, +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_rap_update-site/enabled=false +/instance/org.eclipse.ui.ide/MARKER_LIMITS_VALUE=1000 +/instance/org.eclipse.ui.ide/SAVE_ALL_BEFORE_BUILD=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_epp_updates_1.0_/isSystem=false +@org.eclipse.ui=3.6.0.I20100603-1100 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__www.eclipse.org_modeling_emft_?project\=search\#search/url=http\://www.eclipse.org/modeling/emft/?project\=search\#search +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.ondemandthreshold=99 +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.ignorelowercasenames=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +/instance/org.eclipse.mylyn.java.ui/org.eclipse.mylyn.java.ui.run.count.3_1_0=1 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_dsdp_nab_updates/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/isSystem=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JUNIT_HOME=C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/plugins/org.junit_3.8.2.v20080602-1318 +/instance/org.eclipse.jdt.ui/sp_cleanup.make_private_fields_final=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.builder.invalidClasspath=ignore +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/ +/instance/org.eclipse.ui.editors/undoHistorySize=2000 +/instance/org.eclipse.jdt.ui/proposalOrderMigrated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_m2t_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/isSystem=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/p2/org.eclipse.equinox.p2.core/cache/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__ucdetector.sourceforge.net_update/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache/isSystem=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/description= +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.LaunchParentProject=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/name=file\:/builds/M/org.eclipse.releng.eclipsebuilder/../src/repo - artifacts +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_birt_update-site_2.3/url=http\://download.eclipse.org/birt/update-site/2.3 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__ucdetector.sourceforge.net_update/url=http\://ucdetector.sourceforge.net/update +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_/isSystem=true +/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_this_for_non_static_field_access=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/enabled=true +/instance/com.jprofiler.integrations.eclipse/timestamp=1224245775200 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/version=1.0.0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951/description= +/instance/org.eclipse.jdt.ui/hoverModifierMasks=org.eclipse.jdt.ui.BestMatchHover;0;zorg.eclipse.ajdt.ui.PointcutSourceHover;0;org.eclipse.jdt.internal.debug.ui.JavaDebugHover;0;org.eclipse.jdt.ui.ProblemHover;0;org.eclipse.jdt.ui.NLSStringHover;327680;org.eclipse.jdt.ui.JavadocHover;0;org.eclipse.jdt.ui.JavaSourceHover;131072;org.eclipse.jdt.ui.AnnotationHover;0; +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_dsdp_dd_updates/url=http\://download.eclipse.org/dsdp/dd/updates +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_dltk_updates_/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951/provider= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.director_rollback/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/p2/org.eclipse.equinox.p2.director/rollback +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_trailing_whitespaces_all=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/name=AJDT Artifacts +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/description= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache/name=download cache +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.code_templates_migrated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.tabulation.size=4 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +/instance/org.eclipse.jdt.ui/useQuickDiffPrefPage=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/url=http\://download.eclipse.org/tools/ajdt/34/update +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_m2m_updates_/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_stp_updates_/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_cdt_releases_ganymede/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/suffix=eclipse +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_emf_updates_/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_emft_updates_/isSystem=false +/configuration/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.exception.name=e +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_mdt_updates_/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_epp_updates_1.0_/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +/instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +/instance/edu.umd.cs.findbugs.plugin.eclipse/lastUsedGrouping=[Project, Pattern, Marker] +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.never_use_blocks=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_gmf_updates_releases_/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +/instance/org.eclipse.jdt.core/JRE_SRC= +/instance/org.eclipse.jdt.ui/sp_cleanup.add_serial_version_id=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_e3.4/url=http\://download.eclipse.org/tools/mylyn/update/e3.4 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_mdt_updates_/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_birt_update-site_2.3/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse/isSystem=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_stp_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_releases_ganymede/enabled=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/version=1.0.0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +/instance/org.eclipse.jdt.ui/hoverModifiers=org.eclipse.jdt.ui.BestMatchHover;0;zorg.eclipse.ajdt.ui.PointcutSourceHover;\!0;org.eclipse.jdt.internal.debug.ui.JavaDebugHover;\!0;org.eclipse.jdt.ui.ProblemHover;\!0;org.eclipse.jdt.ui.NLSStringHover;Ctrl+Alt;org.eclipse.jdt.ui.JavadocHover;\!0;org.eclipse.jdt.ui.JavaSourceHover;Shift;org.eclipse.jdt.ui.AnnotationHover;\!0; +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_gmf_updates_releases_/url=http\://download.eclipse.org/modeling/gmf/updates/releases/ +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_194_data_listener_1925729951_/isSystem=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indentation.size=4 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +\!/= +/instance/org.eclipse.jdt.ui/content_assist_guess_method_arguments=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__ucdetector.sourceforge.net_update/url=http\://ucdetector.sourceforge.net/update +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_stp_updates_/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_dltk_updates_/url=http\://download.eclipse.org/technology/dltk/updates/ +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/suffix=artifacts.xml +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/provider= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_194_data_listener_1925729951_/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.detail_pane_word_wrap=true +/instance/org.eclipse.jdt.ui/content_assist_proposals_foreground=0,0,0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache/version=1.0.0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/ +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__www.eclipse.org_modeling_emft_updates_/enabled=false +@org.eclipse.ui.editors=3.6.0.v20100520-0800 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/url=http\://download.eclipse.org/tools/ajdt/34/equinox-aspects +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/url=http\://download.eclipse.org/eclipse/updates/3.4 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_rap_update-site/url=http\://download.eclipse.org/technology/rap/update-site +/instance/org.eclipse.jdt.ui/sourceHoverBackgroundColor=255,255,225 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_cdt_releases_ganymede/url=http\://download.eclipse.org/tools/cdt/releases/ganymede +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_nls_tags=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_buckminster_updates/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__www.eclipse.org_modeling_emft_updates_/isSystem=false +@org.eclipse.mylyn.java.ui=3.4.0.v20100608-0100-e3x +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/name=Equinox Aspects Update Site +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +/instance/org.eclipse.ui.ide/platformState=1254411581688 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse/description= +/instance/org.eclipse.jdt.ui/org.eclipse.pde.ui.ExternalPluginLibrariesFilter1=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.director_rollback/type=org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_cdt_releases_ganymede/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +@org.eclipse.team.cvs.ui=3.3.300.I20100526-0800 +/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_method_access=false +/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_this_for_non_static_method_access=false +/instance/org.eclipse.ant.ui/useAnnotationsPrefPage=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_releases_ganymede/version=1.0.0 +/instance/org.eclipse.ui.editors/lineNumberRuler=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_emft_updates_/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_dltk_updates_/enabled=false +/instance/org.eclipse.jdt.ui/sp_cleanup.format_source_code_changes_only=false +/configuration/org.eclipse.ui.ide/RECENT_WORKSPACES_PROTOCOL=3 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/enabled=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__www.eclipse.org_modeling_emft_?project\=search\#search/isSystem=false +/instance/org.eclipse.jdt.ui/breadcrumb.org.eclipse.debug.ui.DebugPerspective=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JRE_SRCROOT= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_emf_updates_/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +/instance/org.eclipse.debug.ui/Console.highWaterMark=88000 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462_/isSystem=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_line_comments=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/configuration/org.eclipse.osgi/bundles/335/data/listener_-1789306462/ +@org.eclipse.help.ui=3.5.0.v20100517 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_e3.4/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/enabled=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_webtools_updates/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_191_data_listener_-1789306462_/provider= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951_/type=org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__www.eclipse.org_modeling_emft_?project\=search\#search/url=http\://www.eclipse.org/modeling/emft/?project\=search\#search +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/provider= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache/provider= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_emft_updates_/url=http\://download.eclipse.org/technology/emft/updates/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_191_data_listener_-1789306462_/version=1.0.0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.visibilityCheck=enabled +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462/suffix=artifacts.xml +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__www.eclipse.org_modeling_emft_updates_/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_extras/url=http\://download.eclipse.org/tools/mylyn/update/extras +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.PREF_LAUNCH_PERSPECTIVES=\r\n\r\n +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_releases_ganymede/type=org.eclipse.equinox.p2.updatesite.artifactRepository +/instance/org.eclipse.epp.usagedata.recording/org.eclipse.epp.usagedata.recording.last-upload=1254469539593 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected +/instance/org.eclipse.ajdt.ui/org.aspectj.ajdt.core.compiler.lint.InvalidAbsoluteTypeName=error +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_local_variables=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_members=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_webtools_updates/url=http\://download.eclipse.org/webtools/updates +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/suffix=content.xml +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_rt_rap_update-site/url=http\://download.eclipse.org/rt/rap/update-site +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/.eclipseextension +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/description= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.gettersetter.use.is=true +/instance/org.eclipse.jdt.ui/sp_cleanup.format_source_code=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_dsdp_tm_updates_3.0/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/name=http\://findbugs.cs.umd.edu/eclipse +/instance/org.eclipse.jdt.ui/spelling_locale_initialized=true +/instance/org.eclipse.jdt.ui/sp_cleanup.convert_to_enhanced_for_loop=false +/instance/org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_VM_XML=\r\n\r\n\r\n\r\n\r\n\r\n +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/version=1.0.0 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_gef_update-site_releases_site.xml/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_dltk_updates_/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__ucdetector.sourceforge.net_update/enabled=true +/configuration/org.eclipse.ui.ide/SHOW_WORKSPACE_SELECTION_DIALOG=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line +/instance/org.eclipse.mylyn.java.ui/org.eclipse.mylyn.ui.first.run.0_4_9=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462/isSystem=true +/instance/org.eclipse.debug.ui/pref_state_memento.org.eclipse.debug.ui.ExpressionView=\r\n\r\n\r\n\r\n\r\n +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/description= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +/instance/org.eclipse.jdt.ui/CustomFiltersActionGroup.org.eclipse.jdt.ui.PackageExplorer.TAG_DUMMY_TO_TEST_EXISTENCE=storedViewPreferences +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_xref_update/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_deprecated_annotations=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__www.eclipse.org_modeling_emft_updates_/url=http\://www.eclipse.org/modeling/emft/updates/ +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/p2/org.eclipse.equinox.p2.core/cache/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.templates_migrated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/suffix=artifacts.xml +/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_subversive_0.7_update-site_/enabled=false +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.LaunchLastIfNotLaunchable=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/type=org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/version=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_rap_update-site/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_buckminster_updates/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/description= +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.director_rollback/suffix=content.xml +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_gef_update-site_releases_site.xml/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/type=org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +/instance/org.eclipse.ui.workbench/org.eclipse.ui.commands=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.PackageExplorer.ImportDeclarationFilter=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_datatools_updates/url=http\://download.eclipse.org/datatools/updates +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/name=Agent Metadata Cache +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/name=AJDT Update Site (JDT Weaving) +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_methods=true +/instance/org.eclipse.team.cvs.ui/pref_first_startup=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_m2t_updates_/url=http\://download.eclipse.org/modeling/m2t/updates/ +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462_/suffix=content.xml +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_191_data_listener_-1789306462_/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_field_access=false +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.custom_templates= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.timeoutForParameterNameFromAttachedJavadoc=50 +/instance/org.eclipse.jdt.ui/formatter_settings_version=11 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_block=next_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +/instance/org.eclipse.jdt.ui/sp_cleanup.never_use_parentheses_in_expressions=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__ucdetector.sourceforge.net_update/type=org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/name=C\:\\Program Files\\eclipse-SDK-3.4-win32\\eclipse\\.eclipseextension +/instance/org.eclipse.ui.browser/browsers=\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/isSystem=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/suffix=artifacts.xml +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert +/instance/org.eclipse.pde.ui/Preferences.MainPage.overwriteBuildFilesOnExport=prompt +/instance/org.eclipse.pde.core/last_location=C\:\\Program Files\\eclipse-SDK-3.4-win32\\eclipse\\plugins +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +/instance/org.eclipse.jdt.ui/tabWidthPropagated=true +/instance/org.eclipse.ajdt.ui/ajde.version.at.previous.startup=@AJDEVERSION@ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_dsdp_nab_updates/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_m2m_updates_/enabled=false +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.formatterprofiles=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/provider= +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_xref_update/url=http\://download.eclipse.org/tools/ajdt/xref/update +/instance/org.eclipse.ui.ide/org.eclipse.ui.internal.views.markers.CachedMarkerBuilderorg.eclipse.ui.views.ProblemView=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/provider= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_webtools_updates/enabled=false +/instance/org.eclipse.jdt.ui/org.eclipse.ajdt.ui.editor.outline.AdviceFilter=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.deprecation=ignore +/instance/org.eclipse.jdt.ui/sp_cleanup.use_blocks=false +/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_emft_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/description= +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_webtools_updates/url=http\://download.eclipse.org/webtools/updates +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/url=http\://download.eclipse.org/tools/ajdt/34/equinox-aspects +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_191_data_listener_-1789306462_/description= +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.PackageExplorer_patternFilterId_.*=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_gmf_updates_releases_/isSystem=false +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.formatterprofiles.version=11 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_m2m_updates_/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_dsdp_tm_updates_3.0/url=http\://download.eclipse.org/dsdp/tm/updates/3.0 +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.PackageExplorer.SyntheticMembersFilter=true +@org.eclipse.mylyn.monitor.ui=3.4.0.v20100608-0100-e3x +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_gmf_update-site_releases_site.xml/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_194_data_listener_1925729951_/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/configuration/org.eclipse.osgi/bundles/194/data/listener_1925729951/ +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__eclipse.org_tptp_updates_/isSystem=false +/instance/org.eclipse.ui.ide/PROBLEMS_FILTERS_MIGRATE=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_emf_updates_/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_/provider= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +/instance/org.eclipse.ui.browser/browser-choice=1 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_mdt_updates_/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/name=http\://findbugs.cs.umd.edu/eclipse +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462_/type=org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.argumentSuffixes= +/instance/org.eclipse.debug.ui/org.eclipse.debug.uiinspectPopupSashWeights=750\:250 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_xref_update/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__ucdetector.sourceforge.net_update/enabled=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected +/instance/org.eclipse.jdt.ui/sp_cleanup.add_default_serial_version_id=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_m2m_updates_/url=http\://download.eclipse.org/modeling/m2m/updates/ +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_rap_update-site/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_m2t_updates_/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_buckminster_updates/url=http\://download.eclipse.org/tools/buckminster/updates +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_mdt_updates_/url=http\://download.eclipse.org/modeling/mdt/updates/ +@org.eclipse.ui.workbench=3.6.0.I20100603-1100 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951_/isSystem=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_gef_update-site_releases_site.xml/url=http\://download.eclipse.org/tools/gef/update-site/releases/site.xml +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_releases_ganymede/type=org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.importorder=java;javax;org;com; +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_cdt_releases_ganymede/url=http\://download.eclipse.org/tools/cdt/releases/ganymede +/instance/org.eclipse.jdt.ui/sp_cleanup.organize_imports=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_datatools_updates/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_subversive_0.7_update-site_/url=http\://download.eclipse.org/technology/subversive/0.7/update-site/ +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_emft_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__www.eclipse.org_modeling_emft_updates_/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +/instance/org.eclipse.contribution.visualiser/org.eclipse.contribution.visualiser.preferences.provider=AspectJ Provider +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__www.eclipse.org_modeling_emft_?project\=search\#search/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.line_length=80 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_releases_ganymede/url=http\://download.eclipse.org/releases/ganymede +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +/instance/org.eclipse.jdt.debug.ui/org.eclipse.debug.ui.VariableView.org.eclipse.jdt.debug.ui.show_null_entries=true +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.PackageExplorer.EmptyLibraryContainerFilter=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_dsdp_dd_updates/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.fieldSuffixes= +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/type=org.eclipse.equinox.p2.extensionlocation.metadataRepository +/instance/org.eclipse.jdt.ui/content_assist_number_of_computers=14 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.localSuffixes= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462/version=1.0.0 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_subversive_0.7_update-site_/isSystem=false +@org.eclipse.core.resources=3.6.0.v20100526-0737 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/enabled=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_gmf_updates_releases_/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_xref_update/url=http\://download.eclipse.org/tools/ajdt/xref/update +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_stp_updates_/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_dsdp_dd_updates/url=http\://download.eclipse.org/dsdp/dd/updates +@org.eclipse.search=3.6.0.v20100520-0800 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_194_data_listener_1925729951_/description= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.lineSplit=80 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_dsdp_dd_updates/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_rt_rap_update-site/isSystem=false +/instance/org.eclipse.jdt.ui/content_assist_disabled_computers=org.eclipse.jdt.ui.javaAllProposalCategory\u0000org.eclipse.jdt.ui.javaNoTypeProposalCategory\u0000org.eclipse.jdt.ui.textProposalCategory\u0000org.eclipse.jdt.ui.javaTypeProposalCategory\u0000 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_releases_ganymede/suffix=content.xml +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +/instance/org.eclipse.jdt.debug.ui/org.eclipse.jdt.debug.ui.detail_formatters=com.itrsgroup.activepaths.ActivePathData,toVerboseString(),1,com.itrsgroup.activepaths.ActivePathModelEvent,toVerboseString(),1,com.itrsgroup.jno.dataviews.JNDataView,toVerboseString(),1,com.itrsgroup.jno.naming.JNNameResultVector,toVerboseString(),1,com.itrsgroup.jno.primitives.JNMutableTreeNode,toXmlString(),1,com.itrsgroup.setting.Setting,toVerboseString(),1,com.itrsgroup.setting.xml.XmlChoiceSetting,toVerboseString(),1,com.itrsgroup.setting.xml.XmlConfigurable$1,getName() + "\:" + getValue(),1 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_birt_update-site_2.3/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse/provider= +@org.eclipse.ui.ide=3.6.0.I20100601-0800 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_releases_ganymede/provider= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/configuration/org.eclipse.osgi/bundles/337/data/listener_1925729951/ +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_rap_update-site/url=http\://download.eclipse.org/technology/rap/update-site +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.UseContextualLaunch=false +/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_blocks=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__ucdetector.sourceforge.net_update/version=1.0.0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_194_data_listener_1925729951_/provider= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_cdt_releases_ganymede/enabled=false +/instance/org.eclipse.jdt.ui/content_assist_insert_completion=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_emf_updates_/url=http\://download.eclipse.org/modeling/emf/updates/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/p2/org.eclipse.equinox.p2.core/cache/ +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_rt_rap_update-site/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_html=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +/instance/org.eclipse.help.ui/browser.y=62 +/instance/org.eclipse.help.ui/browser.x=1471 +/instance/org.eclipse.help.ui/browser.w=1024 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=next_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/name=Equinox Aspects Update Site +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_extras/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_dsdp_tm_updates_3.0/enabled=false +/instance/org.eclipse.help.ui/browser.h=768 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +/instance/org.eclipse.equinox.p2.ui.sdk/day=Every day +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__eclipse.org_tptp_updates_/url=http\://eclipse.org/tptp/updates/ +/instance/org.eclipse.jdt.debug.ui/org.eclipse.debug.ui.ExpressionView.org.eclipse.jdt.debug.ui.show_null_entries=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_source_code=true +/instance/org.eclipse.jdt.ui/sp_cleanup.correct_indentation=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line +@org.eclipse.debug.core=3.6.0.v20100519 +/instance/org.eclipse.jdt.ui/LexicalSortingAction.isChecked=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_subversive_0.7_update-site_/url=http\://download.eclipse.org/technology/subversive/0.7/update-site/ +file_export_version=3.0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/isSystem=true +/instance/org.eclipse.pde.core/platform_path=C\:\\Program Files\\eclipse-SDK-3.4-win32\\eclipse +@org.eclipse.jdt.debug.ui=3.5.0.v20100602-0830 +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_trailing_whitespaces=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951/name=artifact listener dropins +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_birt_update-site_2.3/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/version=1.0.0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951/version=1.0.0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/version=1.0.0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_m2t_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/suffix=content.xml +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_extras/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_stp_updates_/url=http\://download.eclipse.org/stp/updates/ +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/suffix=content.xml +/instance/com.jprofiler.integrations.eclipse/openNewWindow=2 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/enabled=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_buckminster_updates/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/url=http\://download.eclipse.org/technology/mat/0.7/update-site/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +/instance/org.eclipse.ui.editors/isAJDTErrorGoToNextNavigationTarget=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_dsdp_nab_updates/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/enabled=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unnecessary_casts=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_webtools_updates/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_epp_updates_1.0_/url=http\://download.eclipse.org/technology/epp/updates/1.0/ +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_emft_updates_/url=http\://download.eclipse.org/modeling/emft/updates/ +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462/description= +@org.eclipse.ant.ui=3.5.0.v20100427 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.JavaOutlinePage.SyntheticMembersFilter=true +/instance/org.eclipse.jdt.ui/CustomFiltersActionGroup.org.eclipse.jdt.ui.JavaOutlinePage.TAG_DUMMY_TO_TEST_EXISTENCE=storedViewPreferences +/instance/org.eclipse.ui.ide/TASKS_FILTERS_MIGRATE=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_rt_rap_update-site/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_e3.4/enabled=false +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.overrideannotation=true +/instance/org.eclipse.jdt.ui/sp_cleanup.sort_members_all=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.PackageExplorer.PackageDeclarationFilter=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/provider= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.argumentPrefixes= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__eclipse.org_tptp_updates_/url=http\://eclipse.org/tptp/updates/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +/instance/org.eclipse.equinox.p2.ui.sdk/autoUpdateInit=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +/instance/org.eclipse.jdt.ui/lastRecentlyUsedFilters=org.eclipse.ajdt.ui.editor.outline.AdviceFilter,org.eclipse.ajdt.ui.editor.outline.DeclarationFilter,org.eclipse.ajdt.ui.editor.outline.IntroductionFilter, +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_gef_update-site_releases_site.xml/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/suffix=content.xml +/instance/org.eclipse.debug.ui/pref_state_memento.org.eclipse.debug.ui.VariableView=\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +/instance/org.eclipse.jdt.ui/sp_cleanup.make_parameters_final=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951_/suffix=content.xml +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +/instance/org.eclipse.debug.ui/Console.limitConsoleOutput=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_empty_lines=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +/instance/org.eclipse.ui/showIntro=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_m2t_updates_/url=http\://download.eclipse.org/modeling/m2t/updates/ +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/url=http\://download.eclipse.org/eclipse/updates/3.4 +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.staticondemandthreshold=99 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/.eclipseextension +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.fieldPrefixes= +/instance/com.jprofiler.integrations.eclipse/jprofilerExecutable=C\:\\Program Files\\jprofiler5\\bin\\jprofiler.exe +/instance/org.eclipse.mylyn.monitor.ui/org.eclipse.mylyn.monitor.activity.tracking.enabled.checked=true +/instance/org.eclipse.jdt.ui/MemberFilterActionGroup.org.eclipse.jdt.ui.JavaOutlinePage.4=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.localPrefixes= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_extras/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/version=1.0.0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_epp_updates_1.0_/enabled=false +/instance/org.eclipse.ui.browser/internalWebBrowserHistory=http\://asp.itrsgroup.com/itrack/editissue.asp?issueid\=6245|*|http\://asp.itrsgroup.com/itrack/editissue.asp?issueid\=6510|*| +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/version=1 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462_/version=1.0.0 +/instance/org.eclipse.jdt.ui/spelling_user_dictionary_encoding= +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_annotations=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/type=org.eclipse.equinox.p2.artifact.repository.simpleRepository +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache/description= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_emft_updates_/url=http\://download.eclipse.org/modeling/emft/updates/ +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_gmf_updates_releases_/enabled=false +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.JavaOutlinePage.ImportDeclarationFilter=true +/instance/org.eclipse.contribution.weaving.jdt/org.eclipse.contribution.weaving.jdt.version=1.0.0.200901261628 +@org.eclipse.mylyn.context.core=3.4.0.v20100608-0100-e3x +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/enabled=true +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_emft_updates_/url=http\://download.eclipse.org/technology/emft/updates/ +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462/provider= +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.internal.ui.PackageExplorer.EmptyInnerPackageFilter=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_dsdp_dd_updates/isSystem=false +@org.eclipse.equinox.p2.ui.sdk=1.0.100.v20100513 +@org.eclipse.jdt.launching=3.5.100.v20100526 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_gef_update-site_releases_site.xml/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.compliance=1.6 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_subversive_0.7_update-site_/enabled=false +/instance/org.eclipse.jdt.ui/sp_cleanup.use_blocks_only_for_return_and_throw=false +/instance/org.eclipse.jdt.core/JRE_LIB=C\:/Program Files/Java/jre1.6.0_07/lib/rt.jar +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.user_view_bindings=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/enabled=true +/instance/org.eclipse.jdt.ui/sp_cleanup.add_generated_serial_version_id=false +/configuration/org.eclipse.ui.ide/MAX_RECENT_WORKSPACES=5 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_dsdp_tm_updates_3.0/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_xref_update/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.source=1.6 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_194_data_listener_1925729951_/name=artifact listener dropins +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_epp_updates_1.0_/url=http\://download.eclipse.org/technology/epp/updates/1.0/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951/isSystem=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse/suffix=artifacts.xml +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_dsdp_tm_updates_3.0/isSystem=false +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_fields=true +/instance/org.eclipse.jdt.ui/sp_cleanup.make_local_variable_final=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_e3.4/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/version=1.0.0 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_datatools_updates/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_m2m_updates_/url=http\://download.eclipse.org/modeling/m2m/updates/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_mdt_updates_/url=http\://download.eclipse.org/modeling/mdt/updates/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_birt_update-site_2.3/url=http\://download.eclipse.org/birt/update-site/2.3 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_emft_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_m2m_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_datatools_updates/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_emft_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_dsdp_tm_updates_3.0/url=http\://download.eclipse.org/dsdp/tm/updates/3.0 +/instance/org.eclipse.ui.workbench/editors=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.compact_else_if=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.director_rollback/name=Agent rollback repository +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JUNIT_SRC_HOME=C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/plugins/org.junit.source_3.8.2.v20080602-1318.jar +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_header=false +/instance/org.eclipse.jdt.ui/content_assist_proposals_background=255,255,255 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_dsdp_nab_updates/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.tabulation.char=tab +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_datatools_updates/url=http\://download.eclipse.org/datatools/updates +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.custom_code_templates= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/provider= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/version=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_block_comments=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +/instance/org.eclipse.ui.editors/spellingEnabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning +@org.eclipse.epp.usagedata.recording=1.3.0.R201005261100 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_eclipse_updates_3.4/version=1.0.0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_dltk_updates_/url=http\://download.eclipse.org/technology/dltk/updates/ +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_dsdp_nab_updates/url=http\://download.eclipse.org/dsdp/nab/updates +/instance/org.eclipse.debug.core/prefWatchExpressions=\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/enabled=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +@org.eclipse.team.ui=3.5.100.I20100527-0800 +/instance/org.eclipse.ui.editors/overviewRuler_migration=migrated_3.1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_m2t_updates_/isSystem=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_equinox-aspects/provider= +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_emf_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/type=org.eclipse.equinox.p2.updatesite.metadataRepository +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +/instance/org.eclipse.help.ui/browser.maximized=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/version=1.0.0 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_dsdp_nab_updates/url=http\://download.eclipse.org/dsdp/nab/updates +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.director_rollback/isSystem=true +/instance/org.eclipse.ui.ide/tipsAndTricks=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_dsdp_dd_updates/enabled=false +/instance/org.eclipse.search/org.eclipse.search.defaultPerspective=org.eclipse.search.defaultPerspective.none +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +/instance/org.eclipse.jdt.ui/sp_cleanup.on_save_use_additional_actions=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_.eclipseextension/version=1 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__findbugs.cs.umd.edu_eclipse/url=http\://findbugs.cs.umd.edu/eclipse +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.director_rollback/enabled=true +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache/suffix=artifacts.xml +/instance/org.eclipse.jdt.ui/sp_cleanup.use_parentheses_in_expressions=false +@org.eclipse.debug.ui=3.6.0.v20100601-1530 +@org.eclipse.core.net=1.2.100.I20100511-0800 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_emf_updates_/url=http\://download.eclipse.org/modeling/emf/updates/ +/instance/org.eclipse.jdt.ui/org.eclipse.jface.textfont=1|Courier New|10.0|0|WINDOWS|1|0|0|0|0|0|0|0|0|1|0|0|0|0|Courier New; +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_337_data_listener_1925729951_/name=metadata listener dropins +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_datatools_updates/isSystem=false +/instance/org.eclipse.ui.editors/printMargin=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse/name=Bundle pool +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_extras/url=http\://download.eclipse.org/tools/mylyn/update/extras +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +@org.eclipse.jdt.ui=3.6.0.v20100602-1600 +/instance/org.eclipse.contribution.weaving.jdt/org.eclipse.contribution.weaving.jdt.ask=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/provider= +/instance/org.eclipse.equinox.p2.ui.sdk/hour=1\:00 AM +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unnecessary_nls_tags=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_/version=1.0.0 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_modeling_mdt_updates_/enabled=false +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_modeling_gmf_updates_releases_/url=http\://download.eclipse.org/modeling/gmf/updates/releases/ +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_releases_ganymede/name=http\://download.eclipse.org/releases/ganymede +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_stp_updates_/url=http\://download.eclipse.org/stp/updates/ +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_/description= +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_mylyn_update_e3.4/url=http\://download.eclipse.org/tools/mylyn/update/e3.4 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +@org.eclipse.ui.browser=3.3.0.v20100517 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_335_data_listener_-1789306462_/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/configuration/org.eclipse.osgi/bundles/335/data/listener_-1789306462/ +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_methods=false +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.switch_perspective_on_suspend=always +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_types=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +/instance/org.eclipse.jdt.ui/content_assist_lru_history= +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__download.eclipse.org_rt_rap_update-site/isSystem=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_p2_org.eclipse.equinox.p2.core_cache_/type=org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/url=http\://download.eclipse.org/technology/mat/0.7/update-site/ +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/file\:_C\:_Program\ Files_eclipse-SDK-3.4-win32_eclipse_configuration_org.eclipse.osgi_bundles_191_data_listener_-1789306462_/url=file\:/C\:/Program Files/eclipse-SDK-3.4-win32/eclipse/configuration/org.eclipse.osgi/bundles/191/data/listener_-1789306462/ +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_tools_ajdt_34_update/type=org.eclipse.equinox.internal.p2.metadata.repository.LocalMetadataRepository +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__eclipse.org_tptp_updates_/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +/instance/org.eclipse.ui.ide/quickStart=false +/instance/org.eclipse.jdt.ui/org.eclipse.ajdt.ui.editor.outline.IntroductionFilter=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_mat_0.7_update-site_/version=1.0.0 +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_technology_rap_update-site/isSystem=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +/configuration/org.eclipse.equinox.p2.artifact.repository/repositories/http\:__eclipse.org_tptp_updates_/enabled=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +/configuration/org.eclipse.equinox.p2.metadata.repository/repositories/http\:__download.eclipse.org_releases_ganymede/url=http\://download.eclipse.org/releases/ganymede +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert diff --git a/instasearch/META-INF/MANIFEST.MF b/instasearch/META-INF/MANIFEST.MF new file mode 100755 index 0000000..1af9058 --- /dev/null +++ b/instasearch/META-INF/MANIFEST.MF @@ -0,0 +1,33 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: InstaSearch +Bundle-SymbolicName: it.unibz.instasearch;singleton:=true +Bundle-Version: 1.3.2 +Bundle-Activator: it.unibz.instasearch.InstaSearchPlugin +Bundle-DocURL: http://code.google.com/a/eclipselabs.org/p/instasearch/ +Bundle-UpdateLocation: http://code.inf.unibz.it/instasearch/downloads/ver.php +ErrorReportURL: http://code.inf.unibz.it/instasearch/downloads/contact/send.php +Require-Bundle: org.eclipse.ui;bundle-version="3.7.0", + org.apache.lucene;bundle-version="2.9.1", + org.apache.lucene.analysis;bundle-version="2.9.1", + org.apache.commons.httpclient, + org.apache.commons.lang, + org.eclipse.ui.ide;bundle-version="3.7.0", + org.eclipse.ui.editors, + org.eclipse.ui.workbench.texteditor, + org.eclipse.core.net, + org.eclipse.core.runtime;bundle-version="3.7.0", + org.eclipse.core.resources, + org.eclipse.search, + org.eclipse.jface.text, + org.eclipse.debug.ui, + org.eclipse.jdt.ui;resolution:=optional, + org.eclipse.jdt.core;resolution:=optional, + org.junit;bundle-version="4.0.0";resolution:=optional +Bundle-Vendor: Andrejs Jermakovics +Bundle-ClassPath: lib/lucene-highlighter-1.9.1.jar, + . +Eclipse-LazyStart: false +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin +Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/instasearch/build.properties b/instasearch/build.properties new file mode 100755 index 0000000..66d2f8c --- /dev/null +++ b/instasearch/build.properties @@ -0,0 +1,10 @@ +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + .,\ + icons/,\ + plugin.properties,\ + lib/lucene-highlighter-1.9.1.jar +bin.excludes = icons/sample.gif +src.excludes = test/ diff --git a/instasearch/icons/binary.gif b/instasearch/icons/binary.gif new file mode 100755 index 0000000000000000000000000000000000000000..e3eeb74cbd5ded8e6cd38e62a3cc4823c35e2ce9 GIT binary patch literal 366 zcmV-!0g?VkNk%w1VGsZi0M!5h^!EJt`TWSv-SzkU^!EF&x5;OHscL|$^7Z@n`26|$ z{P_9%ZG)|JinDWxvU-oVfR(#}mb;3c!jYb}@ALW>GF^w9z>T8Bk)_A7z0cn0`1AJr z-stz`?fL5P`SiF#P`t~m4QdGk3Oo4K&6R7q=-VGhD6}VkF=0Iu8cpfjX%_~Xw z6BPoKmPjlmniVAinxLdeDjlI6qynm^LMtSpB(1ZsJ}DuY6Ctg;okAxZ#KpxL8A&M1 M%+1SE(9uBvJNH7o^8f$< literal 0 HcmV?d00001 diff --git a/instasearch/icons/close.gif b/instasearch/icons/close.gif new file mode 100755 index 0000000000000000000000000000000000000000..1aca259db3187590fefc94c816bca144ef3d5d3e GIT binary patch literal 73 zcmZ?wbhEHb6krfwn8?6jA8*gV!0`Y7e;}#&lZBCifr&u}$Og&^0NGMg`d6NQ%P-22 ZVW$0o_tw|Ho*`y>u@XyPb%`)o0|0bQ6Wss+ literal 0 HcmV?d00001 diff --git a/instasearch/icons/collapseall.gif b/instasearch/icons/collapseall.gif new file mode 100755 index 0000000000000000000000000000000000000000..a2d80a9044f38833cb728a69c88294ce3fd007c7 GIT binary patch literal 157 zcmZ?wbhEHb6krfw*v!DtJ#F>UjfWZCs($|cfA#bKkH7!F`St(Z@BiQa{{Qv=|DXRL zz<>l4f3h$#FmN;IfW$y%FtB(Pob+71*X+evXI>YLE;&}Fj8#mRE%&W?B30shyu13% zpT6C#3k-fJGjKF52@24V6I?%GvcZa|)%y<^9(-F=IB9W`k6g3(YLhfsMh0sDZC^x! literal 0 HcmV?d00001 diff --git a/instasearch/icons/dates.gif b/instasearch/icons/dates.gif new file mode 100755 index 0000000000000000000000000000000000000000..96aae05cbf44981945d9bb16620e4641cb105610 GIT binary patch literal 181 zcmZ?wbhEHb6krfw*vtR~4fgi)?d$j3$Jg7}&$pkyfByXX{rl(NzrX+g|Nryn&u?gG zh>wp4ssnO?q~cE&Mg|5x1|5)AkQodtNf%CPp5N7;wMFFDsiurcGgQu28a!DzM`KUQ zl*(o5hXiWQ^RIBu3)hh1c5rrH@%d*1XKIpLL*zoOFwqGN3{0H|+Yd|R`ZGArIJnI6 eT+^XUhpKX6#{3;|ThIMuZft5SZEY1~um%88I!L|% literal 0 HcmV?d00001 diff --git a/instasearch/icons/down_arrow.gif b/instasearch/icons/down_arrow.gif new file mode 100755 index 0000000000000000000000000000000000000000..e96eb257674ed99bc93f440964bce52b0889b756 GIT binary patch literal 52 zcmZ?wbhEHbWM^P!XkcVu2&no0|G(l-79f+6L5BedKr#$W+&%pqrv={fcpJ`TVz34P DJ`oGG literal 0 HcmV?d00001 diff --git a/instasearch/icons/expandall.gif b/instasearch/icons/expandall.gif new file mode 100755 index 0000000000000000000000000000000000000000..0205b29176d4e60307639b6ac80ebfc40be61c3b GIT binary patch literal 164 zcmZ?wbhEHb6krfw*v!DtJ#F>UjfWZCs($|cfA#bKkH7!F`St(Z@Bg3w{Qvg%|F8f5 z|NI951{hHM$->CMz{8*e5&)UOz!Es&r043rW-rb<^SWqs$+0qJtYW%sxo^!AsVxqd z4Ij(xarn?aXSKr@L2f6e289eO){ZAef}c8<<#lln41*fD5c0}?0|NozX2%z|rg^__lm_Y}m7Gx&_Yrq4QzLZS1 z#|hIIl~z3slyFJd{XuKnq6PgLf(f50{&@AbTnxz(6FwE>vM|Cxg1hxGm!{{w1kc5a gmR(1lUe5S&^`qLp8*9pDKe?l~+j50|D+7Zy054ohcK`qY literal 0 HcmV?d00001 diff --git a/instasearch/icons/lightbulb.gif b/instasearch/icons/lightbulb.gif new file mode 100755 index 0000000000000000000000000000000000000000..542dddca3f29bc0bdb8149eafc372c37c6a0b1fd GIT binary patch literal 553 zcmZ?wbhEHb6krfwc*el+;?-NPgsN@(PDB;;v`t$vZ_S?7+YUt*b*ESMRCdjoxNy^+ zqvz@-E{?38nO4$}K5a+#g2M?_U4MT){QhRHQL#98EnEyO#{^Q=1ANQyId$#27%ME{DZvOjf z+xLTJ-){E*xIO9b(={Kr>VMdz_j!lm=beUMFL!*u*7NV_ns@7TK5W$ca<2Ky`PP?< zHC`>ze6>{b^$M-GtF-?=+4vs}7=|oR{K>+|z~IQB1M&eVP8itR8XTLN9W5;^TRNMJ zt$KTnyP8a_rR=9k*_ceUl~*^_GgX(j?b5Z=($rAY(A2Wi?Nl|BmXVW{laV%4?Nl=t zmk<&Wk`Omg>(Un%l@yZ{71p1qW8`q{n&HGI1*PlS3b&e+ud6(4;$`LHVSeVw@4&#s a{#L+&o9**6K^9I9zPFA{93dhc4AuZ>ez)NO literal 0 HcmV?d00001 diff --git a/instasearch/icons/lucene.gif b/instasearch/icons/lucene.gif new file mode 100755 index 0000000000000000000000000000000000000000..b4eeddb3c382be75d7e4b6432b4ec5dca1a5e70c GIT binary patch literal 335 zcmZ?wbhEHb6ky-$L(c>HD6`K~dPl43Qo;R4oeEG?kNe3@Jq~y zE3C+qk(1WZ(~gV@&&)~x|NsB{_wVoDzkmMx`ThI%uV24@{`~p<{r&az^#uh52?+@S z0RavU4h*CN#h)yU3=H-RIv}keKQXZ79GG8V;ZkZfwXN+&g^YS%Ytk+c!FpD{bruWes4cAt l7U*-8UPY6Y9{~y literal 0 HcmV?d00001 diff --git a/instasearch/icons/refresh.gif b/instasearch/icons/refresh.gif new file mode 100755 index 0000000000000000000000000000000000000000..e3831471a6592da14f53b1e7c5a2f7d6a92d9937 GIT binary patch literal 330 zcmZ?wbhEHb6krfwxXQrr@9+EHAGZ8_G3Dpu?%yxxeR;O-=iRE0x0<(4QTcee`1ifm zpO@2qo{itzBDSGSXh)sM<|^S$6~en4MRzrdZmSj9UMIS{QEXSE*vdSC6?p<{3I*2` z3$Dx)T#+ZZp;TynsnFUYp*4j44mHLpVZ-K zl_{b4!&vi3NsFvxfuFi>p>w)=5UaR2Lyxxzb4)b5h__%;3Y%bnva}Kxw?crk1h>pm LXEn6|M+R#EucKvr literal 0 HcmV?d00001 diff --git a/instasearch/icons/remove.gif b/instasearch/icons/remove.gif new file mode 100755 index 0000000000000000000000000000000000000000..2cd9c544436c47a57f20b348b3fb024bb50701a7 GIT binary patch literal 163 zcmZ?wbhEHb6krfw*v!DNV#SID3l_|nF=N7n2^}3B4Gj$y6%_>q1sNF`2?+`R|Nmz| z1&Tje7#SG27<53wATtBYuHJj2L#xNM)vQ#JRl<>hDKU#-N&yE`p}?0M(Gw4T zcQCOfDoF5h^e6?|s2Q}nBw9^i0I}eMb=?0hv=!;iZy|UTOS9Ern3j>2S03Llh A4*&oF literal 0 HcmV?d00001 diff --git a/instasearch/icons/sample.gif b/instasearch/icons/sample.gif new file mode 100755 index 0000000000000000000000000000000000000000..34fb3c9d8cb7d489681b7f7aee4bdcd7eaf53610 GIT binary patch literal 983 zcmZ?wbhEHb6krfw_|CxKYUg-n!?izO{@9*?jxd%4aX0yzy`dymabz zw#(eg=y~&N&n)dZv2xzduG}5lraiApo3(c4*{Ylg5#|$JO_EEZ<^|a2`Z*=9ns7DV zy=TR&gYw*7f%auV?ip3tvjRPmcdoho{K?x$_vR?C#t5&<;~V}S*>OMCr>h}%%bLZ9 zmo3`hYEwTICo-TTCZwgTsC&VjZRgJ1eE#fBa^%9R zmmfWS@;bnyJ27HWY}kxYzv(Hl>yu;FCPlAEh+34Muq-8Rb6C)<8qA3{r2e5 z`$vyngh#H=FWlqqvnapfc5%(!sQ4v?r7J61-&eJNEN^;KTK}T7{#i-gJh%G*9vcYdwv_*~xdw!Gz4Va?T!sXyyF@8?w<>X`X=#j%uHV4GRvj@+tE@ zQ%F!a)GKcn^~8abN>4la1UNXVL;{ZWi)lEwyeatDu%Lr6;aASiLrXXW zQm#*RNf? z`oQk}`*!YKK6~ljZF_cZ+HvgAv6IJ69zSyY;J$;WPMkV&@Th0*!vFtI{{R2)-9{Q{xYzi!ojzd!Hm)rnuOPWpOf;{Cn#PZn9eTp#{=Q|#Kl_?H9)`m^Y_v_E|osjQ0xhPeU?V7 zFYefq7px@erW32aOhZI~o1e+F);Uj8NSKj>%P7ZHO;TK&kDY#h literal 0 HcmV?d00001 diff --git a/instasearch/icons/search_results.gif b/instasearch/icons/search_results.gif new file mode 100755 index 0000000000000000000000000000000000000000..fed3e49d1598300ee94a706cfdc2d9c96df2f0ca GIT binary patch literal 360 zcmV-u0hj(qNk%w1VGsZi0M!5hu%)cKwYjsYu&SM>r<$azpQyyZ!?vxow5zhQr?0J} ztH8UzzPY`po29+Byt%Tt#=^$Q#>vOT$HBhA%E-#Z!NrD}zKoy3lcvU+tjnUaW5 zNo}G3|H=RV{{Hlh>fogN@U!XGbNT72`su3r>8twMefQs<_0^H|)spqpk>9<41eQ(kvMCGLI&6dsbmVP zAr9$8oBF_<(FvvFF2B}L>6CKKim#WfCO@g{K3zU96cH5+H*|nRgcJ}94+1-jLwPR} z69EVcICn)XA006c2LJ;(MxY%YJvIpi1gJ!+9$0XinlfZ literal 0 HcmV?d00001 diff --git a/instasearch/icons/syncdb.gif b/instasearch/icons/syncdb.gif new file mode 100755 index 0000000000000000000000000000000000000000..bb8538b396c21b6a8355295a62d07edc81a21bb4 GIT binary patch literal 362 zcmZ?wbhEHb6krfwxN5}k_}#C4m)>dSAJGn<@bhj}T+?o^!i_H3>ojxrMf9Ahn|*r5 zhHF~so0{gIesw%uGjp3q-o})+eHtP2-ye_r|Ewpg_t1yyb)I?at7o0kj-I8JxI!~~ zw^qX9m3!}NrmXq@xTR{^u?L6aOyic7PChnu?X|jD`?TWbO4wu`b1s5bZFfnxfqTKF>vVb_i^WSmBy4nDp>L<3`A9S?pAegU_Nm|!TpT0BZD;n2KbJ@ literal 0 HcmV?d00001 diff --git a/instasearch/icons/update.gif b/instasearch/icons/update.gif new file mode 100755 index 0000000000000000000000000000000000000000..1b724a6784910f0fb632fdf4df6b46a144555ad2 GIT binary patch literal 336 zcmZ?wbhEHb6krfwxXQr55IT)Fb|!D^4EglA3K?_dGv=CK0qT>Sf9>(8_Cdt1adlnL#q6WLrPyt`3!SEK0m zI?>&YVk`3mR^$n+DHL3hC%BBnnIz~g+PYz|NsAi&cp>2f3h$#FqkpufE0lI z#K4y8FgqYZi?`q7(Xkmen}SxJb-OAu&tZRT}eifdF;41SfF@krG-*ZXoxN^o#XigWm~3yMt<6%}OnWfKq<5fb8OD`Vm1V`gP- SG-KjoT;6*Pfg-V@=K4ljW1v0+qx}ngk@vPoA7q zUJhiJLo_{ka&qV9;sbl<|Nryp$;q{o)ztp~|6g8S4kQ^U28usf7#SEe8FWA=9d5QxBvCb`RTF$>Z$+hssHM#|Ldy%@xuS( zmH*?G^53Zc>$Cs&;s4>4|K+6r_1pi~e*f2h|JsTF-I|E=g_L$w}9ETe%7&k)UbQHm1WMTb<(VP$fI+@n{C9NZ@`*tyq9XY zlxVk;Xt9oEzKvA6lxVq=XuX$fyq0ROi(|T!YPXSSvyW!5jAZog=dXud|NsC0|Nj60 z00000A^8LW002DzEC2ui01yBW000Jyz@BhOEDlLXlCcQmIeD<9Fa!V)7#7bbi5!Xs z;IJ4R6OIz-v>ILRof`1CWA1>rO^|#(0&2BD5fE)C6@`TuJ5D+cqn9D(YArc5J6(Ox|zaXJ(%F|L0rJ)T&c; zYOP&&)j4}#n`hq&(x6~4Apd%pr_Qqd*W}+X&>&zSvZ5-2w32dS^zY*!APWB`g#t1A zBz=g3`C0QxD)|Kj1nu+vf04=x%1MfeDyz`RirL0CAOtd?i9V3Og}n>Fa!8m6@8&CF zM!z)ii4yO3T#lKKUXW~N&t=nI)8?eWQ`LGIdbz z$=-&T$j8E7%p04cQ@M5wD-QeGb=c5h{LI7-!09q&>K8SfF+r^-8h!e$sFdDc%lrTC z1lZ^D?48W%|L+vA|E4f>Ff_I>{ci|S{!VD)YHVuv-_c|L|I#~~8af$U{5L;C^51>U z!qVKr=5x6GuM0r^7xT?|H0L-zxk>gF1cd#cT|mUt%+S@wMbysN-o(_2&e+D#**Qg# zSALKI$@fD28=98Z5eTS}Agu(JN<>L`NE}sQfvWp*`cR5veAYKV3>gWyR}eq6okX#3 zV4!e4?(Tk<7cLL??>8{NLGTGpn|Ydft35T$%kizNl2AjP+Stv?vqzRA3y>|U=;qfV zoJbfMlP$p;(9CGEr*?=nC5d^Bk02Xh+X1LdO6$c+n#1N&9N5Qnuv+PHgcbDk zPU;hKi(jd7P`f`5iD^2C4HY2=PpX^I-C{84eUQJE9-WbB(-On&;&VVMU!cgctk^ce2oe?>;{#c#=3@8)0URow})yj$%7toDg1iF)-UO9CO(BcX$UgibubK~P9^CxGMD zIRF&#N4hIPnohZTZbr@_JM+u_B~Ttjt=^)4C_4likJWKf2pRZYMlL;_-7%5DQ8k3R zTZ{qcR9bt|PV9lqu(3#}J>mS$WF5UbfK@qX6umz+Jf#OQS?r`LxPCRlXc`$YuHnJWBy(xTltddVyPzy5cpB{VEvfi4D!zW@$R@JaJ<<~>G>OzeYc?i4VP`&b!hbobH z#LlxZm-(2To)%dK*SaqA$y->)g5Iwyi0GvlTdO|w3~iZ&0zcbz(Kh$_R7+o;h<@}8 z&2@SV=!}Jdj5g(CX(W3nCe#~>F>mm_8cPSu;hRgh83DxsyQb> z=Nvk?E`?r|ZaQY*%{%S4NBDQppo2s?0zPHu>T@vvzsb;Fs4 zMDNG6iPSN1gVZcjgF5iLBJE1K45?>Jw$NcFgu0qar$w?`BzU`O-KY~ahYL&y^bd)Me@aQq@3A>!XR;v;l8(;Er|o^!pWV#>WZhg;3(Y&ob^z? zLc{l>yjm0L4NQF1Lv~OatSY=uhRVI)VI@p8tONLtge_l(V%mFMq4zylhI>%p_b6!fmsDLYq$zaoHLzIq02_mG!*JVlZ&ma;3SW^uf03wQK~Cw?+b8GYX`!S zO`6awq)7sk8eG}i=IV8Stft@?$x(alN?K1mN(@OoWF>&9Q+q2bGB<3<07Kj{7AGCD z30NOW=NjTUt;E7=6pVPR$ZBTNO-qXg3w&4#E}A*f+7c5>k(rYk=1$99NONh5YrdyQ zlnl?YOpDBAr_+rs!)lJxXQIwyOx*h2X&)nlgZ>dkxnT`Fl0R=v+*si0s4Ym(@}mB! zER`AIXH8txmo_%>9m-c26lUG{7Yr?S6lFU1Prbv(sT?<)!;$Jq_^~l5%JND?Oji|I zdv;Wj2AaqfiM#dqj_h0}yI-)a`DHz26zhFzvxSXj%gw@4@bmV{<3+@_WM|}SRwdYW zx1o|Utzp&c8`%9EtBjjCVYRpPpIRQG0vpvfxxSZN}4pryUi39M>ngXf8A zy{K&T^{ukyf_HaTvMq-JGAyS@f@0#_OWxPo`1afGFc=sz_oOIllQJ&F#=9gw?z+Z$xO{*FGiBqDVYSOpv=9NEMFXTQ5m>KP!fFnhNe$JD< zlr|qjA{g%g3tNN*$^z)V;DXtp zIdEro1M+wAbxcsAmWw7!b1FWop+&^*pNEVRpa!vJY5T{F{;7!mvGB#o6<*hLP97&AqZDTgJiT%xq)DR+S$T5fz5lk%j*~a zyB&EhzJWaS>W&Q0l0Hg}cIL*3$VT!YePLxs`1YxrdNbn;!%jKxp2AVh-V)>81jfS@ zPMh9B`1!{eayTGyX9s@@qcg80<{lG^xHxUQYv8cY(+Oj-sZx8s*)rxIdoe@XCQG1= zn1_G)nSba7P6FpnEn?U(Y#Z3v;_7qlhw(frKHEHgMm54_R1-|1?mA1wv}RL1o?idNo&5&^(wz%1(T|JQHS0-l z(|ee7Lbh}yj@Tpp$Sd%K_`o|P`$JmcYkw7`br(#X7ewVLvDDYg{5`CDaEfiFF8YF3 zriFf~2QrUZ7CC(wFx6?&F69}zLKdVu3(gTtD63F*UW37r^xqltV14PS8`eFTr`6BNc73m1qhz#Mu}2C&%Hmd=<5F|0ymC1t7D zT2kDkY^-pp(q#W6DA`u#C1)jqu3V_}*(N(Gk0IyYtTz?`xAnZ_Mz4&*+M_f3rPJHg zY81a)Qz*Ktw^G{?aqF+(u-1E^w3&>JgU5=9stxGJ1O8}1?}TV}Ef`{&UX$8!r%j(@ zOcJk0DaqtV>n}pw8zT_(>EId2^M*sXie#~&w=YBhh7&Fb#f>KKWi)MgF1H!i&LsFoazouV`ZQ-S0T!{M3! z;0-JB$ortDAP?C)3_*LpZh#-|L{cZS6zG)pEb^8x^ZqrH@6- z$ka%44DJ^5484juzFrhXA6You=uyGD67+jAUk`t|d{<4fK$|M(__pU-alb;}W6xb? zp7PC5ABXjZ_6X}Sd~S|u8-&8fy2dbD=$9!?QOyjxdRCRM-?=1B&8=KBI0r%|oH5Kq z)*|&E5y8q@Dc%*g(UR<^oB0l*4z(HbE6kJk?^!RXt^dZH!IlLLs%-Evn6a(K!n(uy4hhjcQu#yhC&1TW<_ha)u%0n%fmt(BDvmXjuNb6Z z#;jyHu5R%D2*d#Ph}ZxO36H}U!FKXwYbRb&4m)#$>5u=24`PluZGR(xfIJX`fUx{C zmqy~RQ2sCHu0;dZCwVdDBhQ{d-|U7g0}KM|+fArRA`(>k;+I*lz+!krS&%OY_=)sm z227}C%AHHHx{_dM8>$Vf!>z6N?X6ZDwQFjf)~Btmou(fT zQzj@BgKmYr@1s6j?GM~>AMFp>&eQwH{5d@E1`#yu*NA#h5Zx9d%QEYiALyq)aSSmq8f3VczAQyLoBa-wU9mb==uIf?vY6#-cek;aXU=ryOp-qfOp(K1|G`9e(+{ zlRWp9xV+gHaqA)e`3KIsf+D|C9HF;jtUvA0?V}`-UnFMo04Dl`wA8D))b@nbpI*<$ z$9A0e&gbXI#wWs%M{vIif?g#Eebu<8lj}^Uy=C&m@e}{dNBWX&*FTRjbN(Yk_Oe|> z>D{H4wu1+$t-7bUwW}>=yC=FaYpa=B?k%?Ki}eKsrfc`)KUiQR)qsT&CLEdTC>O_V z;7Q(tkV`|WxQOKEBHGnNI2W9c1ajV7#@Cw;OqM|KC~c$b+EoXAK=)eh`LTUlk(=!R z0&uO(;LG>PV37cD|Ers~pR^wlXv8*FOPMMz-|C1Mr#+1q{Xy7lUUU@Ey~ zXmyZRd*C`8r;H+J>_S4Qo|KT}RE#p_>ZB_m#tsO!!EuABz~9)98mu&DN`ZSWLjDbm z+xZ7;6f&a+7aORD zlbor7`3fT~h4g4$YjIBNFmLdWIzro`?BoYFe2cc1MC8(%hz|^#QEfK)vY&vQqf1F9 z9E$VNKO1Q+@FqGRZVv_ROl1)$7(@q?Sg=`}Khh2viIMF>D-i-a@SlQ>*3ylN-7}jr zNqGFn1^k)jl-H2r!Vp_UP$JEpylO@w6T2_*J(_genH`(e>^b~uHX7RNWW(~r!}KHR zOy1%s*xlU7ZT<|$x<$_<0RfAXX9yI=)FZ=F9@Pn^#EDxvS`7vld4J+3MR~VH8Z8%c z)nWAs;{H7BYo4w#eN|zvS&nu8#WRzbQ2VaoZ!{S>;b!J6Uac$ZXd!m~Ms-*gqrE-y zJ|&kk9&-M6%`v=uf~EQFCcGEvr;T6jipts142Q0x!Fb)RR?=w09we6{_guuskdZ$1 zVtjqwL>J;{`K$|6oil!uOmfXk23>b*=|ZzL<+x*6EnXTbyrX%Qb7Gz@+>>1KHN^K1 zPN`pWecQdxu2c=IkZJzI$&D#4O173=5pnD5uEtV@etUNCdZN+Gr6yHTOCrUv`-1i(H%KW$iUsj(lsBg1IjaX)c{Z(~A4 zw?3O<0R0{#1AWn0|AjWt)DskILj<a(43WO2ZXJc2jzzQ3Me}t&tm_<_=n# zfz-t~P&dn9tYIi-TFdC>M~#v}BoL(ztuZIZVoZ6Hka@VV7^>G?L;eVip=2cyTw!{ao;Voa%`$s|K7b{N(AVyn>^ z*ZtCP5x1c~-*Pj(p&$y+8K|F7l|Xic51#1BaT{|P|gjN zB#SH5QPjDKdK8?7spH1t%9=AFx+I#3k=iNuORR&qcxqCGs;1)D{D#bk3ru}R?Mgxr z84%A}FAo1)>34QSI2YVFuuiZ8-(smu#B@_M^=FJ-l^Ff^iQCGM-Pju+Cxf#uyK`pX zu(xYe9R!OpGq2epemWBe5%&*PnPqkCi5i1}s1cQYI#-9CAl>r0A|DqbUPWc)2BR&D z{jc)y0}^i!LX~;i>E9upGRkvDTT(kSGHjc6by|M5H<}v3Tgz!&IOr2{JM2tMB*-+K zSX~xS?L?EZt-OdAO{Hzn9=%%zyQoz!hShc?H6m`I?bc#cT!=$TL{ikns6tQP*+{c~ zz}_OwhQbmbYllRJjIX!FG+sAN-d`}hso+kXH1KwsL?5`5X4b2+aXcIOdL_fb-@PUe(A!c{VkhL0t)`xpgF@b?frI;P`7mkc9-=NWXm-9 zS7g=W`iLSb-s@L1aCyO2_`!0V&|T|HU+z4;w+09d3}eU&Dk?Lbn4EypWTjc^I?1Ya zFp89~!~K=Y4oYQJURW14ITMtfI;Yt=J5xtAO9wVYKOWULj>_D*3>-S~Crk5ejJb;2^SDh0|HmTfj~g z2Y8hs(#nRIAj*u`S6likjsj}h%L?P z3~xd+=Ya-G948Q_XaX5#mSvR)7s3?iE^*gBN)V%@wo)vM6+h7Ok$CSGt}$*Ehvp89 zk6EEqQl1uxRpK;*Pn>qf^g?cyxjdsRbn{pO;F6uigg&hkzY9(DVrINZssGu{z!b2WCzs<@;fVXHr_BZ&UIRQLiNj#Q4nXc%N?*m zaTdBzPVc1sjQ|K^p#P0C@M=f{mC+BWfW{ziQ1Ip1np$4oaF(st84JDOtGF*RcJ&Er zIg0~~Aax}Sx;lJ;m-eVL1U*>fXDX2~8x9SUM_9uLEy$|0wMU^lbwPXaU8t8exP*v) z5$#qTKIg--BzeQw?8;kbz5KzcJr&^J3N`u|H*I4yjR5q8ns<-22!hF*~gAWjmynUrEm|GJwiZYb+#`!Z{mXUf|a$5 z&5pzF+&s;ZKT-jgXjD!9(`qV&YA{FxtQJMCk%?dA7chfUzW#=9jK(YS*ERgeE4wCJ z&v55VnO3nXi92DCnglL~jrDmhe1&NLye{N_k}9tGmdo z4`)x`A$cA_BYd-zy`HT~W!W;eA=+8cB(^umtQF=nCXja*O~GlRsyd09mT+LN1;SU; zb;gVVkl7v0m$0L*{cg|=!x%x?cab9ZS@C9DDuy_+Q`3u2rX_SqQfjS>=UihJ41EN0 zo{LpNoCl280}xL-)JD=d0udXy=$HmR|HVM$FO%vK@oUDVmDx)3a&3o73I>`J>b*4c zN;&S!f%#ZzysGgktW`wSlx1G%2aukVa`)#PtCP#h*QtedTM|P1lz3?&JMr%0a{AxJ zJ6Hp&Md_vG@e`NT?40;cY0H>!2DO=c3eJyz_&cvwYxq(+p{lsPaPlQ zFp)wT&-Q2nTgqSr+6a1ULJ_!rj00_)(Ojfwqci!YN2Lo;>6oSDU7=L8NyTbqWUEc+ zhLXm^PaM+w73SMW2)Pep7as)BtQ|ydC&)|0bqre%Hoo!mQAF6adjh#I42B;MbI{?7 zHhh92C_M*;?^Cs-oA0AOyKoPU0)k##VILNPjMr1NB|SZ12nHwsNp$z>?AuAj>wx42 zC*0o5Xu!jcy#)GiJ24ZfdxBges$UtC0c)<&9@pWqN|2m+ePvjJC(%CS&VhVIy9zG2 zS8c~^ziIXt#@72F1Xu};r-U!sw%`C*sLrnkjA)G*-1Drz_SsL-JV*ERcFJJM!?f$uL$pQ09|*x~x)Q@<=fh_d^$QrHZduOl+Ps%0mxYgcHq~IT{sH__+1*3- zg0ya%lV@4%%#-uCgCqg63sIwnOT*bwo|v$~1G%v-9rB~BYMsFeL60iPCw;qun2ID z^~)($OC?7sDp;rtOJ})~)RlsnZiXGLT=v+{DU(-fw|byZxh$(r)oBN$cEjG861Qaw zQD-BjRTp%4w?ivjp(lFhp@(+?_B^iT=eaG@gZ3*0QlmuzE6)!n!Q(GV;@!;q*9fQn z@t$dYD0n?2gaL6@3F3yQPNY~7jJ)$!IO<}k~1P%hS z1^1709iKH&Cr@Q#d#AtH)}p5Ej3$cq&Xr|i54tB5_{~BBj=U2Z6d4R&5WER#5_~i< z{dW!X+8Kh3S>i9v#(eu{v8VB%{ivQtF?2P%64hjRt$oC6^YSup^3E(1NA?P*s#f|k zdH*fWvgzYv{*U*4@BrpV>d-g_f2aHpb!uA#T3;++!R zG~HbK_8DN;%(Z7ICVQqPkjSRs5ZpZ`JD0hMGwMB8uiZ4gpvWL=0z3iZ!pLuu&bTFR z>kzSB?@C6xcj~s?lBmTvch}K+)j_AfPYDhZ!&C7h2OTAw=t45TIf?0f(k>plN95bj zG?}$KI_A5(?)Bf=;M;sS7kP#jT_+~t=Q9AysIh^aK!70M`jdh8T+#y%9dlVGurDI#6+|-+Rvc3}KTn&I$ZTuT#Fk-w{i6wPh5lYZiV2Etavf_Ys$D5lIN(S8vr!GuTWaxnd;{k|@qN9MX+y29##-byrI7q^? zbVWwMoV~dwDxgS-IlVC8Yp9U?eA>6N>er*kcl_I8*13I~vzeawc1-@p<=oqm-!#4k znp=N=X9ZE2`-v&FoxQW$E$`JnZOzZd=1zqwWK<{&)-WTBC7Jf04lJ6iS4Q@rR z_Dh{YDLK5Y^2)%|H_)3?sBD^A7u~lax%#A5iyeG$yXW0%D=By+*16}s6qhKKPRZ+Ae*GlKlMx}kcs;qDFowsA;D!b+VmoeO8mV|Y%HGx6r zl2vhA8QN@7FyW&z#j?6^utXTP$S-gx(ZSsKeX{w;L?^ouCKd*$1=Im)<%Eg>x;<9V z34yZAz`M~ntf_&5-E7c>Su99Zo#CT#(%=lOIct8X^ z3)u=zCh9e7uqmqKYvj>7gpqZ4m{=@@{%iQy5cSU3u5i`NlH+f7yllKz{F{x!J(AJ=L_iu5un%X-9`^giTd*HW|q67arkNrK%)68wyCo zx&o4fb*F9{^{hy^G5~EpI0V->>YKu*p;<|ww~(XGi1!yD;t-L09O?2bCy_BzJ$eKG z44S`KB0?hG6M{IZa}^Y#k_(2(Z{MfyO-fhQCQ|HVWCn^$YZf8Gr2r10ymY(jnF5Tl zb0E4UgA$W1*roD_a!BF`dWvC9GM2h(9~R$`g+XoYBxDK5FQrmjwShYH=7aBGGjLQo zuxu~R&-_~r*K3h6)y>yls!OACOJ%B>z~rSE|1W=6xf%t(srDd2K(bLmK)C-|dilRp zu8OIXt*D2KlcBMT{lAZR)u`KQqb+0i0DZAFC;|rpqm~}}8tZFYpos)z(M8(^3Inx_ zjPTsV-Od|>nxgv2V=Rr0vKEG#EomjQTGF;4AK zxYis>{2WdokCSj`u|A5GP+g#XZ9k%Y|D#59yp=tda(K#7m_|&fyaaq&lc>sIUTGCw1zCp0u|wgDV|N2-E%BCeMld5r zMC2i|usoKU_XGA@Hi6`6MuCL>l$2>G!4y8L;YcUVZuM8P@$3?mvi8#*!lvyu+u})y zX7??Pb*!=$gQrc`A~e@Z&+I2iQL5dQNUWZo(0GTJwWD7Fe4) z?6TMbGUL~~4=TSN4Xw+u z!rWX_=&qs-avTg+6sO91-t*jDgVEF!9359vLprnD3kUW+X2&Zr<)iGWyV!kZ%`Ul+FqN=2BKXwU zZS;ucftg=1w@aZW$^a$X$t$)%a~yKU5<{Fe@Ckf$ch;jvoncIzi*0(Gi(P5(IR1rm5y5>M z*9U}LLwKqct%2<^VJ>Fp`fH_O;|?M~y<%kB)PWK2XR=FZtx|K0fH$o;p_y~Y4(7sk zeIn@HQxm~?W)0$zHpNi6;i57qW;oV`)%>EBCZ~xAi)WU1%iHlcU4BCehtbVo4;3KW zQC}aY%vbg-1}KiL9oJ+vD>G6*8lMvCK2tQ;Y?}nLidi*7{5mw_++6q3u3`UCcv}vj z`mvSKp^X8`#oWt=iMX46e4K#EqRn1o=G?gIfnE*mhE7kHmiw)jUxT#CMq`na+C!BN z#xeG~g&DlrVMqhx!M`?RJg=;OV0gUoq=0BP- zOczB9#{g5WRo1)0J^jUy%au|I9yp51I#mc_ug)sf$lITq~ls$ zeh=1ZZ+Z_E(g!T#-*?otRQnkmV0*OwOqyTG_RSx3A1RU(_z?663bz~`faxEDz|MOA z##Ly*jWa;(bz`K1tcO*+86NdS3X|lI6-IewraXL*<*DL=a>G>HKJ}^G`;uEoK>v}o zF0YFZhluZ(jn>I~lpKp_Kz~2m5lPbALP)oIUOJ2bFr_S#W1zd*pcV4NTkc>Z~)DmnA5G{lYp!i_J}|1*C~j%_PE7C=#3B`yiu)kC+(w$WCuq~tvj-F^vJX5 z5e{j#VV7ZK14}&rda6Mdq@jqmFodCOd@s*Sy%JQ=sr z67!QMxbG#nbEqC{x9vV+B%~#Hx6!qYrmfn5vK9M6$H1v2zX(`L4RJQb|VUL zCza2l_)QebMlWb(^!?kj`8PK3E`*KG*@20!P#vZVCsG#T)dVVy&Thl$4l|h28Bt4E3hY0TalMl~+EFq4fXbc~dRcUh?KgVdn>{&K z%~Ln$+jE}y|>Cf1E2dXQgK`3!!ZT?5W{;USQJ@Yg5aR1pL!1)h1#nRTn#`HfE5IM?g zO7jY6x?!aeLo>uu-2vkpD0Ka>@;Z1B5%U=^BsG(xu%UM|1aQzv#hdR#;(0#T!`La< zgs&j{#WT6r)raOh&57N%;xTqLE>>40xP0UhEa z7bUfh1jeb4Fwn7&$7L6!tvA2V*G7C1Y&U2X?loA1u8r>KaOB8McDVgjmp+x$JXIx( z5ni3qY_XE!bly`=85*rYM9NPI|$RcbHtdH67y-4I|{s3{oGdiO29>u>{X1l+) zaD$s~tNO8x#{>wqJ4((gLu`bFpv|NlbCy&&jxH^E`^x)MIY)6}a&r}V1z6k==axgv zAaq^?kjR*|8YH_@PDTnr8z`0gRh1=v#01GlGA}qL_>QTpz#!XbhEgn4#VwksNryb? zfUT}HxsRsInlh~*SJe?l1AS>wVM~LqJ_ZuO8qkk+8qXquj;gF5&&p3EEN$5pRN57m zsEOkfMQ}@%l58%*`dILDQM~ep=#B>Qw-Gvu4397ME#V1Uy z>tn&g))>2;+63EU-np-1c8DCLbbZ!%jw6>|#uk}C>;DT{e`v-;3yx+QscD0(M+(qa zUv`4kiklkl?Nf4q#L-o>GBgfO{GrYRwOVM1~AF+$Ukqs z(z~(vXES`a?okHHK?1l;`5m z(g)A{sl^7l*LSQFDwg@vhgtbbP+tzg4<`6GN<*jzhUga-vRFoq1*H(J8-@^y^bzHb zQ+mcQ_H>}OPCw+h?qH081|yYGM$(t7PfZBQ|A zwvUr$=R=InDBsOxsBZasoX)f7CZ4W0jnTs(50>TzJOju9i~LPmH|&lg@K0T56vxp1m=^SLwypD}gGjz6H_s9otjt}z{joTd~n9Vvy2OU5S#*KRR7X`si54r33=YZ+CF%U+W_6H&r}j1QjdvM!(pB)wV4j-kcTGaFoA zT`)LlW|YS+O>$nkhMVBZH4ZWS^D)xT@RauQv%jIf;%1c$@NQVHU%|@aDK4Uh}5qG0$qR6M((QTpYcMJ*PjGJb-41j6Hxopc!o(J9^+4MdSR&AhX*_JpCQJ^unkh zIgtw9q;(OSk}|`He2Gd=8i^WJEj~z)RF$mw0TfaQ&fURX;5mYLH(l%;&lokYH~$rM z^&Pyi({&eD=@83by^gxrSZgDj#9fOQ-)d?G6H=peKuy9hC0$>^&^ozan#NG~7`Irl z4|ILdSJlZ_!zrlxEfIH!rAjJWdHvS^KYXDo`RB~y&&DRd&kPgaKNMvLL%aV=PezXF zmNSm(r+MIK&x(mDu0UxiHAn^e_ z=;~Kva8rf(#L zKR!zW51%E0*iFVY{3yTN%_GN`&yHTk9ch?qz$BTK7zri&wH-zm%io^HOZlC78Vve2*T^} z$(X6Ec)#iP^+;Xh?JQ~>RrfA@{nNm=2SnFbqGQv>>u-t zDzm2##pSSSyR5!5+4S_yQURCrE9*t{v^`{jyG!M#6&4E*w`IS|u-k$+?zwuvV|+-P zzE|PycIVb3Vmm2!cr?-iZ5tV;4ong)_6QX06@|)5PdP${Wo)g=@;JD$Tl;1!wz=Jk zJ*F6WvNCp1FpqfKCF<6YQXLTN1G=8(zK$(;1P>M$g_az0lWK;~V$Lkhwf`|8#rB1` z&+^~l;Z@c8fo9ea=nkC%s!gMe_edGS;+c5F8;Nl<3sX=Zw@HC^JqsCJXp+%yg_N;x zK_TTG=PVp-=Kqd9dxi>a{hef+KKRl+ESyL5?$kUSop?-wm@nAL{Ty-fHSm_SQb|T^ zNi8%T-arUfa}pe*E=MEVb2D)1$>3+~&~lJ#_)yaI+d~BVwoIkTy!CVDx^>kZ}BY99)6M(BRqEtIR)IFzs68fLLjXBD?%JTwfyldpL5y)EAE!5>uMw!&ed%|BlXNZ_5 z7veIA5qnBZvmoX}C6)IN9}l8-kKj~+ke>zF@oPI2X>gyu$+L}a_sdVXZ~UCr-|`0m zgo#tDV3A-6il%c9tfQOBVJVj+d!oYv>I@Y7QG%9QgO+_B_TSm~p|GVEd0%2|z1)C| z)`q{`vVq-ZNs!iXQq1)^=G|xkEOB=Dc zb__BnAAy^z)Rznr@~^sF%xbRO*_8{P^|s5rktj6k z?VQ~yUADeLVDDT9; z1+X8Px*xWEDAF1VtFh#OkQvGtZN)(^L$HhEgr!JWHhC72 z$e+=AhuEjLY6vDXX^=_(E_^2i>P5DmpOViUk|i1PQ^YDaV7_pan{v)u;usNFZU-lL z02%Lj;seJi+|6I1!G&O)Q|XaPN5j`8#WkcCi%cl#DCbVsbX(!`e_vHT^;`2?W;23ge!{1TZ1jxK=TC7F@m@=@b3so7gXS)D5{S9#|B?dhL-s7p-JAtzJ)pYflMN$xuvbFh;zUXb&Ry0GB9L zLXBJD(s_B_^Jxq_wCg_J&*edGA9+IH_#}7C5a%9MGQlnFB%QT0xv7R6)HA)Q)`8}8 zG~^A*B7z1c=kICze`;E84n_tCyeeMHuK-;)9>%8$0hBN%7}mLj>3a3H9q`)5{apgY z<@hVP^b9RcT2+_02hQ`AtD$T4Hq&e}(=NUD_**NJ}P&AoyH9EcJ^3av`53$EYZww zu${)<73CAC;1}ZRjy|<&wpEHP{;KPE1t%Iy@v6DbmYL2-iG+dD8Oz;VZ7jw>90-;+ zPav)>&TmE|-hY&iCFIB*_A8rKusitvRfCTE+q^G#c)FZ<6tj8dxd-|Sr3`Hdi%V&u zWM+bpw6~NVT+nGv(Mgi#d0C1g+}HV-`gBpsZAwurv!D{KBD-G`u{=rdsWZ;glbB{W zmqscEH!M4raN9L3n={tj!cmox>1PV$GvOsbbtL2)2p!)j}_cekk4*5P}tA4t}Gh680O_iXp8X zxt--G96@uY{CbYX8`U1T>vEwUzAo^NI3$L<#7AoFHj%mZBa-R5!YhSvtn7OyVCYTgCmrhdkzeRLA-w2E6QlWi)RKN-#eQ(Q zFFlgP1&Q|5SKAKGs6O@3xwg3ze~xsLuWWx7t6b;~Io8P@i3F3a=+OyjgiBE6jNI_M zDNwa4O0rduRz!8Fd?oyCh560b<~&KRU_(rp*K;fnj)R?=mxLs?OmOWO`S;@|GJrmwmhmJ+Phij#K8aPKU{=Yt+EegppG00F^q9OafmR|Sb2WMR2M>k+jqaWimfqEy*3hvneRq3>k4Uq&#C1kJO3 zjYi&&P#SJ-iMGmTYY(hCBA=PO!|`}DgHK-6R1wWs(@s-wFUd08RT@K1 zDP$#2drHO!Ov{~yS&C^@U&*!FaoABh$JO#yHQT_(fxE%R)8i5!>8+dd^g#oDsEoN4 z*pjcxV*iXnX8YN=8}dt<9T0|?lDJz3#B>@#-@-L4o9p6@*wvtJsT}2FZC~*P&&vR~ z8-WQ2{6!(mqh{6zTdY@A4l7U9Bgi%iTRdBRqDrzYllXM4;ji8~W^JJEP}(Y3 z$MVhYX>E2!1N+-P|-XUnzEM>~w}MVRhM1hY;y zT4~!d1)E==oT&2(WTVkONqyq()QP8>dq7`Ala99(DXJngQvW?G**Ek=6aGShL7OKJ zXcQQIGHql|BaLhF6=r7@C zSZJY(@DPjdq2lHOF|+?3C)t`emFK0-ijQP%8fLz(e&~~CT3J@WJHu8iJ8TUJUqx-2S?Q4x-|6fGGD6)e*g{& zFcl~<$MQo>;<==>=}0!^dMQW(QnYX9esnlp-T8z`N9lDl%Ixu-tXp?V%#2Mh z&typ9ZRl%et-|-^b3Up&K1+;|Ktjo`uW4k$(2cKmvUGe{7P7nZwCR#^L8;kBQA`&} z6+jfd`P1Ad44Gx&ak=q+UWBuT<;@lE9L;V%X_Q`N#>F+9e!|Cj)&HGEjsCr`@faK~ z8rmv`?civJZ3actb(pIo(bmcSdgjsv_V7_W_VdF{*DJg?lmzfY5m}SGAtTV{&ob*l zJT&|dNn~BmSWc7Tb^i0NaG}Qj(I`3_$VaOd95+k;<>&uTmaMnuN~Z@nDB95Xto9rX z?|BYQYqYtL@7|kLi04lCrNWs*eTsrGH^S2mTsRXxbJOZI&&$uD{bd1~GQPMo8cLo? znhcx-!tc)x`vzMj;XqMpB)rSSk}IIAHTU$$INnfP;pwQY$YUcVB60!VGPS(8wW2DmZjnUWw_z7?4{$`yiR_e<6Pz=yiaQA9uCLJR z4Qsj^c81SIT=q$%-e1Z}rWQ&nh1tnG>;4!kcR^2qE+M*^t|~TFMI~kE1N|X9SZg!R zjC6#6)qZ*p-|!W5#IZeI_hwU9E+mGy17`_%H|OXx};|_h(*SAaRu#9M@uo9=f(nYqNly<_*{U%Qc@uT znfpN12cPIPi1{kRoU6Nx2@svIq(Vn^nTIV-IfUntqe0Q`_LaW(7rcj)oNtV@aBOGQ z=+4fDG=v$C3_WlkkL!m7k~R#XI?meaT^uJ+74)A~!E^HG$P~YrHb_b7d96{L+r7PA z=?RJFu;QJ%1gn&nHUoT(N`pwHEr8UH*XgQEqarhllXk8AuL$5$H=Lo&$R29cKzLt1 z@DTqMbJx^xQR>=RE&hd_4%R}ZrnVHZ&M2ggoxFIBUTPv|`MCnbVuf7Jm!dM~T7K8y zhfUomP0R7@sqMqD*zhRCeaymT-Mv{w|bZPch;D_VPV6J=}Y2lCvd>yEZ)Mcpye!PrZ;%){ zZ2JaGqdOcYzowNOm%BQo9w0{cJ_bg*hT1IMVz-ZB$OeggwQbP(%s}UUHkIzbTKPGJ|p4wu3?6ihaGq8MMELKJre5~L?=Gesz`c*^^uq{54MDkq|H7rRFL z3YcNfHemb3sZsX(`zxD87gFxyMb|+5FZv2jdNCMX@D-eZ6ZsTNPMHMA!InaanoX4Z z3O54H?J3NJ7wTz7O8tw$A>J5>w!AVO*tqPUHH1**cpJ;tQ@(PtNt z(G#arc#ggaTa+zJy`^5c0it%Uu;^9EEK*?Xq1Podu6G&a-P`w* z@$|Xm0ra|9t56aokeU`WKVEa@;6qq3ql$_s*VHaxfi@gJf!rW;TFhN5^)W7?QM5dV z@wxshn=WBUv5R6&F)3DW87z!JbXNO+&aW%E@o} zR8H(uSik<9lXpW<$3cVuSX}EpPg_t&zHqPDS<6}GOH@>_b8$h6j$0q2BRtqte0z_5 zd24_kmd9OODiRu03>Z-5ih9Qq^2wC$Ve9q72>j(h+ByZDm$`X^S~_(K@u#jaF+HuN zS#d;u-CD5$oAFKVk4J!{e9h^s%sS13t`j719T5LBU081+d02_g7In~v2**qp^dLvd ze&`Gl-L?5+3vuH}Fzmq-F64xOy^WSaj{rc%g#_|B-8ik1afYgvNh55R1=ve0(YlN@yCM?4~-3ZI*zv;RPJxk)rit3Xj~t=jzbFBBw3&nGG%*^ z=!;?{DX3Rhu<))e=@X~^gij_ry>g3!FnY@uSMsDrR2eYO-D;Vw>IAWYuZ5MPc;?)ysL;XZ`_7^dQ@C zmr+*FOYfI0dIprr7yH=@SqMm8Rjs;*vh(I_MV1_#yO__^+e#htn6+%J$NdRHqOtEJd0TEgQ1&f zW{}t-0L7ZLwt7++)lRyqM_VQ59vbwBc1Wa_PQQr(oR(Z??O?qcqFTSM$lTKH8QWz; zs|vr*Au`ZxA`z8XwieG)*7GPVY7+QH?~$wIxf*$nTG8j069TgHEJDSgKArw?$~wdV zNne4^)<&EgfPIBCmCN~s9M}a$p|=MzwsEAnWv#M!1``Xgh;D&NL5?stbSzk*cMkv1 z+f-4!CabC?%jxFf2GOileJn+V*aO6-mc7X4PF?qZEtiq5C>`De7MoL^TdINw?R$OF z4Wq4$8WZGov}8|(!|-zDe<5r^-TPJ?wuotV4bM)DK7Qtr7JQq;zb zyoxmG3#}DtaYLY-zVUuLGJQUD zOR63j99>zy9O&ntroRZR{x|rMYU%gu2!0wJI^Q)+e=vX7IXzM_#aLYVkHt?-)4v-Y zshVO8b^dAiQ{(jS_D3qG82f-f+W*u%{kxlsKfL_!*NymZZZHyyn6L29DyTnvX8G

    Yf-#2>Mok3}MKBG}B;v$5z(Fc(+3b#WB2NwH9Fe#}=~0_`iv+{v5~u z@3NNI3~Zr83?m)AfBqMYAJbyk0Biw43?Pr_Sb)EjuCY1Tsy-Ob1N0%lF&6Th#t$|D zdkPXmC}uns;ZHM>*bwZ2Jq*O=!m%K~jqhO-u;)`Sgi+Sx6aFx*f(^p%WyOGiXr=j1+~^FMZoVq>s7@h}(=S~}`DYxr|t9ySNNLkYuiM4xK^E6)FM zQ^9T^!H`7It%k=T{k@$8dsW!Q>R(vs-j!ppelJ~PBd}|K7=)_y@eo**Kx_bZfdKl)gjZMWqCB;xp75_E$&kMueSz!>78plHXzR&t~ k6@N + + + + + + + + + + + + + + + + + + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/instasearch/src/it/unibz/instasearch/InstaSearch.java b/instasearch/src/it/unibz/instasearch/InstaSearch.java new file mode 100755 index 0000000..1c74739 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/InstaSearch.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch; + +import it.unibz.instasearch.indexing.WorkspaceIndexer; +import it.unibz.instasearch.indexing.WorkspaceIndexerJDT; +import it.unibz.instasearch.indexing.Searcher; +import it.unibz.instasearch.jobs.DeleteIndexJob; +import it.unibz.instasearch.jobs.IndexUpdateJob; +import it.unibz.instasearch.jobs.IndexingJob; +import it.unibz.instasearch.prefs.PreferenceConstants; + +import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.jobs.Job; + +/** + * InstaSearch class. Manages indexing jobs + */ +public class InstaSearch +{ + private WorkspaceIndexer indexer; + private Searcher searcher; + + private IndexingJob indexingJob; + private IndexUpdateJob indexUpdateJob; + + InstaSearch() throws Exception { + + try { + indexer = new WorkspaceIndexerJDT(); // if have JDT installed, we can index jars + } catch(Throwable ignored) { // NoClassDefFoundError + // no jdt, nevermind + } + + if( indexer == null ) + indexer = new WorkspaceIndexer(); // create default indexer + + searcher = new Searcher(); + indexer.setIndexChangeListener(searcher); + + InstaSearchPlugin.addPreferenceChangeListener(indexer); + InstaSearchPlugin.addPreferenceChangeListener(searcher); + + if( !indexer.isIndexed() || !indexer.isReadable() ) + createIndex(); + else + searcher.onIndexUpdate(); + + int indexUpdateInterval = InstaSearchPlugin.getIntPref(PreferenceConstants.P_INDEX_UPDATE_INTERVAL); + + indexUpdateJob = new IndexUpdateJob(indexer, searcher); + indexUpdateJob.setSystem(true); + indexUpdateJob.schedule(indexUpdateInterval); + + InstaSearchPlugin.addPreferenceChangeListener(indexUpdateJob); + } + + public WorkspaceIndexer getIndexer() { + return indexer; + } + + public Searcher getSearcher() { + return searcher; + } + + public void rebuildIndex() { + createIndex(); + } + + public void deleteIndex() { + DeleteIndexJob deleteIndexJob = new DeleteIndexJob(indexer); + deleteIndexJob.schedule(); + } + + public boolean isIndexing() { + if( indexingJob == null ) + return false; + + if( indexingJob.getState() == WorkspaceJob.RUNNING || indexingJob.getState() == WorkspaceJob.WAITING ) + return true; + + return false; + } + + /** + * Starts the indexing job + * + */ + public void createIndex() { + if( indexingJob == null ) { + indexingJob = new IndexingJob(indexer); + indexingJob.setPriority(Job.LONG); // long running job + } else if( isIndexing() ) + return; + + indexingJob.schedule(); + } + + void cancelJobs() { + if( indexingJob != null ) + indexingJob.cancel(); + + if( indexUpdateJob != null ) + indexUpdateJob.cancel(); + + } + + /** + * Update the index with the latest changes + */ + public void updateIndex() { + if( indexUpdateJob != null ) { + indexUpdateJob.cancel(); + indexUpdateJob.schedule(); + } + } +} diff --git a/instasearch/src/it/unibz/instasearch/InstaSearchPlugin.java b/instasearch/src/it/unibz/instasearch/InstaSearchPlugin.java new file mode 100755 index 0000000..e00da05 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/InstaSearchPlugin.java @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.core.net.proxy.IProxyService; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.IWorkingSetManager; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.util.tracker.ServiceTracker; + +/** + * The activator class controls the plug-in life cycle + */ +public final class InstaSearchPlugin extends AbstractUIPlugin { + + /** **/ + public final static String PLUGIN_ID = "it.unibz.instasearch"; + private final static String INDEX_DIR_NAME = "searchindex"; + + /** The shared plug-in instance */ + private static InstaSearchPlugin plugin; + + private String indexDirLocation; + private InstaSearch instaSearch; + private ServiceTracker proxyServiceTracker; + private boolean debug = false; + + /** + * The Plug-in instance + */ + public InstaSearchPlugin() { + plugin = this; + } + + public void start(BundleContext context) throws Exception { + + configureDebug(); + + try { + super.start(context); + } catch(Exception e) { + log(e); + throw e; + } + + plugin = this; + instaSearch = new InstaSearch(); + } + + public void stop(BundleContext context) throws Exception { + instaSearch.cancelJobs(); + + plugin = null; + super.stop(context); + + instaSearch = null; + } + + /** + * @return location of the index directory + */ + public static File getIndexDirLocation() + { + File indexDir = null; + + try { + indexDir = getStateDir(INDEX_DIR_NAME); + plugin.indexDirLocation = indexDir.getAbsolutePath(); // save + } catch(Exception e) { + log(e); + if( plugin.indexDirLocation != null ) + indexDir = new File(plugin.indexDirLocation); + } + + return indexDir; + } + + /** + * Returns a list of open project names + * @return ProjectNames + */ + public static List getProjectNames() { + + ArrayList projectNames = new ArrayList(); + if( getWorkspaceRoot() == null ) + return projectNames; + + IProject[] projects = getWorkspaceRoot().getProjects(); + + for(IProject project: projects) { + if( project.exists() && project.isAccessible() && project.isOpen() ) + projectNames.add(project.getName()); + } + + Collections.sort(projectNames, String.CASE_INSENSITIVE_ORDER); + + return projectNames; + } + + /** + * Array of working set names + * @return WorkingSets + */ + public static List getWorkingSets() { + ArrayList workingSets = new ArrayList(); + + IWorkingSetManager wsManager = getDefault().getWorkbench().getWorkingSetManager(); + if( wsManager == null ) + return workingSets; + + for(IWorkingSet ws: wsManager.getWorkingSets()) { + workingSets.add(ws.getName()); + } + + Collections.sort(workingSets, String.CASE_INSENSITIVE_ORDER); + + return workingSets; + } + + /** + * Returns project names within working set + * @param workingSet + * @return WorkingSetProjects + */ + public static String[] getWorkingSetProjects(String workingSet) { + + String emptyResults[] = new String[0]; + + IWorkingSetManager wsManager = getDefault().getWorkbench().getWorkingSetManager(); + if( wsManager == null ) + return emptyResults; + + IWorkingSet ws = wsManager.getWorkingSet(workingSet); + if( ws == null ) + return emptyResults; + + ArrayList projects = new ArrayList(); + IAdaptable elements[] = ws.getElements(); + + for( IAdaptable elem: elements ) { + if( elem instanceof IProject ) { + IProject proj = (IProject) elem; + projects.add( proj.getName() ); + } else { + IProject proj = (IProject) elem.getAdapter(IProject.class); + if( proj != null ) + projects.add( proj.getName() ); + } + } + + return projects.toArray(emptyResults); + } + + /** + * Returns the shared plugin instance + * + * @return the shared plugin instance + */ + public static InstaSearchPlugin getDefault() { + return plugin; + } + + /** + * Returns an image descriptor for the image file at the given + * plug-in relative path + * + * @param imageName the image name + * @return the image descriptor + * @see AbstractUIPlugin#imageDescriptorFromPlugin(String, String) + */ + public static ImageDescriptor getImageDescriptor(String imageName) { + return imageDescriptorFromPlugin(getPluginId(), "icons" + File.separator + imageName + ".gif"); + } + + /** + * Returns a directory in the plugin's state directory + * + * @param dirPath + * @return StateDir + */ + public static File getStateDir(String dirPath) + { + IPath stateLocation = plugin.getStateLocation(); + IPath path = stateLocation.append(dirPath); + + return path.toFile(); + } + + public static String getHomePageLocation() { + return getBundleHeader(Constants.BUNDLE_DOCURL); + } + + public static String getUpdateLocation() { + + return getBundleHeader(Constants.BUNDLE_UPDATELOCATION); + } + + public static String getErrorReportURL() { + return getBundleHeader("ErrorReportURL"); + } + + public static String getPluginName() { + return getBundleHeader(Constants.BUNDLE_NAME); + } + + public static String getPluginId() { + return PLUGIN_ID; + } + + public static String getFeatureId() { + return getPluginId() + ".feature"; + } + + public static String getVersion() { + return getBundleHeader(Constants.BUNDLE_VERSION); + } + + public static String getBundleHeader(String header) { + return (String) plugin.getBundle().getHeaders().get(header); + } + + public static void log(IStatus status) { + if( plugin != null ) + plugin.getLog().log(status); + else + ResourcesPlugin.getPlugin().getLog().log(status); + + if( status.getException() != null && isDebug() ) + status.getException().printStackTrace(); + } + + /** + * + * @return true if eclipse is running in debug mode + */ + public static boolean isDebug() + { + if( plugin == null ) return true; + return plugin.debug; + } + + /** + * Print messages if running in eclipse debug mode + * @param msgs + */ + public static void debug(Object... msgs) + { + if( ! isDebug() ) return; + + String msg = StringUtils.join(msgs, ", "); + + System.out.println(msg); + } + + public static void debug(Throwable t) + { + if( ! isDebug() ) return; + + t.printStackTrace(); + } + + public static void log(Exception e) { + Status status = new Status(IStatus.ERROR, getPluginId(), e.getMessage(), e); + log(status); + } + + public static InstaSearch getInstaSearch() + { + return plugin.instaSearch; + } + + public static boolean getBoolPref(String pref) { + return plugin.getPreferenceStore().getBoolean(pref); + } + + public static void setBoolPref(String pref, boolean value) { + plugin.getPreferenceStore().setValue(pref, value); + } + + public static int getIntPref(String pref) { + return plugin.getPreferenceStore().getInt(pref); + } + + public static IWorkspaceRoot getWorkspaceRoot() { + return ResourcesPlugin.getWorkspace().getRoot(); + } + + public static void addPreferenceChangeListener(IPropertyChangeListener listener) + { + if( plugin != null ) + plugin.getPreferenceStore().addPropertyChangeListener(listener); + } + + public static void removePreferenceChangeListener(IPropertyChangeListener listener) + { + if( plugin != null ) + plugin.getPreferenceStore().removePropertyChangeListener(listener); + } + + public IProxyService getProxyService() { + try { + if (proxyServiceTracker == null) { + proxyServiceTracker = new ServiceTracker(getBundle().getBundleContext(), IProxyService.class, null); + proxyServiceTracker.open(); + } + return proxyServiceTracker.getService(); + } catch (Exception e) { + InstaSearchPlugin.log(e); + } + + return null; + } + + private void configureDebug() + { + try { + // check if running in debug mode in Eclipse + + debug = debug || java.lang.management.ManagementFactory.getRuntimeMXBean(). + getInputArguments().toString().contains("-agentlib:jdwp"); + + } catch(Exception e) { + debug = true; + log(e); + } + } +} diff --git a/instasearch/src/it/unibz/instasearch/InstaSearchStartup.java b/instasearch/src/it/unibz/instasearch/InstaSearchStartup.java new file mode 100755 index 0000000..2952923 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/InstaSearchStartup.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch; + +import it.unibz.instasearch.actions.ShowInstaSearchAction; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.ui.IStartup; +import org.eclipse.ui.PlatformUI; + +/** + * This class forces the plugin to be started at eclipse startup (when this class is loaded) + * We need an early startup to start collecting changed files (for indexing) + */ +public class InstaSearchStartup implements IStartup +{ + public void earlyStartup() + { + IPreferenceStore prefs = InstaSearchPlugin.getDefault().getPreferenceStore(); + boolean shownView = InstaSearchPlugin.getBoolPref("shownView"); // false first time + + if( ! shownView ) + { + prefs.setValue("shownView", true); // do not show anymore on startup + + // Show view the first time after installation + PlatformUI.getWorkbench().getDisplay().asyncExec( new ShowInstaSearchAction() ); + } + } + + + +} diff --git a/instasearch/src/it/unibz/instasearch/actions/BuildIndexActionDelegate.java b/instasearch/src/it/unibz/instasearch/actions/BuildIndexActionDelegate.java new file mode 100755 index 0000000..37b160b --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/BuildIndexActionDelegate.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.actions; + +import org.eclipse.jface.action.IAction; + +public class BuildIndexActionDelegate extends InstaSearchActionDelegate +{ + @Override + public void run(IAction action) + { + getInstaSearch().rebuildIndex(); + } + +} diff --git a/instasearch/src/it/unibz/instasearch/actions/CheckUpdatesActionDelegate.java b/instasearch/src/it/unibz/instasearch/actions/CheckUpdatesActionDelegate.java new file mode 100755 index 0000000..bf911ea --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/CheckUpdatesActionDelegate.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.actions; + +import it.unibz.instasearch.jobs.CheckUpdatesJob; + +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.action.IAction; + +/** + * + */ +public class CheckUpdatesActionDelegate extends InstaSearchActionDelegate +{ + /** Action ID */ + public static final String ID = CheckUpdatesActionDelegate.class.getName(); + + @Override + public void run(IAction action) + { + Job checkUpdatesJob = new CheckUpdatesJob(); + checkUpdatesJob.setSystem(false); + checkUpdatesJob.schedule(); + } +} diff --git a/instasearch/src/it/unibz/instasearch/actions/CollapseAllActionDelegate.java b/instasearch/src/it/unibz/instasearch/actions/CollapseAllActionDelegate.java new file mode 100755 index 0000000..091e82f --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/CollapseAllActionDelegate.java @@ -0,0 +1,14 @@ +package it.unibz.instasearch.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.ui.IViewActionDelegate; + +public class CollapseAllActionDelegate extends InstaSearchActionDelegate + implements IViewActionDelegate { + + @Override + public void run(IAction action) { + view.collapseAll(); + } + +} diff --git a/instasearch/src/it/unibz/instasearch/actions/DeleteIndexActionDelegate.java b/instasearch/src/it/unibz/instasearch/actions/DeleteIndexActionDelegate.java new file mode 100755 index 0000000..f39f9bb --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/DeleteIndexActionDelegate.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.actions; + +import org.eclipse.jface.action.IAction; + +public class DeleteIndexActionDelegate extends InstaSearchActionDelegate +{ + @Override + public void run(IAction action) + { + getInstaSearch().deleteIndex(); + } + +} diff --git a/instasearch/src/it/unibz/instasearch/actions/ExpandAllActionDelegate.java b/instasearch/src/it/unibz/instasearch/actions/ExpandAllActionDelegate.java new file mode 100755 index 0000000..c1bad71 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/ExpandAllActionDelegate.java @@ -0,0 +1,14 @@ +package it.unibz.instasearch.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.ui.IViewActionDelegate; + +public class ExpandAllActionDelegate extends InstaSearchActionDelegate + implements IViewActionDelegate { + + @Override + public void run(IAction action) { + view.expandAll(); + } + +} diff --git a/instasearch/src/it/unibz/instasearch/actions/IncrementalSearchActionDelegate.java b/instasearch/src/it/unibz/instasearch/actions/IncrementalSearchActionDelegate.java new file mode 100755 index 0000000..834149b --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/IncrementalSearchActionDelegate.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.actions; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.prefs.PreferenceConstants; + +import org.eclipse.jface.action.IAction; + +public class IncrementalSearchActionDelegate extends InstaSearchActionDelegate { + + @Override + public void run(IAction action) + { + InstaSearchPlugin.setBoolPref(PreferenceConstants.P_INCREMENTAL_SEARCH, action.isChecked()); + } + +} diff --git a/instasearch/src/it/unibz/instasearch/actions/InstaSearchActionDelegate.java b/instasearch/src/it/unibz/instasearch/actions/InstaSearchActionDelegate.java new file mode 100755 index 0000000..1428c01 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/InstaSearchActionDelegate.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.actions; + +import it.unibz.instasearch.InstaSearch; +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.ui.InstaSearchView; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +public abstract class InstaSearchActionDelegate implements IViewActionDelegate +{ + protected InstaSearchView view; + + public void init(IViewPart view) + { + this.view = (InstaSearchView) view; + } + + public abstract void run(IAction action); + + public InstaSearch getInstaSearch() { + return InstaSearchPlugin.getInstaSearch(); + } + + public void selectionChanged(IAction action, ISelection selection) + { + //no-op + } + +} diff --git a/instasearch/src/it/unibz/instasearch/actions/OpenSearchDialog.java b/instasearch/src/it/unibz/instasearch/actions/OpenSearchDialog.java new file mode 100755 index 0000000..1f1d61b --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/OpenSearchDialog.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.actions; + +import it.unibz.instasearch.ui.InstaSearchPage; +import it.unibz.instasearch.ui.InstaSearchUI; + +import org.eclipse.jface.action.IAction; +import org.eclipse.search.ui.NewSearchUI; + +public class OpenSearchDialog extends InstaSearchActionDelegate { + + public OpenSearchDialog() { + } + + public void run(IAction action) { + // set editor as active so we can choose Enclosing project's in the search dialog + InstaSearchUI.getWorkbenchWindow().getActivePage().activate( InstaSearchUI.getActiveEditor() ); + NewSearchUI.openSearchDialog(InstaSearchUI.getWorkbenchWindow(), InstaSearchPage.ID); + } + +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/actions/PreferencesAction.java b/instasearch/src/it/unibz/instasearch/actions/PreferencesAction.java new file mode 100755 index 0000000..a22fab3 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/PreferencesAction.java @@ -0,0 +1,21 @@ +package it.unibz.instasearch.actions; + +import it.unibz.instasearch.prefs.InstaSearchPreferencePage; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.preference.PreferenceDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.PreferencesUtil; + +public class PreferencesAction extends InstaSearchActionDelegate +{ + + @Override + public void run(IAction action) + { + Shell shell = view.getViewSite().getShell(); + PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(shell, InstaSearchPreferencePage.ID, null, null); + dialog.open(); + } + +} diff --git a/instasearch/src/it/unibz/instasearch/actions/ShowExceptionAction.java b/instasearch/src/it/unibz/instasearch/actions/ShowExceptionAction.java new file mode 100755 index 0000000..7d46c5b --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/ShowExceptionAction.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.actions; + +import it.unibz.instasearch.ui.InstaSearchUI; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.action.Action; + +public class ShowExceptionAction extends Action +{ + public static final String ID = "it.unibz.instasearch.ui.InstaSearchUI.ShowExceptionAction"; + + private Throwable exception; + private IStatus status; + + public ShowExceptionAction(Throwable exception) + { + this.exception = exception; + + setId(ID); + setText("Exception"); + setDescription(exception.getMessage()); + setToolTipText(exception.getMessage()); + } + + public ShowExceptionAction(Exception exception, String text) + { + this(exception); + + setText(text); + } + + public ShowExceptionAction(IStatus status) + { + this(status.getException()); + + this.status = status; + } + + @Override + public void run() + { + if( status != null ) + InstaSearchUI.showError(status, getText()); + else + InstaSearchUI.showError(exception, getText()); + } +} diff --git a/instasearch/src/it/unibz/instasearch/actions/ShowInstaSearchAction.java b/instasearch/src/it/unibz/instasearch/actions/ShowInstaSearchAction.java new file mode 100755 index 0000000..1d2db06 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/ShowInstaSearchAction.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.actions; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.prefs.PreferenceConstants; +import it.unibz.instasearch.ui.InstaSearchPage; +import it.unibz.instasearch.ui.InstaSearchUI; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.search.ui.NewSearchUI; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; + +public class ShowInstaSearchAction implements IWorkbenchWindowActionDelegate, Runnable { + + public ShowInstaSearchAction() { + } + + public void run(IAction action) { + run(); + } + + public void run() + { + boolean dialogOnShortcut = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_DIALOG_ON_SHORTCUT); + + if( dialogOnShortcut ) + NewSearchUI.openSearchDialog(InstaSearchUI.getWorkbenchWindow(), InstaSearchPage.ID); + else + InstaSearchUI.showSearchView(); + } + + public void dispose() + { + } + + public void init(IWorkbenchWindow window) + { + } + + public void selectionChanged(IAction action, ISelection selection) + { + } + +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/actions/VisitHomePageActionDelegate.java b/instasearch/src/it/unibz/instasearch/actions/VisitHomePageActionDelegate.java new file mode 100755 index 0000000..fba3e88 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/actions/VisitHomePageActionDelegate.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.actions; + +import it.unibz.instasearch.ui.InstaSearchUI; + +import org.eclipse.jface.action.IAction; + +public class VisitHomePageActionDelegate extends InstaSearchActionDelegate +{ + @Override + public void run(IAction action) + { + try + { + InstaSearchUI.showHomePage(); + } catch (Exception e) + { + InstaSearchUI.showError(e, "Error Opening Page"); + } + } + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/Field.java b/instasearch/src/it/unibz/instasearch/indexing/Field.java new file mode 100755 index 0000000..768721f --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/Field.java @@ -0,0 +1,58 @@ +package it.unibz.instasearch.indexing; + +import org.apache.lucene.index.Term; + +/** + * Document fields for indexing and searching + */ +public enum Field +{ + EXT("Extension"), PROJ("Project"), WS("Working Set"), + CONTENTS, FILE, NAME, JAR, DIR, MODIFIED("Modified"); + + private String title; + + private Field() { + } + + private Field(String title) { + this.title = title; + } + + /** + * @return the title + */ + public String getTitle() { + if( title == null ) + return name(); + + return title; + } + + /** + * Create a term of this field + * @param text + * @return Term + */ + public Term createTerm(String text) { + return new Term(name().toLowerCase(), text); + } + + /** + * + * @param fieldName (case insensitive) + * @return Field or null if no such field exists + */ + public static Field getByName(String fieldName) + { + try { + return Field.valueOf(fieldName.toUpperCase()); + } catch(Exception e) { + return null; + } + } + + public String toString() { + return name().toLowerCase(); + } +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/indexing/FileAnalyzer.java b/instasearch/src/it/unibz/instasearch/indexing/FileAnalyzer.java new file mode 100755 index 0000000..24ab530 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/FileAnalyzer.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import it.unibz.instasearch.indexing.tokenizers.CamelCaseTokenizer; +import it.unibz.instasearch.indexing.tokenizers.DotSplitTokenizer; +import it.unibz.instasearch.indexing.tokenizers.WordSplitTokenizer; +import it.unibz.instasearch.indexing.tokenizers.standard.StandardTokenizer; + +import java.io.IOException; +import java.io.Reader; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.LengthFilter; +import org.apache.lucene.analysis.LowerCaseFilter; +import org.apache.lucene.analysis.TokenFilter; +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.analysis.tokenattributes.TermAttribute; + + +public class FileAnalyzer extends Analyzer { + + private int minWordLength; + + public FileAnalyzer(int minWordLength){ + super(); + + this.minWordLength = minWordLength; + } + + public TokenStream tokenStream(Reader reader) { + + TokenStream result = new StandardTokenizer(reader); // splits at ". ", "-", etc. + + //result = new SysoFilter(result); + + result = new WordSplitTokenizer(result); // non-alphanumerics + result = new DotSplitTokenizer(result); // all.package.names + result = new CamelCaseTokenizer(result); // CamelCaseIdentifiers + + result = new LengthFilter(result, minWordLength, 128); + result = new LowerCaseFilter(result); + + return result; + } + + @Override + public TokenStream tokenStream(String fieldName, Reader reader) { + return tokenStream(reader); + } + + @SuppressWarnings("unused") // used when debugging + private static class SysoFilter extends TokenFilter + { + private TermAttribute termAtt; + + public SysoFilter(TokenStream input) + { + super(input); + termAtt = (TermAttribute) addAttribute(TermAttribute.class); + } + + @Override + public boolean incrementToken() throws IOException + { + if (input.incrementToken()) { + System.out.println("TERM: " + termAtt.term()); + return true; + } + + return false; + } + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/LengthNormSimilarity.java b/instasearch/src/it/unibz/instasearch/indexing/LengthNormSimilarity.java new file mode 100755 index 0000000..569629a --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/LengthNormSimilarity.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + + +import org.apache.lucene.search.DefaultSimilarity; + +/** + * + */ +public class LengthNormSimilarity extends DefaultSimilarity +{ + /** + * + */ + private static final long serialVersionUID = 1L; + + @Override + public float lengthNorm(String fieldName, int numTerms) + { + + if( fieldName.equals(Field.CONTENTS.toString()) ) + return 1.0f; // don't decrease relevance for long documents + else + return super.lengthNorm(fieldName, numTerms); + + //Alternative - Sweetspot similarity: + // 1/sqrt( steepness * (abs(numTerms-min) + abs(numTerms-max) - (max-min)) + 1 ) . + // - steepnes = 0.5, for [min, max] term docs returns 1 + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/QueryAnalyzer.java b/instasearch/src/it/unibz/instasearch/indexing/QueryAnalyzer.java new file mode 100755 index 0000000..ed3eb23 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/QueryAnalyzer.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import it.unibz.instasearch.indexing.tokenizers.CamelCaseTokenizer; +import it.unibz.instasearch.indexing.tokenizers.DotSplitTokenizer; +import it.unibz.instasearch.indexing.tokenizers.WordSplitTokenizer; +import it.unibz.instasearch.indexing.tokenizers.standard.StandardTokenizer; + +import java.io.Reader; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.KeywordTokenizer; +import org.apache.lucene.analysis.LengthFilter; +import org.apache.lucene.analysis.TokenStream; + +/** + * Analyzer for user entered search queries + */ +public class QueryAnalyzer extends Analyzer { + + private static final int MAX_WORD_LENGTH = 128; + private int minWordLength; + + public QueryAnalyzer(int minWordLength) { + super(); + + this.minWordLength = minWordLength; + } + + @Override + public TokenStream tokenStream(String fieldName, Reader reader) + { + if( Field.CONTENTS.toString().equals(fieldName) ) { + TokenStream result = new StandardTokenizer(reader); // splits at ". ", "-" + + result = new WordSplitTokenizer(result); // non-alphanumerics + result = new DotSplitTokenizer(result); // com.package.names + result = new CamelCaseTokenizer(result); // CamelCaseIdentifiers + + //result = new LowerCaseFilter(result); + result = new LengthFilter(result, minWordLength, MAX_WORD_LENGTH); + + return result; + + } else { // PROJECT, EXT fields + return new KeywordTokenizer(reader); // return whole stream contents as token + } + + } + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/ResourceCollector.java b/instasearch/src/it/unibz/instasearch/indexing/ResourceCollector.java new file mode 100755 index 0000000..3cd41b6 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/ResourceCollector.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.regex.Pattern; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceVisitor; +import org.eclipse.core.runtime.CoreException; + +public class ResourceCollector implements IResourceVisitor +{ + private Collection containers = new LinkedList(); + private List excludedPatterns = new ArrayList(); + + public ResourceCollector() { + } + + public boolean visit(IResource resource) throws CoreException { + + if( !(resource instanceof IContainer) ) + return false; + + if( isResourceExcluded(resource, excludedPatterns) ) + return false; + + switch(resource.getType()) + { + case IResource.FOLDER: + containers.add((IContainer)resource); + break; + case IResource.PROJECT: + return visit((IProject) resource); + } + + return true; + } + + + /** + * @param resource + * @param excludedDirPatterns + * @return + */ + static boolean isResourceExcluded(IResource resource, + List excludedDirPatterns) + { + String path = resource.getFullPath().toString(); + + if( path.startsWith("/") ) path = path.substring(1); + + for(Pattern pattern: excludedDirPatterns) + { + if( pattern.matcher(path).matches() ) + return true; + } + + return false; + } + + public boolean visit(IProject project) { + if( !project.isOpen() ) // don't visit closed projects + return false; + + containers.add(project); + + return true; + } + + public Collection getContainers() { + return containers; + } + + /** + * + */ + public void clear() { + containers.clear(); + excludedPatterns.clear(); + } + + /** + * @param excludedDirRegExes + */ + public void setExcludedDirRegExes(List excludedDirRegExes) { + this.excludedPatterns = new ArrayList(excludedDirRegExes); + } + +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/indexing/SearchQuery.java b/instasearch/src/it/unibz/instasearch/indexing/SearchQuery.java new file mode 100755 index 0000000..70750f9 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/SearchQuery.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import java.util.Map; +import java.util.Set; + +/** + * A search query + */ +public class SearchQuery +{ + private String searchString; + /** + * maximum number of results to return ({@link #UNLIMITED_RESULTS} for all results) + */ + private int maxResults = UNLIMITED_RESULTS; + private boolean exact = true; + private boolean fuzzy = false; + private boolean canceled = false; + private String currentProject; + private Map> filter; + + /** + * Unlimited search results + */ + public static final int UNLIMITED_RESULTS = -1; + + public SearchQuery(String searchString, int maxResults) + { + this.searchString = searchString; + this.maxResults = maxResults; + } + + /** + * + * @param searchQuery + */ + public SearchQuery(SearchQuery searchQuery) { + this.searchString = searchQuery.searchString; + this.maxResults = searchQuery.maxResults; + this.fuzzy = searchQuery.fuzzy; + this.exact = searchQuery.exact; + } + + /** + * @return the searchString + */ + public String getSearchString() + { + return searchString; + } + + /** + * @return maxResults + */ + public int getMaxResults() + { + return maxResults; + } + + public boolean isLimited() + { + return (maxResults != UNLIMITED_RESULTS); + } + + /** + * @param maxResults + */ + public void setMaxResults(int maxResults) + { + this.maxResults = maxResults; + } + + /** + * Whether the query is exact or should be split into tokens + * @return the exact + */ + public boolean isExact() + { + return exact; + } + + /** + * @param exact Whether the query is exact or should be split into tokens + */ + public void setExact(boolean exact) + { + this.exact = exact; + } + + /** + * + * @return fuzzy + */ + public boolean isFuzzy() { + return fuzzy; + } + + /** + * Make a fuzzy query to find similar matches + * @param fuzzy + */ + public void setFuzzy(boolean fuzzy) { + this.fuzzy = fuzzy; + } + + @Override + public boolean equals(Object obj) + { + if( obj == this ) return true; + if( obj == null || ! (obj instanceof SearchQuery) ) return false; + + SearchQuery sq = (SearchQuery) obj; + + if( fuzzy != sq.isFuzzy() ) return false; + if( exact != sq.isExact() ) return false; + if( maxResults != sq.getMaxResults() ) return false; + if( ! searchString.equals(sq.getSearchString()) ) return false; + if( filter != null && sq.filter != null ) + { + if( ! filter.equals(sq.filter) ) return false; + } + else if( filter != sq.filter ) return false; // one is null + + return true; + } + + /** + * Cancel the query during its execution + * @param canceled + */ + public void setCanceled(boolean canceled) { + this.canceled = canceled; + } + + /** + * @param searchString the searchString to set + */ + public void setSearchString(String searchString) { + this.searchString = searchString; + } + + /** + * + * @return true if search query has been canceled + */ + public boolean isCanceled() { + return canceled; + } + + /** + * The project that was active when the query was run + * @return the current Project + */ + public String getCurrentProject() { + return currentProject; + } + + /** + * @param currentProject + */ + public void setCurrentProject(String currentProject) { + this.currentProject = currentProject; + } + + /** + * @param filter + */ + public void setFilter(Map> filter) { + this.filter = filter; + } + + /** + * @return the filter + */ + public Map> getFilter() { + return filter; + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/SearchResult.java b/instasearch/src/it/unibz/instasearch/indexing/SearchResult.java new file mode 100755 index 0000000..4795b10 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/SearchResult.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import java.util.List; +import java.util.Map; + +/** + * Container for search results + */ +public class SearchResult { + + private List resultDocs; + private Map searchTerms; + private SearchQuery query; + + public SearchResult(SearchQuery searchQuery, List resultDocs, Map searchTerms) + { + this.query = searchQuery; + this.resultDocs = resultDocs; + this.searchTerms = searchTerms; + } + + public boolean isEmpty() + { + return resultDocs.isEmpty(); + } + + /** + * @return the query + */ + public SearchQuery getQuery() + { + return query; + } + + public List getResultDocs() + { + return resultDocs; + } + + public Map getSearchTerms() + { + return searchTerms; + } + + public boolean isFull() { + return resultDocs.size() == query.getMaxResults(); + } +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/indexing/SearchResultDoc.java b/instasearch/src/it/unibz/instasearch/indexing/SearchResultDoc.java new file mode 100755 index 0000000..eb2c2c6 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/SearchResultDoc.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import it.unibz.instasearch.InstaSearchPlugin; + +import java.io.IOException; +import java.util.Collection; + +import org.apache.lucene.document.Document; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.Term; +import org.apache.lucene.index.TermFreqVector; +import org.apache.lucene.search.Similarity; +import org.apache.lucene.store.Directory; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + + +public class SearchResultDoc { + + private Document doc; + private int docId; + private TermFreqVector termFreqVector; + private float[] termScoreVector; + private float score; + private int matchCount; + private Directory indexDir; + + public SearchResultDoc(Directory dir, Document doc, int docId, float score) { + this.indexDir = dir; + this.docId = docId; + this.doc = doc; + this.score = score; + + matchCount = 0; + } + + private String getFieldValue(Field field) { + return doc.get(field.toString()); + } + + public String getFilePath() { + return getFieldValue(Field.FILE); + } + + public String getFileName() { + return getFieldValue(Field.NAME); + } + + public String getFileExtension() { + return getFieldValue(Field.EXT); + } + + public boolean isInJar() { + if( doc.getField(Field.JAR.toString())==null ) + return false; + + String jarField = getFieldValue(Field.JAR); + + if( StorageIndexer.NO_VALUE.equals(jarField) ) + return false; + + if( jarField.toLowerCase().endsWith(".jar") ) + return true; + + return false; + } + + public String getJarName() { + + if( isInJar() ) + return getFieldValue(Field.JAR); + + return null; + } + + public IPath getProject() { + return new Path(getFieldValue(Field.PROJ)); + } + + public String getProjectName() { + return getProject().lastSegment(); + } + + /** + * + * @return + * @throws IOException + */ + private float[] getTermScoreVector() throws IOException + { + if( termScoreVector == null ) { + IndexReader reader = IndexReader.open(indexDir, true); + + if( termFreqVector == null ) + createFreqVect(reader); + + termScoreVector = createTermScoreVector(termFreqVector, reader); + reader.close(); + } + + return termScoreVector; + } + + private TermFreqVector getTermFreqVector() throws IOException + { + if( termFreqVector == null ) { + IndexReader reader = IndexReader.open(indexDir, true); + createFreqVect(reader); + reader.close(); + } + + return termFreqVector; + } + + private void createFreqVect(IndexReader reader) throws IOException + { + termFreqVector = reader.getTermFreqVector(docId, Field.CONTENTS.toString()); // obtain only when requested + } + + /** + * Returns a vector of given term scores (tf-idf). + * The size of the vector is the number of terms in this document + * The term positions in the vector are the same as in the term frequency vector + * + * @param terms + * @return TermScoreVector + * @throws IOException + */ + public float[] getTermScoreVector(Collection terms) throws IOException + { + float[] allTermScoreVect = getTermScoreVector(); + float[] termScoreVect = new float[allTermScoreVect.length]; + TermFreqVector freqVector = getTermFreqVector(); + + for(String term: terms){ + int idx = freqVector.indexOf(term); // does a binary search + if( idx == -1 ) continue; + termScoreVect[idx] = allTermScoreVect[idx]; + } + + return termScoreVect; + } + + public double getTermScore(String term) throws IOException + { + float[] allTermScoreVect = getTermScoreVector(); + TermFreqVector freqVector = getTermFreqVector(); + + if( freqVector == null ) return 0; + + int idx = freqVector.indexOf(term); // does a binary search + if( idx == -1 ) return 0; + return allTermScoreVect[idx]; + } + + private float[] createTermScoreVector(TermFreqVector vect, IndexReader reader) throws IOException + { + if( vect == null ) + return new float[0]; + + int[] termFrequencies = vect.getTermFrequencies(); + String[] terms = vect.getTerms(); + float[] scores = new float[terms.length]; + + int numDocs = reader.maxDoc(); + Similarity sim = Searcher.SIMILARITY; + + for(int i = 0; i < terms.length; i++) { + String termText = terms[i]; + Term term = new Term(Field.CONTENTS.toString(), termText); + + float termFreq = sim.tf( termFrequencies[i] ); + + int docFreq = reader.docFreq(term); + float idf = sim.idf(docFreq, numDocs); + + float tfIdf = termFreq * idf; + + scores[i] = tfIdf; + } + + return scores; + } + + public IFile getFile() + { + if( isInJar() ) return null; + + Path path = new Path(getFilePath()); + IWorkspaceRoot workspaceRoot = InstaSearchPlugin.getWorkspaceRoot(); + IFile file = workspaceRoot.getFile(path); + + if( file == null || file.getRawLocation() == null ) + file = workspaceRoot.getFileForLocation(path); + + return file; + } + + /** + * @return the score + */ + public float getScore() + { + return score; + } + + /** + * @return the doc + */ + public Document getDoc() + { + return doc; + } + + /** + * @return the docId + */ + public int getDocId() + { + return docId; + } + + /** + * @return the matchCount + */ + public int getMatchCount() + { + return matchCount; + } + + /** + * Computes match count as SUM( tf ) of all query terms in the document + * Accesses the index thus affects performance + * + * @param reader + * @param queryTerms + * @throws IOException + */ + public void computeMatchCount(IndexReader reader, Collection queryTerms) throws IOException + { + if( termFreqVector == null ) + createFreqVect(reader); + + if( termFreqVector == null ) + return; + + int freqs[] = termFreqVector.getTermFrequencies(); + int freqSum = 0; + + for(String term: queryTerms){ + int idx = termFreqVector.indexOf(term); // does a binary search + if( idx == -1 ) continue; + freqSum += freqs[idx]; + } + + matchCount = freqSum; + } + + @Override + public String toString() { + return getFilePath(); + } +} + + diff --git a/instasearch/src/it/unibz/instasearch/indexing/Searcher.java b/instasearch/src/it/unibz/instasearch/indexing/Searcher.java new file mode 100755 index 0000000..fef8640 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/Searcher.java @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import static it.unibz.instasearch.InstaSearchPlugin.debug; +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.indexing.StorageIndexer.IndexChangeListener; +import it.unibz.instasearch.indexing.querying.CSVExpander; +import it.unibz.instasearch.indexing.querying.CurrentProjectSetter; +import it.unibz.instasearch.indexing.querying.FieldAliasConverter; +import it.unibz.instasearch.indexing.querying.FileNameSearcher; +import it.unibz.instasearch.indexing.querying.FilterSetter; +import it.unibz.instasearch.indexing.querying.FolderSearcher; +import it.unibz.instasearch.indexing.querying.LastTermQueryPrefixer; +import it.unibz.instasearch.indexing.querying.LowercaseConverter; +import it.unibz.instasearch.indexing.querying.ModifiedTimeConverter; +import it.unibz.instasearch.indexing.querying.QueryFuzzifier; +import it.unibz.instasearch.indexing.querying.UppercaseNameExpander; +import it.unibz.instasearch.indexing.querying.VisitableQuery; +import it.unibz.instasearch.indexing.querying.WorkingSetExpander; +import it.unibz.instasearch.prefs.PreferenceConstants; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.KeywordAnalyzer; +import org.apache.lucene.document.Document; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.Term; +import org.apache.lucene.index.TermEnum; +import org.apache.lucene.queryParser.ParseException; +import org.apache.lucene.queryParser.QueryParser; +import org.apache.lucene.queryParser.QueryParser.Operator; +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.BooleanQuery.TooManyClauses; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.TopDocCollector; +import org.apache.lucene.search.highlight.QueryTermExtractor; +import org.apache.lucene.search.highlight.WeightedTerm; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.FSDirectory; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + +/** + * Searcher for searching the index using SearchQuery + */ +@SuppressWarnings("deprecation") +public class Searcher implements IPropertyChangeListener, IndexChangeListener { + + /** @see QueryParser#setPhraseSlop(int) */ + private static final int DEFAULT_PHRASE_SLOP = 10; + /** Minimum length of query in characters */ + public static final int MIN_QUERY_LENGTH = 2; + /** Minimum number of characters to be considered a word in indexing */ + public static final int MIN_WORD_LENGTH = 1; + /** Character that identifies the current project in search query */ + public static final String CURRENT_PROJECT_CHAR = "."; + + private IndexSearcher indexSearcher; + + public static final LengthNormSimilarity SIMILARITY = new LengthNormSimilarity(); //TODO: share with WorkspaceIndexer + private static final QueryAnalyzer queryAnalyzer = new QueryAnalyzer(MIN_WORD_LENGTH); + + // Query visitors that modify the search query + private CSVExpander csvExpander = new CSVExpander(); + private WorkingSetExpander workingSetExpander = new WorkingSetExpander(); + private UppercaseNameExpander uppercaseNameExpander = new UppercaseNameExpander(); + private FieldAliasConverter fieldAliasConverter = new FieldAliasConverter(); + private ModifiedTimeConverter modifiedTimeConverter = new ModifiedTimeConverter(); + private LowercaseConverter lowercaseConverter = new LowercaseConverter(); + private FolderSearcher folderSearcher = new FolderSearcher(); + private FileNameSearcher fileNameSearcher = new FileNameSearcher(); + private CurrentProjectSetter currentProjectSetter = new CurrentProjectSetter(); + private QueryFuzzifier queryFuzzifier = new QueryFuzzifier(); + private LastTermQueryPrefixer lastTermQueryPrefixer = new LastTermQueryPrefixer(MIN_QUERY_LENGTH+1); + private FilterSetter filterSetter = new FilterSetter(); + + private boolean showMatchCounts = true; + private boolean fuzzySearchAuto = true; + + /** + * Searcher + */ + public Searcher() { + initPrefs(); + } + + protected Directory getIndexDir() throws IOException { + return FSDirectory.getDirectory(InstaSearchPlugin.getIndexDirLocation(), false); + } + + private SearchResult searchIndex(SearchQuery searchQuery) throws Exception { + + IndexSearcher indexSearcher = getIndexSearcher(); + IndexReader reader = indexSearcher.getIndexReader(); + boolean exact = searchQuery.isExact(); + + Query query = null; + + try { + query = parseSearchQuery(searchQuery, reader, exact, true); + + } catch(TooManyClauses e) { // too many, try without prefix search + query = parseSearchQuery(searchQuery, reader, exact, false); + + } catch(ParseException e) { + + // remove special query characters + String newSearchString = searchQuery.getSearchString().replaceAll("[\\(\\)\"\\[\\]'\\{\\}]", " "); + + try { + searchQuery.setSearchString(newSearchString); + query = parseSearchQuery(searchQuery, reader, exact, true); + + } catch(ParseException ignored) { + // can have error while typing query, just ignore + debug(newSearchString, " - ", ignored.getMessage()); + return null; + } + } + + SearchResult searchResut = collectSearchResults(searchQuery, indexSearcher, reader, query); + + return searchResut; + } + + private SearchResult collectSearchResults(SearchQuery searchQuery, + IndexSearcher indexSearcher, IndexReader reader, Query query) + throws IOException + { + int maxResults = reader.numDocs(); // all documents + + if( searchQuery.isLimited() ) + maxResults = searchQuery.getMaxResults(); + + Map searchTerms = extractTerms(query); + TopDocCollector collector = new TopDocCollector( maxResults ); + + if( searchQuery.isCanceled() ) + return null; + + indexSearcher.search(query, collector); // do the actual search + + if( collector.getTotalHits() == 0 ) + return null; + + ScoreDoc[] hits = collector.topDocs().scoreDocs; + ArrayList resultDocs = new ArrayList(hits.length); + + for (int i = 0; i < hits.length && !searchQuery.isCanceled(); i++) + { + int docId = hits[i].doc; + float score = hits[i].score; + + Document doc = reader.document(docId); + + SearchResultDoc resultDoc = new SearchResultDoc(getIndexDir(), doc, docId, score); + + if( showMatchCounts ) + resultDoc.computeMatchCount(reader, searchTerms.keySet()); + + resultDocs.add(resultDoc); + } + + return new SearchResult(searchQuery, resultDocs, searchTerms); + } + + /** + * Performs a search using the search query + * @param searchQuery + * + * @return SearchResult or null if nothing is found + * @throws Exception + */ + public SearchResult search(SearchQuery searchQuery) throws Exception { + + String searchString = searchQuery.getSearchString(); + + if( searchString == null || searchString.length() < MIN_QUERY_LENGTH ) + return null; + + SearchResult result = null; + + if( searchQuery.isFuzzy() ) + { + searchQuery.setExact(false); + result = searchIndex(searchQuery); // search fuzzy + } + else + { + // 1. search exact text + if( searchQuery.isExact() ) + result = searchIndex(searchQuery); + + // 2. split search text into tokens and search (non-exact) + if( (result==null || result.isEmpty()) && !searchQuery.isCanceled() ) + { + searchQuery.setExact(false); + result = searchIndex(searchQuery); + } + + // 3. search wildcarded and fuzzy matches + if( (result==null || result.isEmpty()) && fuzzySearchAuto && !searchQuery.isCanceled() ){ // if fuzzy search enabled + searchQuery.setFuzzy(true); + searchQuery.setExact(false); + + result = searchIndex(searchQuery); + } + + } + + return result; + } + + /** + * @return the indexSearcher + * @throws IOException + */ + private IndexSearcher getIndexSearcher() throws IOException + { + if( indexSearcher == null ) + { + indexSearcher = new IndexSearcher( getIndexDir(), true ); + indexSearcher.setSimilarity( SIMILARITY ); + } + + // indexSearcher.getIndexReader().isCurrent() + + return indexSearcher; + } + + /** + * Get all terms that start with prefixText + * @param prefixText + * @param prefixField + * + * @return proposed terms + * @throws IOException + */ + public List getProposals(String prefixText, Field prefixField) throws IOException + { + ArrayList proposals = new ArrayList(); + IndexReader reader = getIndexSearcher().getIndexReader(); + Term prefix = prefixField.createTerm(prefixText); + TermEnum enumerator = reader.terms(prefix); + prefixText = prefixText.toLowerCase(); + + try { + do { + Term term = enumerator.term(); + + if (term != null && + term.text().toLowerCase().startsWith(prefixText) && + term.field().equalsIgnoreCase(prefixField.toString())) { + + proposals.add(term.text()); + + } else { + break; + } + } while (enumerator.next()); + } finally { + enumerator.close(); + } + + return proposals; + } + + /** + * Get names of all projects that are in the index + * + * @return list of indexed projects + * @throws IOException + */ + public List getIndexProjects() throws IOException + { + return getProposals("", Field.PROJ); + } + + /** + * Need to reset searcher when index has been updated + * Otherwise changes won't appear in the results + * It is recommended to do a warmup search after the searcher was reset + * + */ + + public void onIndexReset() { + resetSearcher(); + } + + private void resetSearcher() + { + if( indexSearcher != null ) { + try { + indexSearcher.close(); + } catch (IOException e) { + InstaSearchPlugin.log(e); + } finally { + indexSearcher = null; + } + } + } + + /** + * Warmup search. Searches after this will be faster + * + * @throws Exception + */ + private void warmup() throws Exception { + search(new SearchQuery("", 1)); + } + + /** + * Closes and re-opens the index for searching + * Should be called after the index is updated + * + */ + public void onIndexUpdate() { + + resetSearcher(); + + try { + warmup(); + } catch (Exception e) { + InstaSearchPlugin.log(e); + } + } + + private Query parseSearchQuery(SearchQuery searchQuery, IndexReader reader, boolean exact, boolean prefix) throws ParseException, IOException + { + String searchString = searchQuery.getSearchString(); + + BooleanQuery.setMaxClauseCount(5000); // so we don't get TooManyClauses exceptions + + Query exactQuery = createExactQuery(searchQuery); + Query returnQuery; + + if( exact ) // want exact search, use KeywordAnalyzer + { + returnQuery = exactQuery; + } + else + { + Query query = parserSearchString(searchString, queryAnalyzer); + exactQuery.setBoost(query.getBoost() * 2f); // exact query more important + returnQuery = combineQueries(query, exactQuery); + } + + returnQuery = rewriteQuery(searchQuery, prefix, returnQuery); + + debug("q: ", returnQuery, " - exact ", exact); + + returnQuery = returnQuery.rewrite(reader); // lucene's rewrite (ie expand prefix queries) + + return returnQuery; + } + + /** + * @param searchQuery + * @return + * @throws ParseException + */ + private Query createExactQuery(SearchQuery searchQuery) throws ParseException + { + Query query = parserSearchString(searchQuery.getSearchString(), new KeywordAnalyzer()); + + VisitableQuery visitableQuery = new VisitableQuery(query); + + visitableQuery.accept(uppercaseNameExpander); + visitableQuery.accept(fileNameSearcher); + + query = visitableQuery.getQuery(); + + return query; + } + + private Query rewriteQuery(SearchQuery searchQuery, boolean prefix, Query query) + { + VisitableQuery visitableQuery = new VisitableQuery(query); + + visitableQuery.accept(uppercaseNameExpander); + + visitableQuery.accept(lowercaseConverter); + + if( searchQuery.isFuzzy() ) + visitableQuery.accept(queryFuzzifier); + + visitableQuery.accept(csvExpander); + visitableQuery.accept(fieldAliasConverter); + visitableQuery.accept(modifiedTimeConverter); + visitableQuery.accept(folderSearcher); + + if( prefix && !searchQuery.isFuzzy() ) // prefix last term query for substring search while typing + visitableQuery.accept(lastTermQueryPrefixer); + + if( searchQuery.getFilter() != null ) + { + filterSetter.setFilter( searchQuery.getFilter() ); + visitableQuery.accept(filterSetter); + } + + visitableQuery.accept(workingSetExpander); + + if( searchQuery.getCurrentProject() != null ) + { + currentProjectSetter.setCurrentProject(searchQuery.getCurrentProject()); + visitableQuery.accept(currentProjectSetter); + } + + return visitableQuery.getQuery(); // the modified query after all visitors + } + + private BooleanQuery combineQueries(Query query, Query exactQuery) + { + BooleanQuery topQuery = new BooleanQuery(); + topQuery.add(exactQuery, Occur.SHOULD); + topQuery.add(query, Occur.SHOULD); + return topQuery; + } + + private Query parserSearchString(String searchString, Analyzer analyzer) throws ParseException + { + QueryParser queryParser = new QueryParser(Field.CONTENTS.toString(), analyzer); + queryParser.setDefaultOperator(Operator.AND); // all fields required + queryParser.setLowercaseExpandedTerms(false); + queryParser.setPhraseSlop(DEFAULT_PHRASE_SLOP); + + /* + * Allow words in the query to begin with * + * see http://lucene.apache.org/java/2_3_1/api/org/apache/lucene/queryParser/QueryParser.html#setAllowLeadingWildcard%28boolean%29 + */ + queryParser.setAllowLeadingWildcard(true); + + return queryParser.parse(searchString); + } + + /** + * Extracts search terms and their weights + * @param query + * @return + */ + private static Map extractTerms(Query query) + { + WeightedTerm[] weightedTerms = QueryTermExtractor.getTerms(query, false, Field.CONTENTS.toString()); + + Map terms = new HashMap(weightedTerms.length); + + for(WeightedTerm weightedTerm: weightedTerms) + terms.put( weightedTerm.getTerm(), weightedTerm.getWeight() ); + + return terms; + } + + protected void initPrefs() + { + fuzzySearchAuto = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_FUZZY_SEARCH_AUTO); + showMatchCounts = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_SHOW_MATCH_COUNT); + } + + public void propertyChange(PropertyChangeEvent event) { + String prop = event.getProperty(); + + if( PreferenceConstants.P_SHOW_MATCH_COUNT.equals(prop) ) + showMatchCounts = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_SHOW_MATCH_COUNT); + else if( PreferenceConstants.P_FUZZY_SEARCH_AUTO.equals(prop) ) + fuzzySearchAuto = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_FUZZY_SEARCH_AUTO); + + } + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/StorageIndexer.java b/instasearch/src/it/unibz/instasearch/indexing/StorageIndexer.java new file mode 100755 index 0000000..a0ffc77 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/StorageIndexer.java @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.analysis.tokenattributes.OffsetAttribute; +import org.apache.lucene.analysis.tokenattributes.TermAttribute; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field.Store; +import org.apache.lucene.document.Field.TermVector; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.IndexWriter.MaxFieldLength; +import org.apache.lucene.index.Term; +import org.apache.lucene.search.Similarity; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.RAMDirectory; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; + +/** + * Indexes documents of type IStorage + */ +public class StorageIndexer +{ + /** Maximum number of terms indexed per one document */ + private static final int MAX_TERMS_PER_DOC = 200000; + /** */ + public static final String NO_VALUE = ""; + /** */ + public static final int MIN_WORD_LENGTH = 1; + protected static final FileAnalyzer fileAnalyzer = new FileAnalyzer(MIN_WORD_LENGTH); + + private IndexChangeListener changeListener = new NullIndexChangeListener(); + + private static final Similarity similarity = new LengthNormSimilarity(); + private static final int MAX_RETRY_ATTEMPTS = 10; + private Directory indexDir; + + /** + * @throws IOException + * + */ + public StorageIndexer() throws IOException + { + checkLock(); + } + + private void checkLock() throws IOException + { + Directory indexDir = getIndexDir(); + + if( IndexWriter.isLocked(indexDir) ) // should not be locked at startup, unlock + IndexWriter.unlock(indexDir); + } + + protected Directory getIndexDir() throws IOException + { + if( indexDir == null ) indexDir = new RAMDirectory(); + + return indexDir; + } + + /** + * @param create index + * @return IndexWriter + * @throws IOException + */ + public IndexWriter createIndexWriter(boolean create) throws IOException + { + IndexWriter indexWriter = new IndexWriter(getIndexDir(), fileAnalyzer, create, MaxFieldLength.UNLIMITED); + + indexWriter.setMergeFactor(2); // use less resources (although slower) + indexWriter.setSimilarity(similarity); + indexWriter.setMaxFieldLength(MAX_TERMS_PER_DOC); + + return indexWriter; + } + + /** + * @return isIndexed + * @throws IOException + */ + public boolean isIndexed() throws IOException + { + return IndexReader.indexExists(getIndexDir()); + } + + /** + * Check if the index can be read + * + * @return whether the index is readable + */ + public boolean isReadable(){ + + try { + IndexReader reader = IndexReader.open(getIndexDir(), true); + reader.close(); + + } catch (IOException readingException) { + return false; + } + + return true; + } + + /** + * Delethe the whole index + * @throws Exception + */ + public void deleteIndex() throws Exception { + + RetryingRunnable runnable = new RetryingRunnable() + { + public void run() throws Exception + { + IndexWriter w = createIndexWriter(true); // open for writing and close (make empty) + w.deleteAll(); + w.commit(); + w.close(true); + + Directory dir = getIndexDir(); + for(String file: dir.listAll()) + { + if( dir.fileExists(file) ) // still exits + { + dir.sync(file); + dir.deleteFile(file); + } + } + dir.close(); + } + + public boolean handleException(Throwable e) + { + return true; + } + }; + + changeListener.onIndexReset(); // close searcher because index is deleted + + runRetryingRunnable(runnable); // delete index with retry + } + + /** + * @throws Exception + */ + public void optimizeIndex() throws Exception { + if( ! isIndexed() ) + return; + + IndexWriter w = createIndexWriter(false); + w.optimize(); + w.close(); + + changeListener.onIndexUpdate(); + } + + /** + * @param changeListener the changeListener to set + */ + public void setIndexChangeListener(IndexChangeListener changeListener) { + this.changeListener = changeListener; + } + + /** + * @return the changeListener + */ + protected IndexChangeListener getIndexChangeListener() { + return changeListener; + } + + /** + * + * @param indexWriter + * @param storage + * @param projectName + * @param modificationStamp + * @param jar path to jar file containing this file or null + * @throws CoreException + * @throws IOException + */ + public void indexStorage(IndexWriter indexWriter, IStorage storage, String projectName, + long modificationStamp, String jar) throws CoreException, IOException + { + InputStream contents = storage.getContents(); + BufferedReader isReader = new BufferedReader(new InputStreamReader(contents)); + IPath fullPath = storage.getFullPath(); + String ext = fullPath.getFileExtension(); + if( ext == null ) ext = NO_VALUE; + + Document doc = new Document(); + + doc.add(createLuceneField(Field.CONTENTS, isReader)); + doc.add(createLuceneField(Field.FILE, fullPath.toString())); + doc.add(createLuceneField(Field.PROJ, projectName)); + doc.add(createLuceneField(Field.NAME, fullPath.lastSegment())); + doc.add(createLuceneField(Field.EXT, ext.toLowerCase())); + doc.add(createLuceneField(Field.MODIFIED, Long.toString(modificationStamp))); + doc.add(createLuceneField(Field.JAR, (jar==null)?NO_VALUE:jar)); + + indexWriter.addDocument(doc); + } + + private static void runRetryingRunnable(RetryingRunnable runnable) throws Exception + { + Throwable lastException = null; + + for(int i = 1; i <= MAX_RETRY_ATTEMPTS; i++) + { + try + { + runnable.run(); + lastException = null; + break; + } + catch(Throwable e) // exception during run occured + { + lastException = e; + + if( ! runnable.handleException(e) ) + break; + } + + try { + Thread.sleep( i*1000 ); // wait a bit longer each time for files to be freed + } catch(Exception e) { + break; + } + } + + if( lastException != null ) + { + if( lastException instanceof Exception ) + throw (Exception)lastException; + else + throw new Exception(lastException); + } + } + + /** + * Makes several attempts to index storage. + * Occasionally the index files get locked (by other processes) and are temporarily not writable. + * + * @param indexWriter + * @param storage + * @param projectName + * @param modificationStamp + * @param jar + * @throws CoreException + * @throws IOException + */ + protected void indexStorageWithRetry(final IndexWriter indexWriter, final IStorage storage, + final String projectName, final long modificationStamp, final String jar) throws Exception + { + RetryingRunnable runnable = new RetryingRunnable() + { + public void run() throws Exception + { + indexStorage(indexWriter, storage, projectName, modificationStamp, jar); + } + + public boolean handleException(Throwable e) + { + if( e instanceof OutOfMemoryError ) + { + if( indexWriter.getMaxFieldLength() > IndexWriter.DEFAULT_MAX_FIELD_LENGTH ) + indexWriter.setMaxFieldLength(IndexWriter.DEFAULT_MAX_FIELD_LENGTH); // use less memory + else + return false; + } + else if( e instanceof IOException) + { + changeListener.onIndexReset(); // close searcher + } + + return true; // keep retrying + } + }; + + runRetryingRunnable(runnable); + } + + public interface RetryingRunnable + { + public void run() throws Exception; + + /** + * If exception occurs during run() + * + * @param e + * @return true if should run again, false if stop and re-throw exception + */ + public boolean handleException(Throwable e); + } + + public void deleteStorage(IStorage storage) throws Exception + { + IndexReader reader = IndexReader.open(getIndexDir(), false); + + String filePath = storage.getFullPath().toString(); + + Term term = Field.FILE.createTerm(filePath); + reader.deleteDocuments(term); + + reader.close(); + } + + + private static org.apache.lucene.document.Field createLuceneField(Field fieldName, String value) { + return new org.apache.lucene.document.Field(fieldName.toString(), value, + Store.YES, org.apache.lucene.document.Field.Index.NOT_ANALYZED); + } + + private static org.apache.lucene.document.Field createLuceneField(Field fieldName, Reader reader) { + return new org.apache.lucene.document.Field(fieldName.toString(), + reader, TermVector.YES); + } + + /** + * Extracts terms from text + * + * @param text + * @return a map of terms to their offsets in text + * @throws IOException + */ + public static Map> extractTextTerms(String text) throws IOException { + Map> terms = new HashMap>(); + TokenStream tokenStream = fileAnalyzer.tokenStream(Field.CONTENTS.toString(), new StringReader(text)); + + TermAttribute termAtt = (TermAttribute) tokenStream.addAttribute(TermAttribute.class); + OffsetAttribute offsetAtt = (OffsetAttribute) tokenStream.addAttribute(OffsetAttribute.class); + + while(tokenStream.incrementToken()) + { + String termText = termAtt.term().toLowerCase();// t.termText().toLowerCase(); + int offset = offsetAtt.startOffset(); + + List offsets = terms.get(termText); + + if( offsets == null ) { + offsets = new LinkedList(); + terms.put(termText, offsets); + } + + offsets.add(offset); + } + tokenStream.close(); + + return terms; + } + + /** + * Listener that gets called when index has changed + */ + public interface IndexChangeListener + { + /** Index was updated with files or files were removed */ + public void onIndexUpdate(); + + /** Index was reset - created or deleted */ + public void onIndexReset(); + } + + /** Empty implementation to void null checks (Null Object pattern) */ + private static class NullIndexChangeListener implements IndexChangeListener + { + public void onIndexUpdate() {} + public void onIndexReset() {} + } + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/WorkspaceIndexer.java b/instasearch/src/it/unibz/instasearch/indexing/WorkspaceIndexer.java new file mode 100755 index 0000000..a6b3d0f --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/WorkspaceIndexer.java @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.prefs.PreferenceConstants; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; + +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.Term; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.PrefixQuery; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.TopDocs; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.FSDirectory; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.part.FileEditorInput; + +/** + * WorkspaceIndexer + * Indexes the Eclipse workspace + */ +public class WorkspaceIndexer extends StorageIndexer implements ISchedulingRule, IPropertyChangeListener { + + private IContentType TEXT_CONTENT_TYPE; + + private static final ResourceCollector resourceCollector = new ResourceCollector(); + + // Prefs + private String fileExtensions[] = getIndexableFileExtensions(); + private List excludedDirRegExes = getExcludedDirsRegExes(); + private boolean indexEmptyExtension = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_INDEX_EMPTY_EXTENSION); + + /** + * @throws Exception + */ + public WorkspaceIndexer() throws Exception + { + super(); + + if( Platform.getContentTypeManager() != null ) + TEXT_CONTENT_TYPE = Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT); + } + + @Override + protected Directory getIndexDir() throws IOException + { + return FSDirectory.open(getIndexDirLocation()); // FSDirectory.getDirectory(getIndexDirLocation(), false); + } + + /** + * @param monitor + * @throws Exception + */ + public void createIndex(IWorkspaceRoot root, IProgressMonitor monitor) throws Exception { + + getIndexChangeListener().onIndexReset(); + + deleteIndex(); + Directory indexDirectory = FSDirectory.open(getIndexDirLocation()); + + IndexWriter indexWriter = createIndexWriter(true); + + indexContainers(indexWriter, root, monitor); + + monitor.setTaskName("Optimizing Index"); + indexWriter.optimize(); + + indexWriter.close(); + indexDirectory.close(); + + getIndexChangeListener().onIndexUpdate(); + + monitor.done(); + } + + + /** + * Index all containers in the workspace + * + * @param indexWriter + * @param workspaceRoot + * @param monitor + * @throws Exception + */ + protected void indexContainers(IndexWriter indexWriter, IWorkspaceRoot workspaceRoot, IProgressMonitor monitor) throws Exception { + + resourceCollector.clear(); + resourceCollector.setExcludedDirRegExes( excludedDirRegExes ); + workspaceRoot.accept(resourceCollector); // use visitor to collect containers + + monitor.beginTask("File Indexing", resourceCollector.getContainers().size()); + + for(IContainer container: resourceCollector.getContainers()) + { + if( monitor.isCanceled() ) + break; + + monitor.setTaskName("Indexing: " + container.getProject().getName() + " - " + container.getName()); + indexContainer(indexWriter, container, monitor); + monitor.worked(1); + } + + monitor.done(); + } + + private File getIndexDirLocation() + { + File location = InstaSearchPlugin.getIndexDirLocation(); + + if( ! location.exists() ) + location.mkdirs(); + + return location; + } + + @Override + public boolean isIndexed() throws IOException + { + return IndexReader.indexExists(getIndexDir()) && super.isIndexed(); + } + + private static List getExcludedDirsRegExes() + { + String excludeDirList = InstaSearchPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.P_EXCLUDE_DIRS); + + if( excludeDirList == null || "".equals(excludeDirList) ) + return Collections.emptyList(); + + List excludeDirSet = new ArrayList(); + String[] excludedDirArr = excludeDirList.split(File.pathSeparator); + + for (String wildCardPattern : excludedDirArr) + { + Pattern pattern = null; + if( wildCardPattern.startsWith("/") ) wildCardPattern = wildCardPattern.substring(1); + + try { + pattern = wildcardToRegex(wildCardPattern); + excludeDirSet.add(pattern); + } catch(Throwable t) { + InstaSearchPlugin.debug(t); + } + } + + return excludeDirSet; + } + + private static String[] getIndexableFileExtensions() { + + String extensionList = InstaSearchPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.P_INDEXABLE_EXTENSIONS); + if( extensionList == null || "".equals(extensionList) || "*".equals(extensionList) ) return null; + + extensionList = extensionList.replace(" ", ""); + + String[] extensions = extensionList.split("[,|;:]"); + if( extensions.length == 0 ) return null; + + for(int i = 0; i= 0 ) + return true; + + return false; + } + + private void indexFile(IndexWriter indexWriter, IFile file) throws Exception { + + if( ! file.isAccessible() ) + return; + + if( file.isDerived(IResource.CHECK_ANCESTORS) ) + return; + + if( ! file.isSynchronized(IResource.DEPTH_ZERO) ) + return; + + if( file.getRawLocation() == null ) // unknown location + return; + + File f = file.getRawLocation().toFile(); + if( f == null || ! f.canRead() ) + return; + + indexStorageWithRetry(indexWriter, file, file.getProject().getName(), file.getLocalTimeStamp(), null); + } + + /** + * @param file + * @throws Exception + */ + public void updateFile(IFile file) throws Exception { + + if( !isIndexed() ) + return; + + deleteStorage(file); + + if( !isIndexable(file) ) + return; + + if( file.isAccessible() && !file.isDerived(IResource.CHECK_ANCESTORS) ) + { + IndexWriter w = createIndexWriter(false); + indexFile(w, file); + w.close(); + } + + } + + /** + * Deletes and re-indexes files in a folder + * + * @param folder + * @param monitor + * @throws Exception + */ + public void updateFolder(IFolder folder, IProgressMonitor monitor) throws Exception { + + if( !isIndexed() ) + return; + + IndexReader reader = IndexReader.open(getIndexDir(), false); + deleteFolder(reader, folder); + reader.close(); + + if( !folder.isAccessible() ) + return; + + resourceCollector.clear(); + resourceCollector.setExcludedDirRegExes(excludedDirRegExes); + folder.accept(resourceCollector); // get also subfolders + + IndexWriter w = createIndexWriter(false); + + for(IContainer container: resourceCollector.getContainers()) + { + if( isExcluded(container) ) continue; + indexContainer(w, container, monitor); + } + + w.close(); + } + + /** + * @param container + * @return + */ + private boolean isExcluded(IContainer container) { + + if( container == null || excludedDirRegExes == null || excludedDirRegExes.isEmpty() ) + return false; + + return ResourceCollector.isResourceExcluded(container, excludedDirRegExes) + || isExcluded(container.getParent()); + } + + /** + * @param project + * @param monitor + * @throws Exception + */ + public void updateProject(IProject project, IProgressMonitor monitor) throws Exception { + + if( !isIndexed() ) + return; + + deleteProject(project); + + if( project.exists() && project.isAccessible() && project.isOpen() ) { + IndexWriter w = createIndexWriter(false); + + resourceCollector.clear(); + resourceCollector.setExcludedDirRegExes(excludedDirRegExes); + project.accept(resourceCollector); + + for(IContainer container: resourceCollector.getContainers()) + { + indexContainer(w, container, monitor); + } + + w.close(); + } + + } + + /** + * @param w + * @param container + * @param monitor + * @throws Exception + */ + private void indexContainer(IndexWriter w, IContainer container, IProgressMonitor monitor) throws Exception + { + if( !container.isAccessible() || container.isDerived(IResource.CHECK_ANCESTORS) ) + return; + + IResource[] members = container.members(false); + + for(IResource member: members) { + + if( monitor.isCanceled() ) + return; + + if( member.getType() != IResource.FILE || !member.isAccessible() || member.isDerived() ) + continue; + + IFile file = (IFile) member; + + if( isIndexable(file) ) + indexFile(w, file); + } + } + + /** + * @param file + * @return + * @throws CoreException + */ + private boolean isTextFile(IFile file) throws CoreException { + + if( !file.isSynchronized(IResource.DEPTH_ZERO) ) + return false; + + IContentType contentType = IDE.getContentType(file); + if( contentType == null ) contentType = IDE.guessContentType(file); + if( contentType == null ) return false; + + if( TEXT_CONTENT_TYPE != null && contentType.isKindOf(TEXT_CONTENT_TYPE) ) + return true; + + return false; + } + + /** + * @throws IOException + * + */ + private void deleteFolder(IndexReader reader, IContainer container) throws Exception { + + IndexSearcher searcher = new IndexSearcher(reader); + String path = container.getFullPath().addTrailingSeparator().toString(); + TopDocs topDocs = searcher.search(new PrefixQuery(Field.FILE.createTerm(path)), reader.numDocs()); + + for(ScoreDoc doc: topDocs.scoreDocs) + { + int docNum = doc.doc; + reader.deleteDocument(docNum); + } + + searcher.close(); + } + + /** + * @param project + * @return deletedCount + * @throws Exception + */ + public int deleteProject(IProject project) throws Exception { + IndexReader reader = IndexReader.open(getIndexDir(), false); + String filePath = project.getFullPath().toString(); + + Term term = Field.PROJ.createTerm(filePath); + int deletedCount = reader.deleteDocuments(term); + + reader.close(); + + return deletedCount; + } + + public boolean isConflicting(ISchedulingRule rule) + { + return rule == this; // prevent concurrent writing of the index from jobs + } + + public boolean contains(ISchedulingRule rule) + { + return rule == this; + } + + /** + * @param doc + * @return IEditorInput + * @throws Exception + * @throws IOException + */ + public IEditorInput getEditorInput(SearchResultDoc doc) throws Exception { + + return new FileEditorInput(doc.getFile()); + } + + /** + * @param doc + * @return IStorage + * @throws Exception + * @throws IOException + */ + public IStorage getStorage(SearchResultDoc doc) throws Exception { + return doc.getFile(); + } + + public void propertyChange(PropertyChangeEvent event) { + String prop = event.getProperty(); + + if( PreferenceConstants.P_INDEXABLE_EXTENSIONS.equals(prop) ) + fileExtensions = getIndexableFileExtensions(); + else if( PreferenceConstants.P_EXCLUDE_DIRS.equals(prop) ) + excludedDirRegExes = getExcludedDirsRegExes(); + else if( PreferenceConstants.P_INDEX_EMPTY_EXTENSION.equals(prop) ) + indexEmptyExtension = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_INDEX_EMPTY_EXTENSION); + + } + + /** + * Convert path matching wildcard pattern to regular expression. + * + * + * @param pathWildcardPattern + * @return regex pattern + */ + public static Pattern wildcardToRegex(String pathWildcardPattern) + { + String regex = pathWildcardPattern; + + regex = regex.replaceAll("\\*\\*", ""); // escape initially + regex = regex.replaceAll("\\.", "\\."); // escape . + regex = regex.replaceAll("\\*", "[^/]*"); + regex = regex.replaceAll("\\?", "."); + regex = regex.replaceAll("", ".*"); + + Pattern pattern = Pattern.compile(regex); + + return pattern; + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/WorkspaceIndexerJDT.java b/instasearch/src/it/unibz/instasearch/indexing/WorkspaceIndexerJDT.java new file mode 100755 index 0000000..7c38710 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/WorkspaceIndexerJDT.java @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.prefs.PreferenceConstants; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.LinkedList; +import java.util.List; +import java.util.TreeSet; + +import org.apache.lucene.index.IndexWriter; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.core.IClassFile; +import org.eclipse.jdt.core.IJarEntryResource; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaModel; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; +import org.eclipse.ui.IEditorInput; + +/** + * Workspace indexer which also indexes JAR source attachments + */ + + +@SuppressWarnings("restriction") +public class WorkspaceIndexerJDT extends WorkspaceIndexer { + + /** + * @throws Exception + * @throws IOException + */ + public WorkspaceIndexerJDT() throws Exception { + super(); + + if( JavaCore.getJavaCore() == null ) // check that we have JDT. throws exception if we don't have JavaCore + throw new RuntimeException("JDT not detected"); + } + + @Override + protected void indexContainers(IndexWriter indexWriter, IWorkspaceRoot workspaceRoot, IProgressMonitor monitor) throws Exception { + + super.indexContainers(indexWriter, workspaceRoot, monitor); + + boolean indexArchives = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_INDEX_ARCHIVES); + if( ! indexArchives ) + return; + + try { + IJavaModel javaModel = JavaCore.create(workspaceRoot); + + List jars = getJars(javaModel); + + monitor.beginTask("Indexing JAR Source Attachements (" + jars.size() + ")", jars.size()); + + for(IPackageFragmentRoot jar: jars) { + monitor.worked(1); + + indexClassFiles(indexWriter, jar, monitor); + indexNonJavaResources(indexWriter, jar, monitor); + + if( monitor.isCanceled() ) + break; + } + } catch(Exception e) { + InstaSearchPlugin.log(e); + } + + if( monitor.isCanceled() ) { + // if user canceled, disable jar indexing in preferences. next time don't index + InstaSearchPlugin.setBoolPref(PreferenceConstants.P_INDEX_ARCHIVES, false); + } + + monitor.done(); + } + + /** + * Index non .class files + * + * @param indexWriter + * @param jar + * @param monitor + * @throws CoreException + * @throws IOException + */ + private void indexNonJavaResources(IndexWriter indexWriter, IPackageFragmentRoot jar, IProgressMonitor monitor) throws Exception { + + Object[] resources = jar.getNonJavaResources(); + + if( resources == null || resources.length == 0 ) + return; + + IJarEntryResource[] jarEntries = new IJarEntryResource[resources.length]; + System.arraycopy(resources, 0, jarEntries, 0, resources.length); + + indexNonJavaResources(indexWriter, jar, jarEntries, monitor); + } + + /** + * @param indexWriter + * @param jar + * @param resources + * @param monitor + * @throws IOException + * @throws CoreException + */ + private void indexNonJavaResources(IndexWriter indexWriter, IPackageFragmentRoot jar, IJarEntryResource[] resources, IProgressMonitor monitor) throws Exception { + + String jarName = getJarName(jar); + String projectPath = getProjectPath(jar); + + for(IJarEntryResource resource: resources) + { + if( monitor.isCanceled() ) + return; + + if( resource.isFile() ) + { + if( isIndexable(resource) ) + indexStorageWithRetry(indexWriter, resource, projectPath, IResource.NULL_STAMP, jarName); + } + else + { + indexNonJavaResources(indexWriter, jar, resource.getChildren(), monitor); + } + } + + } + + /** + * @param jarRes + * @return + */ + private boolean isIndexable(IJarEntryResource jarRes) { + String ext = jarRes.getFullPath().getFileExtension(); + + return isIndexableExtension(ext); + } + + /** + * @param jar + * @return + */ + private String getProjectPath(IPackageFragmentRoot jar) { + return jar.getJavaProject().getElementName() + "/" + getJarName(jar); + } + + /** + * @param jar + * @return + */ + private String getJarName(IPackageFragmentRoot jar) { + return jar.getElementName(); + } + + private void indexClassFiles(IndexWriter indexWriter, IPackageFragmentRoot jar, IProgressMonitor monitor) throws Exception { + + String jarName = getJarName(jar); + String projectPath = getProjectPath(jar); + + for(IJavaElement pkgRootChild: jar.getChildren()) { + + IPackageFragment pkg = (IPackageFragment) pkgRootChild; + monitor.setTaskName("Indexing JAR Source Attachements: " + jar.getElementName() + " - " + pkg.getElementName()); + + for(IClassFile classFile: pkg.getClassFiles()) { + if( classFile.getElementName().contains("$") ) continue; // not type root + + ClassFileSourceStorage classFileSourceStorage = new ClassFileSourceStorage(classFile); + + if( classFileSourceStorage.hasSource() ) + indexStorageWithRetry(indexWriter, classFileSourceStorage, projectPath, IResource.NULL_STAMP, jarName); + + if( monitor.isCanceled() ) return; + } + + } + + } + + private List getJars(IJavaModel javaModel) throws JavaModelException { + + IJavaProject[] projects = javaModel.getJavaProjects(); + TreeSet jarNames = new TreeSet(); + LinkedList jars = new LinkedList(); + + for(IJavaProject javaProj: projects) { + + IPackageFragmentRoot[] roots = javaProj.getPackageFragmentRoots(); + + for(IPackageFragmentRoot root: roots) { + if( root.isArchive() && root.getSourceAttachmentPath() != null ) { + + String name = root.getElementName(); + + if( !jarNames.contains(name) ) { + jarNames.add(name); + jars.add(root); + } + } + } + } + + return jars; + } + + @Override + public IEditorInput getEditorInput(SearchResultDoc doc) throws Exception { + + if( ! doc.isInJar() ) + return super.getEditorInput(doc); + + if( "class".equals(doc.getFileExtension()) ) { + IClassFile classFile = getClassFile(doc); + + if( classFile == null ) + return null; + + return EditorUtility.getEditorInput(classFile); + } + + IStorage storage = getNonJavaResource(doc); + + if( storage == null ) + return null; + + return EditorUtility.getEditorInput(storage); + } + + @Override + public IStorage getStorage(SearchResultDoc doc) throws Exception { + if( !doc.isInJar() ) + return super.getStorage(doc); // return file + + if( "class".equals(doc.getFileExtension())) { + IClassFile classFile = getClassFile(doc); + + if( classFile == null ) + return null; + + ClassFileSourceStorage storage = new ClassFileSourceStorage(classFile); + + return storage; + } + + return getNonJavaResource(doc); + } + + /** + * @param doc + * @return + * @throws JavaModelException + */ + private IStorage getNonJavaResource(SearchResultDoc doc) throws JavaModelException { + + IWorkspaceRoot workspaceRoot = InstaSearchPlugin.getWorkspaceRoot(); + IJavaModel javaModel = JavaCore.create(workspaceRoot); + + String javaProjectName = doc.getProject().segment(0); + IJavaProject javaProj = javaModel.getJavaProject(javaProjectName); + + if( !javaProj.isOpen() ) + javaProj.open(new NullProgressMonitor()); + + javaModel.refreshExternalArchives(new IJavaElement[]{javaProj}, new NullProgressMonitor()); + + String jarName = doc.getJarName(); + + IPackageFragmentRoot[] roots = javaProj.getPackageFragmentRoots(); + IPackageFragmentRoot jar = null; + + for(IPackageFragmentRoot root: roots) { + if( root.isArchive() && root.getSourceAttachmentPath() != null ) { + + String name = root.getElementName(); + if( name.equals(jarName)) { + jar = root; + break; + } + } + } + + if( jar == null ) + return null; + + String filePath = doc.getFilePath(); + IPath path = new Path(filePath); + + IJarEntryResource res = null; + for(String segment: path.segments()) + { + if( res == null ) + res = findJarEntry(jar, segment); + else + res = findJarEntry(res.getChildren(), segment); + } + + return res; + } + + /** + * @param jar + * @param filePath + * @return + * @throws JavaModelException + */ + private IJarEntryResource findJarEntry(IPackageFragmentRoot jar, String filePath) throws JavaModelException { + + Object[] resources = jar.getNonJavaResources(); + + if( resources == null || resources.length == 0 ) + return null; + + IJarEntryResource[] jarEntries = new IJarEntryResource[resources.length]; + System.arraycopy(resources, 0, jarEntries, 0, resources.length); + + return findJarEntry(jarEntries, filePath); + } + + /** + * @param jarEntries + * @param filePath + * @return + */ + private IJarEntryResource findJarEntry(IJarEntryResource[] jarEntries, + String filePath) { + + for(IJarEntryResource entry: jarEntries) + { + if( filePath.equals(entry.getName()) ) + return entry; + } + + return null; + } + + /** + * @param doc + * @return + * @throws JavaModelException + */ + private IClassFile getClassFile(SearchResultDoc doc) throws Exception { + + IWorkspaceRoot workspaceRoot = InstaSearchPlugin.getWorkspaceRoot(); + IJavaModel javaModel = JavaCore.create(workspaceRoot); + + String javaProjectName = doc.getProject().segment(0); + IJavaProject proj = javaModel.getJavaProject(javaProjectName); + + if( proj == null ) + throw new Exception("Project " + javaProjectName + " not found"); + + if( !proj.isOpen() ) + proj.open(new NullProgressMonitor()); + + javaModel.refreshExternalArchives(new IJavaElement[]{proj}, new NullProgressMonitor()); + + IPath filePath = new Path(doc.getFilePath()); + String fileName = filePath.lastSegment(); + + IPath jarPath = filePath.removeLastSegments(2); // remove pkg and filename + IPackageFragmentRoot jar = null; + IResource jarFile = workspaceRoot.findMember(jarPath); + + if( jarFile != null ) + jar = proj.getPackageFragmentRoot(jarFile); + else + jar = proj.getPackageFragmentRoot(jarPath.toString()); // external archive + + if( jar == null ) + throw new Exception("Jar " + jarPath + " not found in project " + doc.getProjectName()); + + IPath pkgPath = filePath.removeLastSegments(1); // remove filename + String pkgName = pkgPath.lastSegment(); + + IPackageFragment pkg = jar.getPackageFragment(pkgName); + + if( pkg == null ) + throw new Exception("Package " + pkgName + " not found in " + doc.getProjectName()); + + IClassFile classFile = pkg.getClassFile(fileName); + + return classFile; + } + + /** + * Stores the attached source of a .class file + */ + private class ClassFileSourceStorage implements IStorage { + + private IClassFile classFile; + private String source; + + /** + * @param classFileWithSource + * @throws JavaModelException + * + */ + public ClassFileSourceStorage(IClassFile classFileWithSource) throws JavaModelException { + this.classFile = classFileWithSource; + this.source = classFile.getSource(); + } + + public InputStream getContents() throws CoreException { + if( !hasSource() ) return null; + + return new ByteArrayInputStream(source.getBytes()); + } + + public boolean hasSource() { + return source != null; + } + + /** + * // + */ + public IPath getFullPath() { + IPackageFragment pkg = (IPackageFragment)classFile.getParent(); + + IPackageFragmentRoot jar = (IPackageFragmentRoot)pkg.getParent(); + + String pkgName = pkg.getElementName(); + IPath jarPath = jar.getPath(); + + IPath filePath = jarPath.append(pkgName).append(getName()); + + return filePath; + } + + public String getName() { + return classFile.getElementName(); // ClassName.class + } + + public boolean isReadOnly() { + return true; + } + + @SuppressWarnings("rawtypes") + public Object getAdapter(Class adapter) { + return classFile.getAdapter(adapter); + } + + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/CSVExpander.java b/instasearch/src/it/unibz/instasearch/indexing/querying/CSVExpander.java new file mode 100755 index 0000000..18e95cd --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/CSVExpander.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; + +/** + * Expands a list of comma separated values (CSV) into a boolean query. eg. + * ext:xml,java,txt becomes (ext:xml OR ext:java OR ext:txt) + */ +public class CSVExpander extends QueryVisitor { + + @Override + public Query visit(TermQuery termQuery, Field field) { + + Term term = termQuery.getTerm(); + + if( field != Field.CONTENTS && term.text().contains(",") ) { + BooleanQuery bq = new BooleanQuery(); + + String vals[] = term.text().split(","); + + if( vals.length == 0 ) return termQuery; + + for(String val: vals) { + if( "".equals(val) ) continue; + TermQuery tq = new TermQuery(field.createTerm(val)); + bq.add(tq, Occur.SHOULD); + } + + return bq; + } + + return super.visit(termQuery, field); + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/CurrentProjectSetter.java b/instasearch/src/it/unibz/instasearch/indexing/querying/CurrentProjectSetter.java new file mode 100755 index 0000000..abd650d --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/CurrentProjectSetter.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; +import it.unibz.instasearch.indexing.Searcher; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; + +/** + * Replaces '.' with the name of the active project (as a shortcut) + */ +public class CurrentProjectSetter extends QueryVisitor { + + private String currentProject; + + public CurrentProjectSetter() { + } + + public CurrentProjectSetter(String currentProject) { + this.currentProject = currentProject; + } + + /** + * @param currentProject the current Project to set + */ + public void setCurrentProject(String currentProject) { + this.currentProject = currentProject; + } + + @Override + public Query visit(TermQuery termQuery, Field field) { + + Term term = termQuery.getTerm(); + + if( Searcher.CURRENT_PROJECT_CHAR.equals(term.text()) ) { + if( field == Field.PROJ || field == Field.CONTENTS ) { + return new TermQuery(Field.PROJ.createTerm(currentProject)); + } + } + + return super.visit(termQuery, field); + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/FieldAliasConverter.java b/instasearch/src/it/unibz/instasearch/indexing/querying/FieldAliasConverter.java new file mode 100755 index 0000000..b7da36c --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/FieldAliasConverter.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import java.util.HashMap; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.PrefixQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.WildcardQuery; + +/** + * Converts field aliases to actual field names + */ +public class FieldAliasConverter extends QueryVisitor { + + private static HashMap aliases = new HashMap(); + + static { + aliases.put("project", Field.PROJ); + aliases.put("filetype", Field.EXT); + aliases.put("type", Field.EXT); + aliases.put("workingset", Field.WS); + aliases.put("age", Field.MODIFIED); + aliases.put("folder", Field.DIR); + } + + /** + * + */ + public FieldAliasConverter() { + } + + @Override + public Query visit(TermQuery termQuery, Field termField) { + + Term t = termQuery.getTerm(); + + if( termField == null && aliases.containsKey(t.field()) ) { + Field field = aliases.get(t.field()); + Term newTerm = field.createTerm(t.text()); + TermQuery newTermQuery = new TermQuery(newTerm); + return newTermQuery; + } + + return super.visit(termQuery, termField); + } + + @Override + public Query visit(PrefixQuery prefixQuery, Field termField) { + + Term t = prefixQuery.getPrefix(); + + if( termField == null && aliases.containsKey(t.field()) ) { + Field field = aliases.get(t.field()); + Term newTerm = field.createTerm(t.text()); + PrefixQuery newTermQuery = new PrefixQuery(newTerm); + return newTermQuery; + } + + return super.visit(prefixQuery, termField); + } + + @Override + public Query visit(WildcardQuery wildcardQuery, Field termField) { + + Term t = wildcardQuery.getTerm(); + + if( termField == null && aliases.containsKey(t.field()) ) { + Field field = aliases.get(t.field()); + Term newTerm = field.createTerm(t.text()); + WildcardQuery newTermQuery = new WildcardQuery(newTerm); + return newTermQuery; + } + + return super.visit(wildcardQuery, termField); + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/FileNameSearcher.java b/instasearch/src/it/unibz/instasearch/indexing/querying/FileNameSearcher.java new file mode 100755 index 0000000..b0826e6 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/FileNameSearcher.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; + +/** + * Searches in the "name" field as well as in contents field if the query is a term query + */ +public class FileNameSearcher extends QueryVisitor { + + private Query originalQuery; + + @Override + public void init(Query query) { + originalQuery = query; + } + + @Override + public Query visit(TermQuery termQuery, Field field) { + + if( field == Field.CONTENTS && termQuery == originalQuery ) // if our query is a term query + { + Term term = termQuery.getTerm(); + Term nameTerm = Field.NAME.createTerm(term.text()); + TermQuery nameQuery = new TermQuery(nameTerm); + nameQuery.setBoost( termQuery.getBoost() * 2f ); + + BooleanQuery boolQuery = new BooleanQuery(); + boolQuery.add(nameQuery, Occur.SHOULD); + boolQuery.add(termQuery, Occur.SHOULD); + + return boolQuery; + } + + return termQuery; + } + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/FilterSetter.java b/instasearch/src/it/unibz/instasearch/indexing/querying/FilterSetter.java new file mode 100755 index 0000000..7ab8fe4 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/FilterSetter.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import java.util.Map; +import java.util.Set; + +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.PrefixQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.WildcardQuery; + +/** + * + */ +public class FilterSetter extends QueryVisitor { + + private Map> filter; + + public FilterSetter() { + } + + @Override + public Query visit(TermQuery termQuery, Field field) { + return addFilters(termQuery, field); + } + + @Override + public Query visit(PrefixQuery originalQuery, Field field) { + return addFilters(originalQuery, field); + } + + @Override + public Query visit(WildcardQuery wildcardQuery, Field field) { + return addFilters(wildcardQuery, field); + } + + private Query getFilterQuery(Query originalQuery, Field field, Set values) + { + BooleanQuery boolQuery = new BooleanQuery(); + + if( originalQuery != null ) + { + boolQuery.add(originalQuery, Occur.SHOULD); // original term + boolQuery.setBoost( originalQuery.getBoost() ); + } + + for(String value: values) + boolQuery.add(new TermQuery(field.createTerm(value)), Occur.SHOULD); + + return boolQuery; + } + + private Query addFilters(Query originalQuery, Field field) + { + Set values = filter.get(field); + if( values != null ) + { + filter.remove(field); + return getFilterQuery(originalQuery, field, values); + } + return originalQuery; + } + + @Override + public Query endVisit(Query query) + { + if( filter.isEmpty() ) + return super.endVisit(query); + + // combine filters with main query using AND + BooleanQuery conjQuery = new BooleanQuery(); + conjQuery.add(query, Occur.MUST); + + for(Field field: filter.keySet()) + { + Set values = filter.get(field); // possible values + + if( values.size() == 1 ) + { + String value = values.iterator().next(); + conjQuery.add( new TermQuery(field.createTerm(value)), Occur.MUST); + } + else // several values, any of them should match (using OR here) + { + conjQuery.add( getFilterQuery(null, field, values), Occur.MUST); + } + } + + return conjQuery; + } + + /** + * @param filter + */ + public void setFilter(Map> filter) { + this.filter = filter; + } + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/FolderSearcher.java b/instasearch/src/it/unibz/instasearch/indexing/querying/FolderSearcher.java new file mode 100755 index 0000000..cd85fe5 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/FolderSearcher.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.PrefixQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.WildcardQuery; + +/** + * + */ +public class FolderSearcher extends QueryVisitor { + + @Override + public Query visit(TermQuery termQuery, Field field) { + + Term t = termQuery.getTerm(); + + if( field == Field.DIR ) + { + if( t.text().startsWith("/") ) // already absolute + { + Term fileTerm = Field.FILE.createTerm(t.text()); + return new PrefixQuery(fileTerm); + } + + Term fileTerm = Field.FILE.createTerm("/*/" + t.text() + "/*"); + + return new WildcardQuery(fileTerm); + } + + return super.visit(termQuery, field); + } + + @Override + public Query visit(PrefixQuery prefixQuery, Field field) { + Term t = prefixQuery.getPrefix(); + + if( field == Field.DIR ) + { + String text = t.text(); + + if( text.startsWith("/") ) // already absolute + { + Term fileTerm = Field.FILE.createTerm(text); + return new PrefixQuery(fileTerm); //change field + } + + Term fileTerm = Field.FILE.createTerm("/*/" + text + "*/*"); // meant to end with * already + + return new WildcardQuery(fileTerm); + } + + return super.visit(prefixQuery, field); + } + + @Override + public Query visit(WildcardQuery wildcardQuery, Field field) { + + Term t = wildcardQuery.getTerm(); + + if( field == Field.DIR ) + { + String text = t.text(); + + if( text.startsWith("/") ) // already absolute + { + Term fileTerm = Field.FILE.createTerm(text); + return new WildcardQuery(fileTerm); //change field + } + + Term fileTerm = Field.FILE.createTerm("/*/" + t.text()); + + return new WildcardQuery(fileTerm); + } + + return super.visit(wildcardQuery, field); + } + + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/LastTermQueryPrefixer.java b/instasearch/src/it/unibz/instasearch/indexing/querying/LastTermQueryPrefixer.java new file mode 100755 index 0000000..632d73a --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/LastTermQueryPrefixer.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.PrefixQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; + +/** + * Replaces last TermQuery by (TermQuery OR PrefixQuery) in the query + */ +public class LastTermQueryPrefixer extends QueryVisitor { + + private int clauseCount; + private int minTermLength; + + public LastTermQueryPrefixer(int minTermLength) { + clauseCount = 0; + this.minTermLength = minTermLength; + } + + @Override + public Query visit(TermQuery termQuery, Field field) { + + if( clauseCount == 0 ) { // at last query + Term term = termQuery.getTerm(); + + if( term.text().length() < minTermLength ) // exclude short queries to avoid clause overload + return termQuery; + + PrefixQuery prefixQuery = new PrefixQuery(term); + prefixQuery.setBoost( termQuery.getBoost()/4f ); + + BooleanQuery boolQuery = new BooleanQuery(); + boolQuery.add(termQuery, Occur.SHOULD); + boolQuery.add(prefixQuery, Occur.SHOULD); + boolQuery.setBoost( termQuery.getBoost() ); + + return boolQuery; + } + return termQuery; + } + + @Override + public BooleanQuery visit(BooleanQuery boolQuery) { + clauseCount += boolQuery.getClauses().length; + return super.visit(boolQuery); + } + + @Override + public boolean visit(BooleanClause boolClause) { + clauseCount--; + + if(boolClause.getOccur() == Occur.MUST_NOT) // skip prohibited + return false; + + return true; + } + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/LowercaseConverter.java b/instasearch/src/it/unibz/instasearch/indexing/querying/LowercaseConverter.java new file mode 100755 index 0000000..2e415f9 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/LowercaseConverter.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.PhraseQuery; +import org.apache.lucene.search.PrefixQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.WildcardQuery; + +/** + * + */ +public class LowercaseConverter extends QueryVisitor { + + + @Override + public void init(Query query) { + } + + @Override + public Query visit(TermQuery termQuery, Field field) { + + if( field == Field.CONTENTS ) + { + Term term = termQuery.getTerm(); + return new TermQuery(field.createTerm( term.text().toLowerCase() )); + } + + return termQuery; + } + + @Override + public Query visit(PrefixQuery prefixQuery, Field field) { + + if( field == Field.CONTENTS ) + { + Term term = prefixQuery.getPrefix(); + return new PrefixQuery( field.createTerm( term.text().toLowerCase() ) ); + } + + return super.visit(prefixQuery, field); + } + + @Override + public Query visit(WildcardQuery wildcardQuery, Field field) { + if( field == Field.CONTENTS ) + { + Term term = wildcardQuery.getTerm(); + return new WildcardQuery( field.createTerm( term.text().toLowerCase() ) ); + } + return super.visit(wildcardQuery, field); + } + + @Override + public Query visit(PhraseQuery phraseQuery) + { + PhraseQuery newQuery = new PhraseQuery(); + + for(Term term: phraseQuery.getTerms()) + { + Field field = Field.getByName( term.field() ); + if( field != Field.CONTENTS ) + return phraseQuery; + + Term newTerm = Field.CONTENTS.createTerm( term.text().toLowerCase() ); + newQuery.add( newTerm ); + } + + newQuery.setSlop(phraseQuery.getSlop()); + newQuery.setBoost( phraseQuery.getBoost() ); + + return newQuery; + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/ModifiedTimeConverter.java b/instasearch/src/it/unibz/instasearch/indexing/querying/ModifiedTimeConverter.java new file mode 100755 index 0000000..a198991 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/ModifiedTimeConverter.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang.math.NumberUtils; +import org.apache.lucene.index.Term; +import org.apache.lucene.search.NumericRangeQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; + +/** + * Replaces named modified field values with millisecond range queries + */ +public class ModifiedTimeConverter extends QueryVisitor { + + private static ArrayList intervalNames = new ArrayList(); + private static Calendar cal = Calendar.getInstance(); + + static { + for(Interval interval: Interval.values()) + intervalNames.add(interval.toString().toLowerCase()); + + intervalNames.add("3 days"); // as an example, any number can be specified + } + + private enum Interval + { + TODAY, + YESTERDAY, + HOUR(TimeUnit.HOURS.toMillis(1)), + DAY(TimeUnit.DAYS.toMillis(1)), + WEEK(TimeUnit.DAYS.toMillis(7)), + MONTH(TimeUnit.DAYS.toMillis(30)) + ; + + private long millis; + + Interval() { }; + + Interval(long millis) + { + this.millis = millis; + } + } + + public static List getDurationNames() + { + return intervalNames; + } + + /** + * + */ + public ModifiedTimeConverter() { + } + + @Override + public Query visit(TermQuery termQuery, Field termField) { + + if( termField != Field.MODIFIED ) + return super.visit(termQuery, termField); + + Term t = termQuery.getTerm(); + String intervalName = t.text(); + int multiplier = 1; + + if( intervalName.matches("^[0-9]+.*$") ) // e.g. "3 days" + { + String multiplierString = intervalName.replaceAll("[^0-9]+", ""); // remove non-digits + multiplier = NumberUtils.toInt(multiplierString.trim(), 1); + + intervalName = intervalName.replaceAll("[0-9 ]+", "").trim(); // remove digits + } + + if( intervalName.endsWith("s") ) + intervalName = intervalName.substring(0, intervalName.length() - 1 ); + + Interval interval = getIntervalByName(intervalName); + + if( interval == null ) + return super.visit(termQuery, termField); + + long start = 0, end = System.currentTimeMillis(); + cal.setTimeInMillis(end); + + switch(interval) + { + case TODAY: + cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE), 0, 0, 0); + start = cal.getTimeInMillis(); + break; + case YESTERDAY: + cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE), 0, 0, 0); + end = cal.getTimeInMillis(); + cal.add(Calendar.DATE, -1); + start = cal.getTimeInMillis(); + break; + default: + start = end - multiplier * interval.millis; + } + + String field = Field.MODIFIED.name().toLowerCase(); + NumericRangeQuery rangeQuery = NumericRangeQuery.newLongRange(field, start, end, true, true); + + return rangeQuery; + } + + private static Interval getIntervalByName(String intervalName) + { + try { + return Interval.valueOf(intervalName.toUpperCase()); + } + catch(Throwable ignored) + { + return null; + } + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/PhraseSearcher.java b/instasearch/src/it/unibz/instasearch/indexing/querying/PhraseSearcher.java new file mode 100755 index 0000000..0ccbdbd --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/PhraseSearcher.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.PhraseQuery; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.BooleanClause.Occur; + +/** + * Converts a boolean query into a phrase query + */ +public class PhraseSearcher extends QueryVisitor +{ + /** + * + */ + private static final int DEFAULT_SLOP = 10; + + @Override + public BooleanQuery visit(BooleanQuery boolQuery) + { + PhraseQuery phraseQuery = new PhraseQuery(); + + for(BooleanClause clause: boolQuery.getClauses()) + { + if( clause.isProhibited() || !clause.isRequired() || !(clause.getQuery() instanceof TermQuery) ) + return super.visit(boolQuery); // only consider required terms + + TermQuery tq = (TermQuery) clause.getQuery(); + + Field field = Field.getByName( tq.getTerm().field() ); + if( field != Field.CONTENTS ) + continue; + + phraseQuery.add(tq.getTerm()); + } + + phraseQuery.setSlop(DEFAULT_SLOP); + + BooleanQuery bq = new BooleanQuery(); + bq.add(phraseQuery, Occur.SHOULD); + bq.add(boolQuery, Occur.SHOULD); + bq.setBoost(boolQuery.getBoost()); + + phraseQuery.setBoost(boolQuery.getBoost()); + boolQuery.setBoost( phraseQuery.getBoost()*0.5f ); + + return bq; + } + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/QueryFuzzifier.java b/instasearch/src/it/unibz/instasearch/indexing/querying/QueryFuzzifier.java new file mode 100755 index 0000000..0b52243 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/QueryFuzzifier.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.FuzzyQuery; +import org.apache.lucene.search.PhraseQuery; +import org.apache.lucene.search.PrefixQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.WildcardQuery; + +/** + * Makes the query fuzzy. + * Replaces each TermQuery by Query of the form: term* OR *term* OR term~ + */ +public class QueryFuzzifier extends QueryVisitor { + + @Override + public Query visit(TermQuery termQuery, Field field) { + + if( field != Field.CONTENTS ) + return termQuery; + + // turn term query into: (term* OR *term* OR term~) + + Term term = termQuery.getTerm(); + + PrefixQuery prefixQuery = new PrefixQuery(term); + prefixQuery.setBoost( termQuery.getBoost() ); + + Term wildcardTerm = Field.CONTENTS.createTerm("*" + term.text() + "*"); + WildcardQuery wildcardQuery = new WildcardQuery(wildcardTerm); + wildcardQuery.setBoost( termQuery.getBoost() * 0.75f ); + + FuzzyQuery fuzzyQuery = new FuzzyQuery( term ); + fuzzyQuery.setBoost( termQuery.getBoost() * 0.5f ); + + BooleanQuery boolQuery = new BooleanQuery(); + boolQuery.add(prefixQuery, Occur.SHOULD); + boolQuery.add(wildcardQuery, Occur.SHOULD); + boolQuery.add(fuzzyQuery, Occur.SHOULD); + boolQuery.setBoost( termQuery.getBoost() ); + + return boolQuery; + } + + @Override + public Query visit(PhraseQuery phraseQuery) { + BooleanQuery bq = new BooleanQuery(); + + for(Term t: phraseQuery.getTerms()) { + Field f = Field.getByName(t.field()); + + if( f != Field.CONTENTS ) + return phraseQuery; + + bq.add(new FuzzyQuery(t), Occur.SHOULD); + } + + return bq; + } + + @Override + public boolean visit(BooleanClause boolClause) { + if(boolClause.getOccur() == Occur.MUST_NOT) // skip prohibited, don't fuzzify + return false; + + return true; + } + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/QueryVisitor.java b/instasearch/src/it/unibz/instasearch/indexing/querying/QueryVisitor.java new file mode 100755 index 0000000..706cb5f --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/QueryVisitor.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.PhraseQuery; +import org.apache.lucene.search.PrefixQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.WildcardQuery; + +public abstract class QueryVisitor { + + /** + * @param query + * @return Query + */ + public Query visitQuery(Query query) { + return query; + } + + /** + * @param termQuery + * @param field or null if field is not recognized + * @return Query + */ + public Query visit(TermQuery termQuery, Field field) { + return termQuery; + } + + /** + * + * @param boolQuery + * @return the Query to replace boolQuery with (or itself). + * If new query is returned, children of boolQuery are still visited + */ + public BooleanQuery visit(BooleanQuery boolQuery) { + return boolQuery; + } + + /** + * @param boolClause + * @return true if should visit this clause (and its children), false to skip it + */ + public boolean visit(BooleanClause boolClause) { + return true; + } + + /** + * @param phraseQuery + * @return Query + */ + public Query visit(PhraseQuery phraseQuery) { + return phraseQuery; + } + + /** + * @param wildcardQuery + * @param field + * @return Query + */ + public Query visit(WildcardQuery wildcardQuery, Field field) { + return wildcardQuery; + } + + /** + * @param prefixQuery + * @param field + * @return Query + */ + public Query visit(PrefixQuery prefixQuery, Field field) { + return prefixQuery; + } + + /** + * Initialize visitor + * @param query + */ + public void init(Query query) { + + } + + /** + * @param query + * @return modified query + */ + public Query endVisit(Query query) { + return query; + } + +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/UppercaseNameExpander.java b/instasearch/src/it/unibz/instasearch/indexing/querying/UppercaseNameExpander.java new file mode 100755 index 0000000..2abd11b --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/UppercaseNameExpander.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.WildcardQuery; + +/** + * Converts camel-cased file name patterns to wildcard queries. + * Eg. converts ABC to A*B*C in order to match AbstractBaseClass + * also AbsBC will match + */ +public class UppercaseNameExpander extends QueryVisitor { + + @Override + public Query visit(TermQuery termQuery, Field field) { + + if( field != Field.NAME ) + return termQuery; + + Term term = termQuery.getTerm(); + String text = term.text(); + + if( text.matches("[A-Z][a-z0-9_]*[A-Z].*") ) { // if has several uppercase letters + BooleanQuery bq = new BooleanQuery(); + + bq.add(termQuery, Occur.SHOULD); + + String wcText = text.replaceAll("([A-Z][a-z0-9_]*)", "$1*"); + + Term wcTerm = Field.NAME.createTerm(wcText); + WildcardQuery wcQuery = new WildcardQuery(wcTerm); + wcQuery.setBoost( termQuery.getBoost()/2f ); + bq.add(wcQuery, Occur.SHOULD); + + return bq; + } + + return super.visit(termQuery, field); + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/VisitableQuery.java b/instasearch/src/it/unibz/instasearch/indexing/querying/VisitableQuery.java new file mode 100755 index 0000000..e5dc9c2 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/VisitableQuery.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + + + +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.FilteredQuery; +import org.apache.lucene.search.PhraseQuery; +import org.apache.lucene.search.PrefixQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.WildcardQuery; + +/** + * A query that can accepts visitors for its clauses + * The visitors can modify the query + */ +public class VisitableQuery { + + private Query query; + + public VisitableQuery(Query q) { + this.query = q; + } + + /** + * Accept a query visitor + * @param queryVisitor + */ + public void accept(QueryVisitor queryVisitor) { + queryVisitor.init(query); + query = accept(query, queryVisitor); + query = queryVisitor.endVisit(query); + } + + /** + * Recursively go through all the clauses of the query and call the visitor + * + * @param query + * @param queryVisitor + * @return + */ + private Query accept(Query query, QueryVisitor queryVisitor) { + + Query returnQuery = query; + + if( query instanceof TermQuery ) { + TermQuery termQuery = (TermQuery) query; + Field field = Field.getByName(termQuery.getTerm().field()); + + Query newQuery = queryVisitor.visit( termQuery, field ); + + newQuery.setBoost( query.getBoost() ); + returnQuery = newQuery; + + } else if( query instanceof BooleanQuery ) { + BooleanQuery boolQuery = (BooleanQuery) query; + BooleanQuery newBoolQuery = queryVisitor.visit(boolQuery); + + for(BooleanClause boolClause: boolQuery.getClauses()) { + if( ! queryVisitor.visit(boolClause) ) continue; + Query newQuery = accept( boolClause.getQuery(), queryVisitor ); + boolClause.setQuery( newQuery ); + } + + newBoolQuery.setBoost( boolQuery.getBoost() ); + newBoolQuery.setMinimumNumberShouldMatch(boolQuery.getMinimumNumberShouldMatch()); + + returnQuery = newBoolQuery; + } + else if( query instanceof FilteredQuery ) { + FilteredQuery fq = (FilteredQuery) query; + Query newQuery = accept(fq.getQuery(), queryVisitor); + + if( newQuery != fq.getQuery() ) + { + FilteredQuery newFq = new FilteredQuery(fq.getQuery(), fq.getFilter()); + newFq.setBoost( fq.getBoost() ); + + returnQuery = newFq; + } + } + else if( query instanceof PhraseQuery ) { + PhraseQuery phraseQuery = (PhraseQuery) query; + + returnQuery = queryVisitor.visit(phraseQuery); + + } else if( query instanceof WildcardQuery ) { + WildcardQuery wildcardQuery = (WildcardQuery) query; + Field field = Field.getByName(wildcardQuery.getTerm().field()); + + Query newQuery = queryVisitor.visit( wildcardQuery, field ); + + newQuery.setBoost( query.getBoost() ); + returnQuery = newQuery; + + } else if( query instanceof PrefixQuery ) { + PrefixQuery prefixQuery = (PrefixQuery) query; + Field field = Field.getByName(prefixQuery.getPrefix().field()); + + Query newQuery = queryVisitor.visit( prefixQuery, field ); + + newQuery.setBoost( query.getBoost() ); + returnQuery = newQuery; + } + else { + returnQuery = queryVisitor.visitQuery(query); + } + + return returnQuery; + } + + /** + * @return the resulting query after all visitors have changed it + */ + public Query getQuery() { + return query; + } + +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/indexing/querying/WorkingSetExpander.java b/instasearch/src/it/unibz/instasearch/indexing/querying/WorkingSetExpander.java new file mode 100755 index 0000000..87d5897 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/querying/WorkingSetExpander.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.querying; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.indexing.Field; + +import org.apache.lucene.index.Term; +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; + +/** + * Replaces working set name with a list of enclosed projects + */ +public class WorkingSetExpander extends QueryVisitor { + + @Override + public Query visit(TermQuery termQuery, Field field) { + Term term = termQuery.getTerm(); + + if( field == Field.WS ) { + BooleanQuery bq = new BooleanQuery(); + String workingSet = term.text(); + + String projects[] = InstaSearchPlugin.getWorkingSetProjects(workingSet); + + if( projects.length == 0 ) + return termQuery; + + for(String proj: projects) { + if( "".equals(proj) ) continue; + TermQuery tq = new TermQuery(Field.PROJ.createTerm(proj)); + bq.add(tq, Occur.SHOULD); + } + + return bq; + } + + return super.visit(termQuery, field); + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/CamelCaseTokenizer.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/CamelCaseTokenizer.java new file mode 100755 index 0000000..8ecda95 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/CamelCaseTokenizer.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.tokenizers; + + +import org.apache.lucene.analysis.TokenStream; + +/** + * Splits words at camel case, underscore and dot + */ +public class CamelCaseTokenizer extends TermSplitTokenizer { + + public CamelCaseTokenizer(TokenStream in) { + super(in); + } + + @Override + public String[] splitTerm(String term) { + + String newWord = term.replaceAll("([A-Z][a-z])", "_$1"); // not ideal, but short + newWord = newWord.replaceAll("([a-z])([A-Z])", "$1_$2"); + + return newWord.split("[_]"); // will also split CONSTANT_NAMES + } + + @Override + protected boolean returnOriginalTerm() { + return true; + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/DotSplitTokenizer.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/DotSplitTokenizer.java new file mode 100755 index 0000000..a80099d --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/DotSplitTokenizer.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.tokenizers; + + +import org.apache.lucene.analysis.TokenStream; + +/** + * Splits words at non-alphanumeric characters + */ +public class DotSplitTokenizer extends TermSplitTokenizer { + + /** + * @param in + */ + public DotSplitTokenizer(TokenStream in) { + super(in); + } + + @Override + public String[] splitTerm(String term) { + String[] parts = term.split("[.]"); + return parts; + } + + @Override + protected boolean returnOriginalTerm() + { + return true; + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/TermSplitTokenizer.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/TermSplitTokenizer.java new file mode 100755 index 0000000..2084ff8 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/TermSplitTokenizer.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.tokenizers; + +import java.io.IOException; +import java.util.LinkedList; + +import org.apache.lucene.analysis.Token; +import org.apache.lucene.analysis.TokenFilter; +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.analysis.tokenattributes.OffsetAttribute; +import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute; +import org.apache.lucene.analysis.tokenattributes.TermAttribute; + +/** + * Splits terms. Returns the original term and its split parts + */ +public abstract class TermSplitTokenizer extends TokenFilter { + + private LinkedList tokens = new LinkedList(); + + private TermAttribute termAtt; + private OffsetAttribute offsetAtt; + private PositionIncrementAttribute posAtt; + + public TermSplitTokenizer(TokenStream in) { + super(in); + + assert( in.hasAttribute(TermAttribute.class) ); + assert( in.hasAttribute(OffsetAttribute.class) ); + assert( in.hasAttribute(PositionIncrementAttribute.class) ); + + termAtt = (TermAttribute) addAttribute(TermAttribute.class); + offsetAtt = (OffsetAttribute) addAttribute(OffsetAttribute.class); + posAtt = (PositionIncrementAttribute) addAttribute(PositionIncrementAttribute.class); + } + + @Override + public boolean incrementToken() throws IOException + { + if( !tokens.isEmpty() ) + { + applyToken(tokens.removeFirst()); + } + else if( input.incrementToken() ) + { + splitIntoTokens(); + + if( !tokens.isEmpty() ) + { + if( ! returnOriginalTerm() ) + applyToken( tokens.removeFirst() ); + } + } + else + { + return false; // does not have any more tokens + } + + return true; + } + + private void splitIntoTokens() + { + String term = termAtt.term(); + String[] termParts = splitTerm(term); + + if(termParts.length > 1) + { + int termPos = offsetAtt.startOffset(); + + for (int i = 0; i < termParts.length; i++) + { + String termPart = termParts[i]; + int termPartPos = termPos + term.indexOf(termPart); + int termPartEndPos = termPartPos + termPart.length(); + + Token newToken = new Token(termPart, termPartPos, termPartEndPos); + newToken.setPositionIncrement(0); // in the same position + + tokens.add( newToken ); + } + } + } + + private void applyToken(Token token) + { + termAtt.setTermBuffer(token.termBuffer(), 0, token.termLength()); + posAtt.setPositionIncrement(token.getPositionIncrement()); + offsetAtt.setOffset(token.startOffset(), token.endOffset()); + } + + /** + * Return original term together with the parts + * @return returnOriginalTerm + */ + protected boolean returnOriginalTerm() + { + return false; + } + + /** + * Split term into an array of terms + * + * @param term + * @return split term + */ + public abstract String[] splitTerm(String term); +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/WordSplitTokenizer.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/WordSplitTokenizer.java new file mode 100755 index 0000000..76d1a7f --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/WordSplitTokenizer.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing.tokenizers; + + +import org.apache.lucene.analysis.TokenStream; + +/** + * Splits words at non-alphanumeric characters + */ +public class WordSplitTokenizer extends TermSplitTokenizer { + + /** + * @param in + */ + public WordSplitTokenizer(TokenStream in) { + super(in); + } + + @Override + public String[] splitTerm(String term) + { + return term.split("[^A-Za-z0-9\u00E0-\u00FF_'.]"); //"\\W" or "[^A-Za-z0-9'\u00E0-\u00FF]" + } + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/CharStream.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/CharStream.java new file mode 100755 index 0000000..766f763 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/CharStream.java @@ -0,0 +1,115 @@ +/* Generated By:JavaCC: Do not edit this line. CharStream.java Version 5.0 */ +/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ +package it.unibz.instasearch.indexing.tokenizers.standard; + +/** + * This interface describes a character stream that maintains line and + * column number positions of the characters. It also has the capability + * to backup the stream to some extent. An implementation of this + * interface is used in the TokenManager implementation generated by + * JavaCCParser. + * + * All the methods except backup can be implemented in any fashion. backup + * needs to be implemented correctly for the correct operation of the lexer. + * Rest of the methods are all used to get information like line number, + * column number and the String that constitutes a token and are not used + * by the lexer. Hence their implementation won't affect the generated lexer's + * operation. + */ + +public +interface CharStream { + + /** + * Returns the next character from the selected input. The method + * of selecting the input is the responsibility of the class + * implementing this interface. Can throw any java.io.IOException. + */ + char readChar() throws java.io.IOException; + + @Deprecated + /** + * Returns the column position of the character last read. + * @deprecated + * @see #getEndColumn + */ + int getColumn(); + + @Deprecated + /** + * Returns the line number of the character last read. + * @deprecated + * @see #getEndLine + */ + int getLine(); + + /** + * Returns the column number of the last character for current token (being + * matched after the last call to BeginTOken). + */ + int getEndColumn(); + + /** + * Returns the line number of the last character for current token (being + * matched after the last call to BeginTOken). + */ + int getEndLine(); + + /** + * Returns the column number of the first character for current token (being + * matched after the last call to BeginTOken). + */ + int getBeginColumn(); + + /** + * Returns the line number of the first character for current token (being + * matched after the last call to BeginTOken). + */ + int getBeginLine(); + + /** + * Backs up the input stream by amount steps. Lexer calls this method if it + * had already read some characters, but could not use them to match a + * (longer) token. So, they will be used again as the prefix of the next + * token and it is the implemetation's responsibility to do this right. + */ + void backup(int amount); + + /** + * Returns the next character that marks the beginning of the next token. + * All characters must remain in the buffer between two successive calls + * to this method to implement backup correctly. + */ + char BeginToken() throws java.io.IOException; + + /** + * Returns a string made up of characters from the marked token beginning + * to the current buffer position. Implementations have the choice of returning + * anything that they want to. For example, for efficiency, one might decide + * to just return null, which is a valid implementation. + */ + String GetImage(); + + /** + * Returns an array of characters that make up the suffix of length 'len' for + * the currently matched token. This is used to build up the matched string + * for use in actions in the case of MORE. A simple and inefficient + * implementation of this is as follows : + * + * { + * String t = GetImage(); + * return t.substring(t.length() - len, t.length()).toCharArray(); + * } + */ + char[] GetSuffix(int len); + + /** + * The lexer calls this function to indicate that it is done with the stream + * and hence implementations can free any resources held by this class. + * Again, the body of this function can be just empty and it will not + * affect the lexer's operation. + */ + void Done(); + +} +/* JavaCC - OriginalChecksum=2307bc80dd6b392620032acbc9db7950 (do not edit this line) */ diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/FastCharStream.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/FastCharStream.java new file mode 100755 index 0000000..d6b1585 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/FastCharStream.java @@ -0,0 +1,120 @@ +package it.unibz.instasearch.indexing.tokenizers.standard; + +/** + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.*; + +/** An efficient implementation of JavaCC's CharStream interface.

    Note that + * this does not do line-number counting, but instead keeps track of the + * character position of the token in the input, as required by Lucene's {@link + * org.apache.lucene.analysis.Token} API. */ +public final class FastCharStream implements CharStream { + char[] buffer = null; + + int bufferLength = 0; // end of valid chars + int bufferPosition = 0; // next char to read + + int tokenStart = 0; // offset in buffer + int bufferStart = 0; // position in file of buffer + + Reader input; // source of chars + + /** Constructs from a Reader. */ + public FastCharStream(Reader r) { + input = r; + } + + public final char readChar() throws IOException { + if (bufferPosition >= bufferLength) + refill(); + return buffer[bufferPosition++]; + } + + private final void refill() throws IOException { + int newPosition = bufferLength - tokenStart; + + if (tokenStart == 0) { // token won't fit in buffer + if (buffer == null) { // first time: alloc buffer + buffer = new char[2048]; + } else if (bufferLength == buffer.length) { // grow buffer + char[] newBuffer = new char[buffer.length*2]; + System.arraycopy(buffer, 0, newBuffer, 0, bufferLength); + buffer = newBuffer; + } + } else { // shift token to front + System.arraycopy(buffer, tokenStart, buffer, 0, newPosition); + } + + bufferLength = newPosition; // update state + bufferPosition = newPosition; + bufferStart += tokenStart; + tokenStart = 0; + + int charsRead = // fill space in buffer + input.read(buffer, newPosition, buffer.length-newPosition); + if (charsRead == -1) + throw new IOException("read past eof"); + else + bufferLength += charsRead; + } + + public final char BeginToken() throws IOException { + tokenStart = bufferPosition; + return readChar(); + } + + public final void backup(int amount) { + bufferPosition -= amount; + } + + public final String GetImage() { + return new String(buffer, tokenStart, bufferPosition - tokenStart); + } + + public final char[] GetSuffix(int len) { + char[] value = new char[len]; + System.arraycopy(buffer, bufferPosition - len, value, 0, len); + return value; + } + + public final void Done() { + try { + input.close(); + } catch (IOException e) { + System.err.println("Caught: " + e + "; ignoring."); + } + } + + public final int getColumn() { + return bufferStart + bufferPosition; + } + public final int getLine() { + return 1; + } + public final int getEndColumn() { + return bufferStart + bufferPosition; + } + public final int getEndLine() { + return 1; + } + public final int getBeginColumn() { + return bufferStart + tokenStart; + } + public final int getBeginLine() { + return 1; + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/ParseException.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/ParseException.java new file mode 100755 index 0000000..a70f8d7 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/ParseException.java @@ -0,0 +1,187 @@ +/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */ +/* JavaCCOptions:KEEP_LINE_COL=null */ +package it.unibz.instasearch.indexing.tokenizers.standard; + +/** + * This exception is thrown when parse errors are encountered. + * You can explicitly create objects of this exception type by + * calling the method generateParseException in the generated + * parser. + * + * You can modify this class to customize your error reporting + * mechanisms so long as you retain the public fields. + */ +public class ParseException extends RuntimeException { + + /** + * The version identifier for this Serializable class. + * Increment only if the serialized form of the + * class changes. + */ + private static final long serialVersionUID = 1L; + + /** + * This constructor is used by the method "generateParseException" + * in the generated parser. Calling this constructor generates + * a new object of this type with the fields "currentToken", + * "expectedTokenSequences", and "tokenImage" set. + */ + public ParseException(Token currentTokenVal, + int[][] expectedTokenSequencesVal, + String[] tokenImageVal + ) + { + super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal)); + currentToken = currentTokenVal; + expectedTokenSequences = expectedTokenSequencesVal; + tokenImage = tokenImageVal; + } + + /** + * The following constructors are for use by you for whatever + * purpose you can think of. Constructing the exception in this + * manner makes the exception behave in the normal way - i.e., as + * documented in the class "Throwable". The fields "errorToken", + * "expectedTokenSequences", and "tokenImage" do not contain + * relevant information. The JavaCC generated code does not use + * these constructors. + */ + + public ParseException() { + super(); + } + + /** Constructor with message. */ + public ParseException(String message) { + super(message); + } + + + /** + * This is the last token that has been consumed successfully. If + * this object has been created due to a parse error, the token + * followng this token will (therefore) be the first error token. + */ + public Token currentToken; + + /** + * Each entry in this array is an array of integers. Each array + * of integers represents a sequence of tokens (by their ordinal + * values) that is expected at this point of the parse. + */ + public int[][] expectedTokenSequences; + + /** + * This is a reference to the "tokenImage" array of the generated + * parser within which the parse error occurred. This array is + * defined in the generated ...Constants interface. + */ + public String[] tokenImage; + + /** + * It uses "currentToken" and "expectedTokenSequences" to generate a parse + * error message and returns it. If this object has been created + * due to a parse error, and you do not catch it (it gets thrown + * from the parser) the correct error message + * gets displayed. + */ + private static String initialise(Token currentToken, + int[][] expectedTokenSequences, + String[] tokenImage) { + String eol = System.getProperty("line.separator", "\n"); + StringBuffer expected = new StringBuffer(); + int maxSize = 0; + for (int i = 0; i < expectedTokenSequences.length; i++) { + if (maxSize < expectedTokenSequences[i].length) { + maxSize = expectedTokenSequences[i].length; + } + for (int j = 0; j < expectedTokenSequences[i].length; j++) { + expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' '); + } + if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { + expected.append("..."); + } + expected.append(eol).append(" "); + } + String retval = "Encountered \""; + Token tok = currentToken.next; + for (int i = 0; i < maxSize; i++) { + if (i != 0) retval += " "; + if (tok.kind == 0) { + retval += tokenImage[0]; + break; + } + retval += " " + tokenImage[tok.kind]; + retval += " \""; + retval += add_escapes(tok.image); + retval += " \""; + tok = tok.next; + } + retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; + retval += "." + eol; + if (expectedTokenSequences.length == 1) { + retval += "Was expecting:" + eol + " "; + } else { + retval += "Was expecting one of:" + eol + " "; + } + retval += expected.toString(); + return retval; + } + + /** + * The end of line string for this machine. + */ + protected String eol = System.getProperty("line.separator", "\n"); + + /** + * Used to convert raw characters to their escaped version + * when these raw version cannot be used as part of an ASCII + * string literal. + */ + static String add_escapes(String str) { + StringBuffer retval = new StringBuffer(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) + { + case 0 : + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + +} +/* JavaCC - OriginalChecksum=3daa8e3236de7ab1c44859baa09c8e74 (do not edit this line) */ diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/ReadMe.txt b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/ReadMe.txt new file mode 100755 index 0000000..ebc6264 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/ReadMe.txt @@ -0,0 +1,3 @@ +Java files generated from StandardTokenizer.jj using JavaCC Eclipse Plug-in + +http://eclipse-javacc.sourceforge.net/ diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizer.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizer.java new file mode 100755 index 0000000..d88f4d2 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizer.java @@ -0,0 +1,209 @@ +/* Generated By:JavaCC: Do not edit this line. StandardTokenizer.java */ +package it.unibz.instasearch.indexing.tokenizers.standard; + +import java.io.IOException; + +/** A grammar-based tokenizer constructed with JavaCC. + * + *

    This should be a good tokenizer for most European-language documents: + * + *

      + *
    • Splits words at punctuation characters, removing punctuation. However, a + * dot that's not followed by whitespace is considered part of a token. + *
    • Splits words at hyphens, unless there's a number in the token, in which case + * the whole token is interpreted as a product number and is not split. + *
    • Recognizes email addresses and internet hostnames as one token. + *
    + * + *

    Many applications have specific tokenizer needs. If this tokenizer does + * not suit your application, please consider copying this source code + * directory to your project and maintaining your own grammar-based tokenizer. + */ +public class StandardTokenizer extends org.apache.lucene.analysis.Tokenizer implements StandardTokenizerConstants { + + /** Constructs a tokenizer for this Reader. */ + public StandardTokenizer(java.io.Reader reader) { + this(new FastCharStream(reader)); + this.input = reader; + } + +/** Returns the next token in the stream, or null at EOS. + *

    The returned token's type is set to an element of {@link + * StandardTokenizerConstants#tokenImage}. + */ + @SuppressWarnings("unused") +final public org.apache.lucene.analysis.Token next() throws ParseException, IOException { + Token token = null; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ALPHANUM: + token = jj_consume_token(ALPHANUM); + break; + case APOSTROPHE: + token = jj_consume_token(APOSTROPHE); + break; + case ACRONYM: + token = jj_consume_token(ACRONYM); + break; + case NUM: + token = jj_consume_token(NUM); + break; + case CJ: + token = jj_consume_token(CJ); + break; + case 0: + token = jj_consume_token(0); + break; + default: + jj_la1[0] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + if (token.kind == EOF) { + {if (true) return null;} + } else { + {if (true) return + new org.apache.lucene.analysis.Token(token.image, + token.beginColumn,token.endColumn, + tokenImage[token.kind]);} + } + throw new Error("Missing return statement in function"); + } + + /** Generated Token Manager. */ + public StandardTokenizerTokenManager token_source; + /** Current token. */ + public Token token; + /** Next token. */ + public Token jj_nt; + private int jj_ntk; + private int jj_gen; + final private int[] jj_la1 = new int[1]; + static private int[] jj_la1_0; + static { + jj_la1_init_0(); + } + private static void jj_la1_init_0() { + jj_la1_0 = new int[] {0x21f,}; + } + + /** Constructor with user supplied CharStream. */ + public StandardTokenizer(CharStream stream) { + token_source = new StandardTokenizerTokenManager(stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 1; i++) jj_la1[i] = -1; + } + + /** Reinitialise. */ + public void ReInit(CharStream stream) { + token_source.ReInit(stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 1; i++) jj_la1[i] = -1; + } + + /** Constructor with generated Token Manager. */ + public StandardTokenizer(StandardTokenizerTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 1; i++) jj_la1[i] = -1; + } + + /** Reinitialise. */ + public void ReInit(StandardTokenizerTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 1; i++) jj_la1[i] = -1; + } + + private Token jj_consume_token(int kind) throws ParseException { + Token oldToken; + if ((oldToken = token).next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + if (token.kind == kind) { + jj_gen++; + return token; + } + token = oldToken; + jj_kind = kind; + throw generateParseException(); + } + + +/** Get the next Token. */ + final public Token getNextToken() { + if (token.next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + jj_gen++; + return token; + } + +/** Get the specific Token. */ + final public Token getToken(int index) { + Token t = token; + for (int i = 0; i < index; i++) { + if (t.next != null) t = t.next; + else t = t.next = token_source.getNextToken(); + } + return t; + } + + private int jj_ntk() { + if ((jj_nt=token.next) == null) + return (jj_ntk = (token.next=token_source.getNextToken()).kind); + else + return (jj_ntk = jj_nt.kind); + } + + private java.util.List jj_expentries = new java.util.ArrayList(); + private int[] jj_expentry; + private int jj_kind = -1; + + /** Generate ParseException. */ + public ParseException generateParseException() { + jj_expentries.clear(); + boolean[] la1tokens = new boolean[13]; + if (jj_kind >= 0) { + la1tokens[jj_kind] = true; + jj_kind = -1; + } + for (int i = 0; i < 1; i++) { + if (jj_la1[i] == jj_gen) { + for (int j = 0; j < 32; j++) { + if ((jj_la1_0[i] & (1< This should be a good tokenizer for most European-language documents: + * + *

      + *
    • Splits words at punctuation characters, removing punctuation. However, a + * dot that's not followed by whitespace is considered part of a token. + *
    • Splits words at hyphens, unless there's a number in the token, in which case + * the whole token is interpreted as a product number and is not split. + *
    • Recognizes email addresses and internet hostnames as one token. + *
    + * + *

    Many applications have specific tokenizer needs. If this tokenizer does + * not suit your application, please consider copying this source code + * directory to your project and maintaining your own grammar-based tokenizer. + */ +public class StandardTokenizer extends org.apache.lucene.analysis.Tokenizer { + + /** Constructs a tokenizer for this Reader. */ + public StandardTokenizer(java.io.Reader reader) { + this(new FastCharStream(reader)); + this.input = reader; + } +} + +PARSER_END(StandardTokenizer) + +TOKEN : { // token patterns + + // basic word: a sequence of digits & letters + ||)+ > + + // internal apostrophes: O'Reilly, you're, O'Reilly's + // use a post-filter to remove possesives +| ("'" )+ > + + // acronyms: U.S.A., I.B.M., etc. + // use a post-filter to remove dots +| "." ( ".")+ > + + // floating point, serial, model numbers, ip addresses, etc. + // every other segment must have at least one digit +|

    + |

    + | (

    )+ + | (

    )+ + |

    (

    )+ + |

    (

    )+ + ) + > +| <#P: ("_"|"-"|"/"|"."|",") > +| <#HAS_DIGIT: // at least one digit + (|)* + + (|)* + > + +| < #ALPHA: ()+> +| < #LETTER: // unicode letters + [ + "_", ".", + "\u0041"-"\u005a", + "\u0061"-"\u007a", + "\u00c0"-"\u00d6", + "\u00d8"-"\u00f6", + "\u00f8"-"\u00ff", + "\u0100"-"\u1fff" + ] + > +| < CJ: // Chinese, Japanese + [ + "\u3040"-"\u318f", + "\u3300"-"\u337f", + "\u3400"-"\u3d2d", + "\u4e00"-"\u9fff", + "\uf900"-"\ufaff" + ] + > +| < KOREAN: // Korean + [ + "\uac00"-"\ud7af" + ] + > +| < #DIGIT: // unicode digits + [ + "\u0030"-"\u0039", + "\u0660"-"\u0669", + "\u06f0"-"\u06f9", + "\u0966"-"\u096f", + "\u09e6"-"\u09ef", + "\u0a66"-"\u0a6f", + "\u0ae6"-"\u0aef", + "\u0b66"-"\u0b6f", + "\u0be7"-"\u0bef", + "\u0c66"-"\u0c6f", + "\u0ce6"-"\u0cef", + "\u0d66"-"\u0d6f", + "\u0e50"-"\u0e59", + "\u0ed0"-"\u0ed9", + "\u1040"-"\u1049" + ] + > +} + +SKIP : { // skip unrecognized chars + +} + +/** Returns the next token in the stream, or null at EOS. + *

    The returned token's type is set to an element of {@link + * StandardTokenizerConstants#tokenImage}. + */ +org.apache.lucene.analysis.Token next() throws IOException : +{ + Token token = null; +} +{ + ( token = | + token = | + token = | + token = | + token = | + token = + ) + { + if (token.kind == EOF) { + return null; + } else { + return + new org.apache.lucene.analysis.Token(token.image, + token.beginColumn,token.endColumn, + tokenImage[token.kind]); + } + } +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizerConstants.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizerConstants.java new file mode 100755 index 0000000..159870d --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizerConstants.java @@ -0,0 +1,58 @@ +/* Generated By:JavaCC: Do not edit this line. StandardTokenizerConstants.java */ +package it.unibz.instasearch.indexing.tokenizers.standard; + + +/** + * Token literal values and constants. + * Generated by org.javacc.parser.OtherFilesGen#start() + */ +public interface StandardTokenizerConstants { + + /** End of File. */ + int EOF = 0; + /** RegularExpression Id. */ + int ALPHANUM = 1; + /** RegularExpression Id. */ + int APOSTROPHE = 2; + /** RegularExpression Id. */ + int ACRONYM = 3; + /** RegularExpression Id. */ + int NUM = 4; + /** RegularExpression Id. */ + int P = 5; + /** RegularExpression Id. */ + int HAS_DIGIT = 6; + /** RegularExpression Id. */ + int ALPHA = 7; + /** RegularExpression Id. */ + int LETTER = 8; + /** RegularExpression Id. */ + int CJ = 9; + /** RegularExpression Id. */ + int KOREAN = 10; + /** RegularExpression Id. */ + int DIGIT = 11; + /** RegularExpression Id. */ + int NOISE = 12; + + /** Lexical state. */ + int DEFAULT = 0; + + /** Literal token values. */ + String[] tokenImage = { + "", + "", + "", + "", + "", + "

    ", + "", + "", + "", + "", + "", + "", + "", + }; + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizerTokenManager.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizerTokenManager.java new file mode 100755 index 0000000..2b062db --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/StandardTokenizerTokenManager.java @@ -0,0 +1,1161 @@ +/* Generated By:JavaCC: Do not edit this line. StandardTokenizerTokenManager.java */ +package it.unibz.instasearch.indexing.tokenizers.standard; + +/** Token Manager. */ +public class StandardTokenizerTokenManager implements StandardTokenizerConstants +{ + + /** Debug output. */ + public java.io.PrintStream debugStream = System.out; + /** Set debug output. */ + public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } +private int jjMoveStringLiteralDfa0_0() +{ + return jjMoveNfa_0(0, 0); +} +static final long[] jjbitVec0 = { + 0x1ff0000000000000L, 0xffffffffffffc000L, 0xffffffffL, 0x600000000000000L +}; +static final long[] jjbitVec2 = { + 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL +}; +static final long[] jjbitVec3 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffL, 0x0L +}; +static final long[] jjbitVec4 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0x0L, 0x0L +}; +static final long[] jjbitVec5 = { + 0x3fffffffffffL, 0x0L, 0x0L, 0x0L +}; +static final long[] jjbitVec6 = { + 0x0L, 0x0L, 0xfffff00000000000L, 0x7fffffL +}; +static final long[] jjbitVec7 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffL, 0x0L +}; +static final long[] jjbitVec8 = { + 0xfffffffeL, 0x0L, 0x0L, 0x0L +}; +static final long[] jjbitVec9 = { + 0x0L, 0x0L, 0x0L, 0xff7fffffff7fffffL +}; +static final long[] jjbitVec10 = { + 0x1600L, 0x0L, 0x0L, 0x0L +}; +static final long[] jjbitVec11 = { + 0x0L, 0xffc000000000L, 0x0L, 0xffc000000000L +}; +static final long[] jjbitVec12 = { + 0x0L, 0x3ff00000000L, 0x0L, 0x3ff000000000000L +}; +static final long[] jjbitVec13 = { + 0x0L, 0xffc000000000L, 0x0L, 0xff8000000000L +}; +static final long[] jjbitVec14 = { + 0x0L, 0xffc000000000L, 0x0L, 0x0L +}; +static final long[] jjbitVec15 = { + 0x0L, 0x3ff0000L, 0x0L, 0x3ff0000L +}; +static final long[] jjbitVec16 = { + 0x0L, 0x3ffL, 0x0L, 0x0L +}; +static final long[] jjbitVec17 = { + 0xfffffffeL, 0x0L, 0xfffff00000000000L, 0x7fffffL +}; +private int jjMoveNfa_0(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 62; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 0: + if ((0x3ff400000000000L & l) != 0L) + { + if (kind > 1) + kind = 1; + jjCheckNAddStates(0, 6); + } + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddStates(7, 12); + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(13, 18); + else if (curChar == 46) + jjCheckNAddStates(19, 22); + break; + case 2: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddStates(7, 12); + break; + case 3: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(3, 4); + break; + case 4: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(5, 6); + break; + case 5: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(5, 6); + break; + case 6: + if ((0xf00000000000L & l) != 0L) + jjCheckNAdd(7); + break; + case 7: + if ((0x3ff400000000000L & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAdd(7); + break; + case 8: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(8, 9); + break; + case 9: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(10, 11); + break; + case 10: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(10, 11); + break; + case 11: + if ((0xf00000000000L & l) != 0L) + jjCheckNAdd(12); + break; + case 12: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(12, 13); + break; + case 13: + if ((0xf00000000000L & l) != 0L) + jjCheckNAddTwoStates(14, 15); + break; + case 14: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(14, 15); + break; + case 15: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(11, 16); + break; + case 16: + if ((0x3ff400000000000L & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(11, 16); + break; + case 17: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(17, 18); + break; + case 18: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(19, 20); + break; + case 19: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(19, 20); + break; + case 20: + if ((0xf00000000000L & l) != 0L) + jjCheckNAdd(21); + break; + case 21: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(21, 22); + break; + case 22: + if ((0xf00000000000L & l) != 0L) + jjCheckNAddTwoStates(23, 24); + break; + case 23: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(23, 24); + break; + case 24: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(25, 26); + break; + case 25: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(25, 26); + break; + case 26: + if ((0xf00000000000L & l) != 0L) + jjCheckNAdd(27); + break; + case 27: + if ((0x3ff400000000000L & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(22, 27); + break; + case 28: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(13, 18); + break; + case 29: + if ((0x3ff400000000000L & l) == 0L) + break; + if (kind > 1) + kind = 1; + jjCheckNAddStates(0, 6); + break; + case 30: + if ((0x3ff400000000000L & l) == 0L) + break; + if (kind > 1) + kind = 1; + jjCheckNAdd(30); + break; + case 31: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(31, 32); + break; + case 32: + if ((0xf00000000000L & l) != 0L) + jjCheckNAddTwoStates(33, 34); + break; + case 33: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(33, 34); + break; + case 34: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAdd(35); + break; + case 35: + if ((0x3ff400000000000L & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAdd(35); + break; + case 36: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(36, 37); + break; + case 37: + if ((0xf00000000000L & l) != 0L) + jjCheckNAddTwoStates(38, 39); + break; + case 38: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(38, 39); + break; + case 39: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(40, 41); + break; + case 40: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(40, 41); + break; + case 41: + if ((0xf00000000000L & l) != 0L) + jjCheckNAdd(42); + break; + case 42: + if ((0x3ff400000000000L & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(37, 42); + break; + case 43: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(43, 44); + break; + case 44: + if ((0xf00000000000L & l) != 0L) + jjCheckNAddTwoStates(45, 46); + break; + case 45: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(45, 46); + break; + case 46: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(47, 48); + break; + case 47: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(47, 48); + break; + case 48: + if ((0xf00000000000L & l) != 0L) + jjCheckNAdd(49); + break; + case 49: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(49, 50); + break; + case 50: + if ((0xf00000000000L & l) != 0L) + jjCheckNAddTwoStates(51, 52); + break; + case 51: + if ((0x3ff400000000000L & l) != 0L) + jjCheckNAddTwoStates(51, 52); + break; + case 52: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(48, 53); + break; + case 53: + if ((0x3ff400000000000L & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(48, 53); + break; + case 54: + if (curChar == 46) + jjCheckNAddStates(19, 22); + break; + case 55: + if (curChar == 46) + jjCheckNAddTwoStates(55, 56); + break; + case 56: + if (curChar == 39) + jjCheckNAdd(57); + break; + case 57: + if (curChar != 46) + break; + if (kind > 2) + kind = 2; + jjCheckNAddTwoStates(56, 57); + break; + case 58: + if (curChar == 46) + jjCheckNAddTwoStates(58, 59); + break; + case 59: + if (curChar == 46) + jjCheckNAdd(60); + break; + case 60: + if (curChar == 46) + jjCheckNAddTwoStates(60, 61); + break; + case 61: + if (curChar != 46) + break; + if (kind > 3) + kind = 3; + jjCheckNAdd(60); + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 0: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddStates(19, 22); + if ((0x7fffffe87fffffeL & l) != 0L) + { + if (kind > 1) + kind = 1; + jjCheckNAddStates(0, 6); + } + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddStates(7, 12); + break; + case 2: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddStates(7, 12); + break; + case 3: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(3, 4); + break; + case 5: + if ((0x7fffffe87fffffeL & l) != 0L) + jjAddStates(23, 24); + break; + case 6: + if (curChar == 95) + jjCheckNAdd(7); + break; + case 7: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAdd(7); + break; + case 8: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(8, 9); + break; + case 10: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(10, 11); + break; + case 11: + if (curChar == 95) + jjCheckNAdd(12); + break; + case 12: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(12, 13); + break; + case 13: + if (curChar == 95) + jjCheckNAddTwoStates(14, 15); + break; + case 14: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(14, 15); + break; + case 16: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(11, 16); + break; + case 17: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(17, 18); + break; + case 19: + if ((0x7fffffe87fffffeL & l) != 0L) + jjAddStates(25, 26); + break; + case 20: + if (curChar == 95) + jjCheckNAdd(21); + break; + case 21: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(21, 22); + break; + case 22: + if (curChar == 95) + jjCheckNAddTwoStates(23, 24); + break; + case 23: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(23, 24); + break; + case 25: + if ((0x7fffffe87fffffeL & l) != 0L) + jjAddStates(27, 28); + break; + case 26: + if (curChar == 95) + jjCheckNAdd(27); + break; + case 27: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(22, 27); + break; + case 29: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 1) + kind = 1; + jjCheckNAddStates(0, 6); + break; + case 30: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 1) + kind = 1; + jjCheckNAdd(30); + break; + case 31: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(31, 32); + break; + case 32: + if (curChar == 95) + jjCheckNAddTwoStates(33, 34); + break; + case 33: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(33, 34); + break; + case 35: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjstateSet[jjnewStateCnt++] = 35; + break; + case 36: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(36, 37); + break; + case 37: + if (curChar == 95) + jjCheckNAddTwoStates(38, 39); + break; + case 38: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(38, 39); + break; + case 40: + if ((0x7fffffe87fffffeL & l) != 0L) + jjAddStates(29, 30); + break; + case 41: + if (curChar == 95) + jjCheckNAdd(42); + break; + case 42: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(37, 42); + break; + case 43: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(43, 44); + break; + case 44: + if (curChar == 95) + jjCheckNAddTwoStates(45, 46); + break; + case 45: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(45, 46); + break; + case 47: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(47, 48); + break; + case 48: + if (curChar == 95) + jjCheckNAdd(49); + break; + case 49: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(49, 50); + break; + case 50: + if (curChar == 95) + jjCheckNAddTwoStates(51, 52); + break; + case 51: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(51, 52); + break; + case 53: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(48, 53); + break; + case 54: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddStates(19, 22); + break; + case 55: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(55, 56); + break; + case 57: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 2) + kind = 2; + jjCheckNAddTwoStates(56, 57); + break; + case 58: + if ((0x7fffffe87fffffeL & l) != 0L) + jjCheckNAddTwoStates(58, 59); + break; + case 60: + if ((0x7fffffe87fffffeL & l) != 0L) + jjAddStates(31, 32); + break; + default : break; + } + } while(i != startsAt); + } + else + { + int hiByte = (int)(curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 0: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + { + if (kind > 9) + kind = 9; + } + if (jjCanMove_1(hiByte, i1, i2, l1, l2)) + { + if (kind > 10) + kind = 10; + } + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddStates(7, 12); + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddStates(13, 18); + if (jjCanMove_4(hiByte, i1, i2, l1, l2)) + { + if (kind > 1) + kind = 1; + jjCheckNAddStates(0, 6); + } + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddStates(19, 22); + break; + case 1: + if (jjCanMove_1(hiByte, i1, i2, l1, l2) && kind > 10) + kind = 10; + break; + case 2: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddStates(7, 12); + break; + case 3: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(3, 4); + break; + case 4: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(5, 6); + break; + case 5: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(5, 6); + break; + case 7: + if (!jjCanMove_4(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjstateSet[jjnewStateCnt++] = 7; + break; + case 8: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(8, 9); + break; + case 9: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(10, 11); + break; + case 10: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(10, 11); + break; + case 12: + if (jjCanMove_4(hiByte, i1, i2, l1, l2)) + jjAddStates(33, 34); + break; + case 14: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjAddStates(35, 36); + break; + case 15: + if (!jjCanMove_3(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(11, 16); + break; + case 16: + if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(11, 16); + break; + case 17: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(17, 18); + break; + case 18: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(19, 20); + break; + case 19: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(19, 20); + break; + case 21: + if (jjCanMove_4(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(21, 22); + break; + case 23: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjAddStates(37, 38); + break; + case 24: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(25, 26); + break; + case 25: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(25, 26); + break; + case 27: + if (!jjCanMove_4(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(22, 27); + break; + case 28: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddStates(13, 18); + break; + case 29: + if (!jjCanMove_4(hiByte, i1, i2, l1, l2)) + break; + if (kind > 1) + kind = 1; + jjCheckNAddStates(0, 6); + break; + case 30: + if (!jjCanMove_4(hiByte, i1, i2, l1, l2)) + break; + if (kind > 1) + kind = 1; + jjCheckNAdd(30); + break; + case 31: + if (jjCanMove_4(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(31, 32); + break; + case 33: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjAddStates(39, 40); + break; + case 34: + if (!jjCanMove_3(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjCheckNAdd(35); + break; + case 35: + if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjCheckNAdd(35); + break; + case 36: + if (jjCanMove_4(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(36, 37); + break; + case 38: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjAddStates(41, 42); + break; + case 39: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(40, 41); + break; + case 40: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(40, 41); + break; + case 42: + if (!jjCanMove_4(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(37, 42); + break; + case 43: + if (jjCanMove_4(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(43, 44); + break; + case 45: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjAddStates(43, 44); + break; + case 46: + if (jjCanMove_3(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(47, 48); + break; + case 47: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(47, 48); + break; + case 49: + if (jjCanMove_4(hiByte, i1, i2, l1, l2)) + jjAddStates(45, 46); + break; + case 51: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjAddStates(47, 48); + break; + case 52: + if (!jjCanMove_3(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(48, 53); + break; + case 53: + if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjCheckNAddTwoStates(48, 53); + break; + case 54: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddStates(19, 22); + break; + case 55: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(55, 56); + break; + case 57: + if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) + break; + if (kind > 2) + kind = 2; + jjCheckNAddTwoStates(56, 57); + break; + case 58: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjCheckNAddTwoStates(58, 59); + break; + case 60: + if (jjCanMove_2(hiByte, i1, i2, l1, l2)) + jjAddStates(31, 32); + break; + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 62 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +static final int[] jjnextStates = { + 30, 31, 32, 36, 37, 43, 44, 3, 4, 8, 9, 17, 18, 5, 6, 10, + 11, 19, 20, 55, 56, 58, 59, 5, 6, 19, 20, 25, 26, 40, 41, 60, + 61, 12, 13, 14, 15, 23, 24, 33, 34, 38, 39, 45, 46, 49, 50, 51, + 52, +}; +private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 48: + return ((jjbitVec2[i2] & l2) != 0L); + case 49: + return ((jjbitVec3[i2] & l2) != 0L); + case 51: + return ((jjbitVec4[i2] & l2) != 0L); + case 61: + return ((jjbitVec5[i2] & l2) != 0L); + default : + if ((jjbitVec0[i1] & l1) != 0L) + return true; + return false; + } +} +private static final boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 215: + return ((jjbitVec7[i2] & l2) != 0L); + default : + if ((jjbitVec6[i1] & l1) != 0L) + return true; + return false; + } +} +private static final boolean jjCanMove_2(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 0: + return ((jjbitVec9[i2] & l2) != 0L); + default : + if ((jjbitVec8[i1] & l1) != 0L) + return true; + return false; + } +} +private static final boolean jjCanMove_3(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 6: + return ((jjbitVec12[i2] & l2) != 0L); + case 11: + return ((jjbitVec13[i2] & l2) != 0L); + case 13: + return ((jjbitVec14[i2] & l2) != 0L); + case 14: + return ((jjbitVec15[i2] & l2) != 0L); + case 16: + return ((jjbitVec16[i2] & l2) != 0L); + default : + if ((jjbitVec10[i1] & l1) != 0L) + if ((jjbitVec11[i2] & l2) == 0L) + return false; + else + return true; + return false; + } +} +private static final boolean jjCanMove_4(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 0: + return ((jjbitVec9[i2] & l2) != 0L); + case 215: + return ((jjbitVec7[i2] & l2) != 0L); + default : + if ((jjbitVec17[i1] & l1) != 0L) + return true; + return false; + } +} + +/** Token literal values. */ +public static final String[] jjstrLiteralImages = { +"", null, null, null, null, null, null, null, null, null, null, null, null, }; + +/** Lexer state names. */ +public static final String[] lexStateNames = { + "DEFAULT", +}; +static final long[] jjtoToken = { + 0x61fL, +}; +static final long[] jjtoSkip = { + 0x1000L, +}; +protected CharStream input_stream; +private final int[] jjrounds = new int[62]; +private final int[] jjstateSet = new int[124]; +protected char curChar; +/** Constructor. */ +public StandardTokenizerTokenManager(CharStream stream){ + input_stream = stream; +} + +/** Constructor. */ +public StandardTokenizerTokenManager(CharStream stream, int lexState){ + this(stream); + SwitchTo(lexState); +} + +/** Reinitialise parser. */ +public void ReInit(CharStream stream) +{ + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); +} +private void ReInitRounds() +{ + int i; + jjround = 0x80000001; + for (i = 62; i-- > 0;) + jjrounds[i] = 0x80000000; +} + +/** Reinitialise parser. */ +public void ReInit(CharStream stream, int lexState) +{ + ReInit(stream); + SwitchTo(lexState); +} + +/** Switch to specified lex state. */ +public void SwitchTo(int lexState) +{ + if (lexState >= 1 || lexState < 0) + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); + else + curLexState = lexState; +} + +protected Token jjFillToken() +{ + final Token t; + final String curTokenImage; + final int beginLine; + final int endLine; + final int beginColumn; + final int endColumn; + String im = jjstrLiteralImages[jjmatchedKind]; + curTokenImage = (im == null) ? input_stream.GetImage() : im; + beginLine = input_stream.getBeginLine(); + beginColumn = input_stream.getBeginColumn(); + endLine = input_stream.getEndLine(); + endColumn = input_stream.getEndColumn(); + t = Token.newToken(jjmatchedKind, curTokenImage); + + t.beginLine = beginLine; + t.endLine = endLine; + t.beginColumn = beginColumn; + t.endColumn = endColumn; + + return t; +} + +int curLexState = 0; +int defaultLexState = 0; +int jjnewStateCnt; +int jjround; +int jjmatchedPos; +int jjmatchedKind; + +/** Get the next Token. */ +public Token getNextToken() +{ + Token matchedToken; + int curPos = 0; + + EOFLoop : + for (;;) + { + try + { + curChar = input_stream.BeginToken(); + } + catch(java.io.IOException e) + { + jjmatchedKind = 0; + matchedToken = jjFillToken(); + return matchedToken; + } + + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + if (jjmatchedPos == 0 && jjmatchedKind > 12) + { + jjmatchedKind = 12; + } + if (jjmatchedKind != 0x7fffffff) + { + if (jjmatchedPos + 1 < curPos) + input_stream.backup(curPos - jjmatchedPos - 1); + if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + matchedToken = jjFillToken(); + return matchedToken; + } + else + { + continue EOFLoop; + } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { input_stream.readChar(); input_stream.backup(1); } + catch (java.io.IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } + else + error_column++; + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); + } +} + +private void jjCheckNAdd(int state) +{ + if (jjrounds[state] != jjround) + { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } +} +private void jjAddStates(int start, int end) +{ + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); +} +private void jjCheckNAddTwoStates(int state1, int state2) +{ + jjCheckNAdd(state1); + jjCheckNAdd(state2); +} + +private void jjCheckNAddStates(int start, int end) +{ + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); +} + +} diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/Token.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/Token.java new file mode 100755 index 0000000..bddebf2 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/Token.java @@ -0,0 +1,131 @@ +/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */ +/* JavaCCOptions:TOKEN_EXTENDS=org.apache.lucene.analysis.standard.Token,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ +package it.unibz.instasearch.indexing.tokenizers.standard; + +/** + * Describes the input token stream. + */ + +public class Token extends org.apache.lucene.analysis.Token implements java.io.Serializable { + + /** + * The version identifier for this Serializable class. + * Increment only if the serialized form of the + * class changes. + */ + private static final long serialVersionUID = 1L; + + /** + * An integer that describes the kind of this token. This numbering + * system is determined by JavaCCParser, and a table of these numbers is + * stored in the file ...Constants.java. + */ + public int kind; + + /** The line number of the first character of this Token. */ + public int beginLine; + /** The column number of the first character of this Token. */ + public int beginColumn; + /** The line number of the last character of this Token. */ + public int endLine; + /** The column number of the last character of this Token. */ + public int endColumn; + + /** + * The string image of the token. + */ + public String image; + + /** + * A reference to the next regular (non-special) token from the input + * stream. If this is the last token from the input stream, or if the + * token manager has not read tokens beyond this one, this field is + * set to null. This is true only if this token is also a regular + * token. Otherwise, see below for a description of the contents of + * this field. + */ + public Token next; + + /** + * This field is used to access special tokens that occur prior to this + * token, but after the immediately preceding regular (non-special) token. + * If there are no such special tokens, this field is set to null. + * When there are more than one such special token, this field refers + * to the last of these special tokens, which in turn refers to the next + * previous special token through its specialToken field, and so on + * until the first special token (whose specialToken field is null). + * The next fields of special tokens refer to other special tokens that + * immediately follow it (without an intervening regular token). If there + * is no such token, this field is null. + */ + public Token specialToken; + + /** + * An optional attribute value of the Token. + * Tokens which are not used as syntactic sugar will often contain + * meaningful values that will be used later on by the compiler or + * interpreter. This attribute value is often different from the image. + * Any subclass of Token that actually wants to return a non-null value can + * override this method as appropriate. + */ + public Object getValue() { + return null; + } + + /** + * No-argument constructor + */ + public Token() {} + + /** + * Constructs a new token for the specified Image. + */ + public Token(int kind) + { + this(kind, null); + } + + /** + * Constructs a new token for the specified Image and Kind. + */ + public Token(int kind, String image) + { + this.kind = kind; + this.image = image; + } + + /** + * Returns the image. + */ + public String toString() + { + return image; + } + + /** + * Returns a new Token object, by default. However, if you want, you + * can create and return subclass objects based on the value of ofKind. + * Simply add the cases to the switch for all those special cases. + * For example, if you have a subclass of Token called IDToken that + * you want to create if ofKind is ID, simply add something like : + * + * case MyParserConstants.ID : return new IDToken(ofKind, image); + * + * to the following switch statement. Then you can cast matchedToken + * variable to the appropriate type and use sit in your lexical actions. + */ + public static Token newToken(int ofKind, String image) + { + switch(ofKind) + { + default : return new Token(ofKind, image); + } + } + +// public static Token newToken(int ofKind) +// { +// return newToken(ofKind, null); +// } + +} +/* JavaCC - OriginalChecksum=ba395bab065e7e34c9f650f2899acc2f (do not edit this line) */ diff --git a/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/TokenMgrError.java b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/TokenMgrError.java new file mode 100755 index 0000000..f5ea6d0 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/indexing/tokenizers/standard/TokenMgrError.java @@ -0,0 +1,147 @@ +/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */ +/* JavaCCOptions: */ +package it.unibz.instasearch.indexing.tokenizers.standard; + +/** Token Manager Error. */ +public class TokenMgrError extends Error +{ + + /** + * The version identifier for this Serializable class. + * Increment only if the serialized form of the + * class changes. + */ + private static final long serialVersionUID = 1L; + + /* + * Ordinals for various reasons why an Error of this type can be thrown. + */ + + /** + * Lexical error occurred. + */ + static final int LEXICAL_ERROR = 0; + + /** + * An attempt was made to create a second instance of a static token manager. + */ + static final int STATIC_LEXER_ERROR = 1; + + /** + * Tried to change to an invalid lexical state. + */ + static final int INVALID_LEXICAL_STATE = 2; + + /** + * Detected (and bailed out of) an infinite loop in the token manager. + */ + static final int LOOP_DETECTED = 3; + + /** + * Indicates the reason why the exception is thrown. It will have + * one of the above 4 values. + */ + int errorCode; + + /** + * Replaces unprintable characters by their escaped (or unicode escaped) + * equivalents in the given string + */ + protected static final String addEscapes(String str) { + StringBuffer retval = new StringBuffer(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) + { + case 0 : + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + + /** + * Returns a detailed message for the Error when it is thrown by the + * token manager to indicate a lexical error. + * Parameters : + * EOFSeen : indicates if EOF caused the lexical error + * curLexState : lexical state in which this error occurred + * errorLine : line number when the error occurred + * errorColumn : column number when the error occurred + * errorAfter : prefix that was seen before this error occurred + * curchar : the offending character + * Note: You can customize the lexical error message by modifying this method. + */ + protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { + return("Lexical error at line " + + errorLine + ", column " + + errorColumn + ". Encountered: " + + (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + + "after : \"" + addEscapes(errorAfter) + "\""); + } + + /** + * You can also modify the body of this method to customize your error messages. + * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not + * of end-users concern, so you can return something like : + * + * "Internal Error : Please file a bug report .... " + * + * from this method for such cases in the release version of your parser. + */ + public String getMessage() { + return super.getMessage(); + } + + /* + * Constructors of various flavors follow. + */ + + /** No arg constructor. */ + public TokenMgrError() { + } + + /** Constructor with message and reason. */ + public TokenMgrError(String message, int reason) { + super(message); + errorCode = reason; + } + + /** Full Constructor. */ + public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { + this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); + } +} +/* JavaCC - OriginalChecksum=9d80c9ffe6519e51fc953d9d270c83df (do not edit this line) */ diff --git a/instasearch/src/it/unibz/instasearch/jobs/CheckUpdatesJob.java b/instasearch/src/it/unibz/instasearch/jobs/CheckUpdatesJob.java new file mode 100755 index 0000000..26b9ab8 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/jobs/CheckUpdatesJob.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.jobs; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.actions.ShowExceptionAction; +import it.unibz.instasearch.ui.InstaSearchUI; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.HostConfiguration; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.methods.GetMethod; +import org.eclipse.core.net.proxy.IProxyData; +import org.eclipse.core.net.proxy.IProxyService; +import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.progress.IProgressConstants; + +/** + * A job that checks for new updates of the plugin + * + */ +public class CheckUpdatesJob extends WorkspaceJob +{ + // return code constants + public static final int UPDATE_AVAILABLE_CODE = 1; + public static final int NO_UPDATE_AVAILABLE_CODE = 2; + + private boolean updateAvailable; + + public CheckUpdatesJob() + { + super("InstaSearch Update Check"); + + setProperty(IProgressConstants.ICON_PROPERTY, + InstaSearchPlugin.getImageDescriptor("update")); + + setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE); + setProperty(IProgressConstants.KEEPONE_PROPERTY, Boolean.TRUE); + } + + @Override + public IStatus runInWorkspace(IProgressMonitor monitor) + throws CoreException + { + try + { + checkForUpdates(monitor); + + if( ! isSystem() ) + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { + public void run() { + IAction action; + + if( isUpdateAvailable() ) + action = createUpdateNotificationAction(); + else + action = createNoUpdateNotificationAction(); + + action.run(); + } + }); + + //setProperty(IProgressConstants.ACTION_PROPERTY, action); + + } catch (Exception e) { + IAction action = new ShowExceptionAction(e, "Error Checking Updates"); + setProperty(IProgressConstants.ACTION_PROPERTY, action); + + if (!isSystem()) + setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE); + + if( ! isSystem() ) { + InstaSearchPlugin.log(e); + return new Status(IStatus.ERROR, InstaSearchPlugin.getPluginId(), 0, action.getText(), e); + } + } + + int returnCode = isUpdateAvailable() ? UPDATE_AVAILABLE_CODE : NO_UPDATE_AVAILABLE_CODE; + return new Status(IStatus.OK, InstaSearchPlugin.getPluginId(), returnCode, "Done", null); + } + + private boolean checkForUpdates(IProgressMonitor monitor) throws HttpException, IOException, URISyntaxException + + { + updateAvailable = false; + + String versionCheckUrl = InstaSearchPlugin.getUpdateLocation(); + String v = InstaSearchPlugin.getVersion(); + + HttpClient httpClient = new HttpClient(); + configureProxy(httpClient, versionCheckUrl); + + GetMethod getMethod = new GetMethod(versionCheckUrl + "?v="+v); + + int statusCode = httpClient.executeMethod(getMethod); + + if (statusCode != HttpStatus.SC_OK) + return updateAvailable; + + String response = getMethod.getResponseBodyAsString(); + getMethod.releaseConnection(); + + if( "y".equals(response) ) + updateAvailable = true; + + return updateAvailable; + } + + /** + * @param httpClient + * @param versionCheckUrl + * @throws URISyntaxException + */ + private void configureProxy(HttpClient httpClient, String versionCheckUrl) throws URISyntaxException + { + IProxyService proxyService = InstaSearchPlugin.getDefault().getProxyService(); + + if (proxyService != null && proxyService.isProxiesEnabled()) { + URI uri = new URI(versionCheckUrl); + final IProxyData[] proxiesData = proxyService.select(uri); + + IProxyData proxy = null; + for(IProxyData proxyData: proxiesData) + { + if( proxyData.getType().equals(IProxyData.HTTP_PROXY_TYPE) ) + { + proxy = proxyData; + break; + } + } + + if( proxy == null ) + return; + + HostConfiguration config = httpClient.getHostConfiguration(); + config.setProxy(proxy.getHost(), proxy.getPort()); + + if( proxy.isRequiresAuthentication() ) + { + Credentials credentials = new UsernamePasswordCredentials(proxy.getUserId(), proxy.getPassword()); + AuthScope authScope = new AuthScope(proxy.getHost(), proxy.getPort()); + httpClient.getState().setProxyCredentials(authScope, credentials); + } + } + } + + private IAction createNoUpdateNotificationAction() + { + String text = "No Update Available"; + + IAction notificationAction = new Action(text) + { + public void run() + { + InstaSearchUI.showMessage("You have the latest version (" + InstaSearchPlugin.getVersion() + ")"); + setEnabled(false); + } + }; + notificationAction.setDescription(text); + notificationAction.setToolTipText(text); + + return notificationAction; + } + + /** + * Creates an action that offers to update the plugin + * @return IAction + */ + public static IAction createUpdateNotificationAction() + { + String text = "New Version Available"; + + IAction notificationAction = new Action("Update") + { + public void run() + { + /* + MessageDialogWithToggle.openYesNoQuestion(shell, "Update", + "There is a new version of InstaSearch available. Update?", + "Update automatically", true, + InstaSearchPlugin.getDefault().getPreferenceStore(), "AUTO_UPDATE"); + */ + boolean update = MessageDialog.openQuestion( + InstaSearchUI.getActiveShell(), + getDescription(), + "There is a new version available. Update?"); + + if( update ) + { + UpdatePluginJob updateJob = new UpdatePluginJob(); + updateJob.schedule(); + } + + } + }; + notificationAction.setDescription(text); + notificationAction.setToolTipText(text); + + return notificationAction; + } + + /** + * Is there an update available for this plugin + * The value is set after the job has finished + * @return UpdateAvailable + */ + public boolean isUpdateAvailable() + { + return updateAvailable; + } + + @Override + public boolean belongsTo(Object family) + { + return family == CheckUpdatesJob.class; + } + + +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/jobs/DeleteIndexJob.java b/instasearch/src/it/unibz/instasearch/jobs/DeleteIndexJob.java new file mode 100755 index 0000000..7719ad3 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/jobs/DeleteIndexJob.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.jobs; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.actions.ShowExceptionAction; +import it.unibz.instasearch.indexing.WorkspaceIndexer; +import it.unibz.instasearch.indexing.StorageIndexer; + +import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.ui.progress.IProgressConstants; + +/** + * + */ +public class DeleteIndexJob extends WorkspaceJob +{ + private StorageIndexer indexer; + + /** + * @param indexer + */ + public DeleteIndexJob(WorkspaceIndexer indexer) + { + super("Delete InstaSearch Index"); + + this.indexer = indexer; + setRule(indexer); + + setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE); + setProperty(IProgressConstants.ICON_PROPERTY, + InstaSearchPlugin.getImageDescriptor("delete")); + } + + @Override + public IStatus runInWorkspace(IProgressMonitor monitor) + throws CoreException + { + if (!isSystem()) + setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE); + + try + { + indexer.deleteIndex(); + } catch (Exception e) + { + monitor.beginTask("Exception", 1); + ShowExceptionAction action = new ShowExceptionAction(e, "Unable to delete index"); + setProperty(IProgressConstants.ACTION_PROPERTY, action); + + return Status.CANCEL_STATUS; + } + + return Status.OK_STATUS; + } + +} diff --git a/instasearch/src/it/unibz/instasearch/jobs/IndexUpdateJob.java b/instasearch/src/it/unibz/instasearch/jobs/IndexUpdateJob.java new file mode 100755 index 0000000..506c337 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/jobs/IndexUpdateJob.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.jobs; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.actions.ShowExceptionAction; +import it.unibz.instasearch.indexing.WorkspaceIndexer; +import it.unibz.instasearch.indexing.StorageIndexer.IndexChangeListener; +import it.unibz.instasearch.prefs.PreferenceConstants; +import it.unibz.instasearch.ui.InstaSearchUI; + +import java.io.File; +import java.io.IOException; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.progress.IProgressConstants; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.SynchronousBundleListener; + +/** + * Workspace job that periodically updates the index + */ +public class IndexUpdateJob extends WorkspaceJob implements SynchronousBundleListener, IResourceChangeListener, IPropertyChangeListener { + + private WorkspaceIndexer indexer; + private IndexChangeListener indexChangeListener; + + private Map changedResources = new ConcurrentHashMap(); // changed by several threads + private boolean searchViewVisible = false; + + /** + * @param indexer + * @param indexChangeListener + */ + public IndexUpdateJob(WorkspaceIndexer indexer, IndexChangeListener indexChangeListener) { + super("InstaSearch Index Update"); + this.indexer = indexer; + this.indexChangeListener = indexChangeListener; + + ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); // listen to file changes + + if( InstaSearchPlugin.getDefault() != null ) + InstaSearchPlugin.getDefault().getBundle().getBundleContext().addBundleListener(this); // listen to plugin stopping + + setRule(indexer); + + setProperty(IProgressConstants.ICON_PROPERTY, InstaSearchPlugin.getImageDescriptor("syncdb")); + setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE); + } + + public void resourceChanged(IResourceChangeEvent event) + { + if( event.getType() == IResourceChangeEvent.PRE_BUILD + || event.getType() == IResourceChangeEvent.POST_BUILD ) + return; // not change events + + try + { + if( indexer.isIndexed() ) + { + if( event.getType() == IResourceChangeEvent.POST_CHANGE ) + { + IResourceDelta delta = event.getDelta(); + + delta.accept(createResourceVisitor(), false); + } + //else if( event.getResource().getType() == IResource.PROJECT ) // CLOSE,DELETE,REFRESH events for project + //changedResources.put( event.getResource(), 0 ); + } + } catch (Exception e) { + InstaSearchPlugin.log(e); + } + } + + private IResourceDeltaVisitor createResourceVisitor() + { + return new IResourceDeltaVisitor() + { + public boolean visit(IResourceDelta delta) throws CoreException + { + IResource resource = delta.getResource(); + + if( resource.getType() == IResource.FILE ) + { + IFile file = (IFile) resource; + + if( indexer.isIndexable(file) ) { + changedResources.put( file, file.getType()); + } + + } + else if( resource.getType() == IResource.FOLDER ) { + if( delta.getFlags() == IResourceDelta.DERIVED_CHANGED ) { // we must skip derived resources + changedResources.put( resource, resource.getType() ); + } + } + + //else if(resource.getType() == IResource.PROJECT ) + // System.out.println("Project change " + resource.toString()); + + return true; + } + }; + } + + public void bundleChanged(BundleEvent event) + { + if( event.getType() == BundleEvent.STOPPING || event.getType() == BundleEvent.STOPPED ) { + ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); + this.cancel(); + + if( event.getBundle() != null && event.getBundle().getBundleContext() != null ) + event.getBundle().getBundleContext().removeBundleListener(this); + } + } + + @Override + protected void canceling() { + //ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); + } + + @Override + public IStatus runInWorkspace(IProgressMonitor monitor) + throws CoreException + { + if( InstaSearchPlugin.getDefault() == null || monitor.isCanceled() ) // no plugin (stopped) + return Status.CANCEL_STATUS; + + int indexUpdateInterval = InstaSearchPlugin.getIntPref(PreferenceConstants.P_INDEX_UPDATE_INTERVAL); + + boolean indexed = false; + + try { + indexed = indexer.isIndexed(); + } catch (IOException e1) { + InstaSearchPlugin.log(e1); + } + + if( !indexed || changedResources.isEmpty() ) { // not indexed or still indexing + schedule(indexUpdateInterval); // check later + return Status.CANCEL_STATUS; + } + + monitor.beginTask("Updating Search Index", changedResources.size()); + IStatus returnStatus = Status.OK_STATUS; + + try + { + for (Iterator iterator = changedResources.keySet().iterator(); + iterator.hasNext() && !monitor.isCanceled();) + { + IResource resource = iterator.next(); + monitor.subTask(resource.getName()); + + if( resource.getType() == IResource.FILE ) + indexer.updateFile( (IFile)resource ); + else if( resource.getType() == IResource.FOLDER ) { + indexer.updateFolder( (IFolder)resource, monitor ); + } + //else if( resource.getType() == IResource.PROJECT ) + // indexer.updateProject((IProject)resource); + + iterator.remove(); + + monitor.worked(1); + } + + indexChangeListener.onIndexUpdate(); + + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { + public void run() { + searchViewVisible = InstaSearchUI.isSearchViewVisible(); // must run in UI thread, but this job isn't + } + }); + + if( ! searchViewVisible ) { // don't optimize when might be searching + indexer.optimizeIndex(); + } + + monitor.done(); + + } catch (Exception e) { + monitor.beginTask("Exception", 1); + setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE); + setProperty(IProgressConstants.ACTION_PROPERTY, new ShowExceptionAction(e, "Error Updating Index")); + InstaSearchPlugin.log(e); + + returnStatus = Status.CANCEL_STATUS; + } + + if( ! monitor.isCanceled() ) + schedule(indexUpdateInterval); + + return returnStatus; + } + + public void propertyChange(PropertyChangeEvent event) { + String prop = event.getProperty(); + + if( PreferenceConstants.P_EXCLUDE_DIRS.equals(prop) ) + { + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + String excludedDirStr = ""; + + if( event.getOldValue() != null ) + excludedDirStr += event.getOldValue().toString() + File.pathSeparator; + + if( event.getNewValue() != null ) + excludedDirStr += event.getNewValue().toString(); + + String[] excludedDirArr = excludedDirStr.split(File.pathSeparator); + + for (String excludedDir : excludedDirArr) + { + if( excludedDir.length() == 0 ) continue; + Path path = new Path(excludedDir); + if( !root.exists(path) ) continue; + + IResource res = root.findMember(path); + if( res != null ) + changedResources.put(res, res.getType());// mark excluded as changed for re-indexing + } + } + } + +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/jobs/IndexingJob.java b/instasearch/src/it/unibz/instasearch/jobs/IndexingJob.java new file mode 100755 index 0000000..6a1a230 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/jobs/IndexingJob.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.jobs; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.actions.ShowExceptionAction; +import it.unibz.instasearch.indexing.WorkspaceIndexer; + +import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.ui.progress.IProgressConstants; + +public class IndexingJob extends WorkspaceJob { + + private WorkspaceIndexer indexer; + + public IndexingJob(WorkspaceIndexer indexer) { + super("InstaSearch Indexing"); + this.indexer = indexer; + + setRule(indexer); + + setProperty(IProgressConstants.ICON_PROPERTY, InstaSearchPlugin.getImageDescriptor("binary")); + setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE); + } + + @Override + public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException + { + try + { + indexer.createIndex(InstaSearchPlugin.getWorkspaceRoot(), monitor); + + } catch (Exception e) { + + monitor.beginTask("Exception", 1); + setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE); + setProperty(IProgressConstants.ACTION_PROPERTY, new ShowExceptionAction(e, "Error Creating Index")); + InstaSearchPlugin.log(e); + + return Status.CANCEL_STATUS; + } + + return Status.OK_STATUS; + } + +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/jobs/UpdatePluginJob.java b/instasearch/src/it/unibz/instasearch/jobs/UpdatePluginJob.java new file mode 100755 index 0000000..530d614 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/jobs/UpdatePluginJob.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.jobs; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.actions.ShowExceptionAction; + +import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.swt.widgets.Event; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.progress.IProgressConstants; + +/** + * Workspace Job that updates the plugin + */ +public class UpdatePluginJob extends WorkspaceJob +{ + + /** + * + */ + private static final String UPDATE_MANAGER_COMMAND = "org.eclipse.equinox.p2.ui.sdk.update"; + + public UpdatePluginJob() + { + super("InstaSearch Update"); + + setProperty(IProgressConstants.ICON_PROPERTY, InstaSearchPlugin.getImageDescriptor("update")); + setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE); + } + + @Override + public IStatus runInWorkspace(IProgressMonitor monitor) + throws CoreException + { + if( !isSystem() ) + setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE); + + showUpdateManager(); + + return new Status(IStatus.OK, InstaSearchPlugin.getPluginId(), 0, "Update Manager Launched", null); + } + + private void showUpdateManager() + { + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { + + public void run() + { + IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class); + + if( handlerService != null ) { + try { + handlerService.executeCommand(UPDATE_MANAGER_COMMAND, new Event()); // show software updates dialog + } catch(Exception e) { + InstaSearchPlugin.log(e); + setProperty(IProgressConstants.ACTION_PROPERTY, new ShowExceptionAction(e, "Error Launching Update Manager")); + } + } + } + }); + } + +} diff --git a/instasearch/src/it/unibz/instasearch/prefs/InstaSearchPreferencePage.java b/instasearch/src/it/unibz/instasearch/prefs/InstaSearchPreferencePage.java new file mode 100755 index 0000000..79469a8 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/prefs/InstaSearchPreferencePage.java @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.prefs; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.indexing.WorkspaceIndexer; +import it.unibz.instasearch.indexing.WorkspaceIndexerJDT; + +import java.util.Arrays; +import java.util.regex.Pattern; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.preference.BooleanFieldEditor; +import org.eclipse.jface.preference.ComboFieldEditor; +import org.eclipse.jface.preference.FieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.PathEditor; +import org.eclipse.jface.preference.StringButtonFieldEditor; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Link; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog; +import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.ui.dialogs.TypeFilteringDialog; + +public class InstaSearchPreferencePage + extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + public static final String ID = InstaSearchPreferencePage.class.getName(); + + public InstaSearchPreferencePage() { + super(GRID); + setPreferenceStore(InstaSearchPlugin.getDefault().getPreferenceStore()); + setDescription(""); + } + + /** + * Creates the field editors. Field editors are abstractions of + * the common GUI blocks needed to manipulate various types + * of preferences. Each field editor knows how to save and + * restore itself. + */ + @Override + public void createFieldEditors() { + + String[] fileValues = new String[]{"5", "10", "15", "25", "50"}; + addField(new ComboFieldEditor(PreferenceConstants.P_SHOWN_FILES_COUNT, "Shown results (initially)", getArrayOfPairs(fileValues), getFieldEditorParent())); + + String[] lineValues = new String[]{"3", "4", "5", "7", "10", "15", "25"}; + addField(new ComboFieldEditor(PreferenceConstants.P_SHOWN_LINES_COUNT, "Preview lines", getArrayOfPairs(lineValues), getFieldEditorParent())); + + addBoolField(PreferenceConstants.P_SHOW_MATCH_COUNT, "Show number of matches"); + + addBoolField(PreferenceConstants.P_SHOW_FULL_PATH, "Show full file path in results"); + + addBoolField(PreferenceConstants.P_DIALOG_ON_SHORTCUT, "Open search dialog with shortcut key (Ctrl+Alt+I)"); + + StringButtonFieldEditor extensions = new ExtensionsFieldEditor(getFieldEditorParent()); + extensions.setChangeButtonText("..."); + extensions.setEmptyStringAllowed(true); + addField(extensions); + + addBoolField(PreferenceConstants.P_INDEX_EMPTY_EXTENSION, "Index files without extension"); + + BooleanFieldEditor indexJars = new BooleanFieldEditor(PreferenceConstants.P_INDEX_ARCHIVES, "Index JAR Source Attachements (beta)", getFieldEditorParent()); + addField(indexJars); + indexJars.setEnabled(false, getFieldEditorParent()); + + if( InstaSearchPlugin.getInstaSearch() != null && InstaSearchPlugin.getInstaSearch().getIndexer() instanceof WorkspaceIndexerJDT ) + indexJars.setEnabled(true, getFieldEditorParent()); + + addBoolField(PreferenceConstants.P_FUZZY_SEARCH_AUTO, "Find similar matches when no exact matches found"); + + String version = InstaSearchPlugin.getVersion(); + addBoolField(PreferenceConstants.P_CHECK_UPDATES, "Notify about updates (ver. " + version + ")"); + + addField(new WorkspacePathEditor(PreferenceConstants.P_EXCLUDE_DIRS, "Exclude folders from index", "Select folder to exclude from indexing", getFieldEditorParent())); + //new Label(getFieldEditorParent(), SWT.NONE).setText("Note: Folders with Derived flag are excluded"); + + Link annotationsLink = new Link(getFieldEditorParent(), SWT.NONE); + annotationsLink.setText("See Annotations to set Search Results highlight color"); + annotationsLink.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) + { + PreferencesUtil.createPreferenceDialogOn(getShell(), "org.eclipse.ui.editors.preferencePages.Annotations", null, null).open(); + } + }); + } + + @Override + public boolean performOk() { + return super.performOk(); + } + + @Override + protected Control createContents(Composite parent) { + Control contents = super.createContents(parent); + + return contents; + } + + /** + * + */ + private void addBoolField(String id, String label) + { + addField(new BooleanFieldEditor(id, label, getFieldEditorParent())); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) { + } + + @Override + public void propertyChange(PropertyChangeEvent event) + { + super.propertyChange(event); + + if( event.getSource() instanceof FieldEditor ) + { + FieldEditor field = (FieldEditor)event.getSource(); + + if( PreferenceConstants.P_INDEXABLE_EXTENSIONS.equals(field.getPreferenceName()) + || PreferenceConstants.P_EXCLUDE_DIRS.equals(field.getPreferenceName()) + || PreferenceConstants.P_INDEX_EMPTY_EXTENSION.equals(field.getPreferenceName())) + setMessage("Rebuilding of index is recommended", INFORMATION); + else if( PreferenceConstants.P_INDEX_ARCHIVES.equals(field.getPreferenceName()) ) + setMessage("Rebuilding of index is required", INFORMATION); + } + } + + @Override + protected void checkState() + { + super.checkState(); + + setValid(true); + } + + private static String[][] getArrayOfPairs(String[] values) + { + String[][] pairs = new String[values.length][2]; + for(int i = 0; i < values.length; i++) { + String val = values[i]; + pairs[i] = new String[]{val, val}; + } + return pairs; + } + + private static class WorkspacePathEditor extends PathEditor + { + public WorkspacePathEditor(String name, String labelText, String dirChooserLabelText, Composite parent) + { + super(name, labelText, dirChooserLabelText, parent); + } + + @Override + protected String getNewInputObject() + { + FilteredResourcesPatternDialog dlg = new FilteredResourcesPatternDialog(getShell()); + dlg.setTitle("Exclude folders"); + dlg.setMessage("Exclude folders matching pattern (? = any character, * = any string, ** = any subfolder)"); + dlg.setInitialPattern("**/bin"); + dlg.setHelpAvailable(false); + dlg.open(); + + if( dlg.getReturnCode() == Window.OK ) + return dlg.getLastPattern(); + + return null; + }; + } + + private static class FilteredResourcesPatternDialog extends FilteredResourcesSelectionDialog + { + private String lastPattern = null; + private Pattern regexPattern; + + /** + */ + public FilteredResourcesPatternDialog(Shell shell) + { + super(shell, false, ResourcesPlugin.getWorkspace().getRoot(), IResource.FOLDER | IResource.PROJECT ); + } + + @Override + protected ItemsFilter createFilter() + { + Text patternText = (Text) getPatternControl(); + String wcPattern = patternText.getText(); + if( wcPattern.startsWith("/") ) wcPattern = wcPattern.substring(1); + + try + { + this.regexPattern = WorkspaceIndexer.wildcardToRegex(wcPattern); + + } catch(Exception t) + { + InstaSearchPlugin.log(t); + return null; // invalid pattern, no filter + } + + lastPattern = wcPattern; + + ResourceFilter filter = new ResourceFilter() + { + @Override + public boolean isSubFilter(ItemsFilter filter) + { + return false; + } + + @Override + public boolean matchItem(Object item) + { + if( !(item instanceof IResource) ) + return false; + + IResource resource = (IResource) item; + + if( resource.getType() != IResource.FOLDER + && resource.getType() != IResource.PROJECT ) + return false; + + if( resource.isDerived() ) + return false; + + String path = resource.getFullPath().toString(); + if( path.startsWith("/") ) path = path.substring(1); + + boolean matches = false; + + try + { + matches = regexPattern.matcher(path).matches(); + } catch(Exception t) + { + InstaSearchPlugin.log(t); + } + + return matches; + } + + @Override + public boolean equalsFilter(ItemsFilter iFilter) + { + return false; + } + }; + + return filter; + } + + /** + * @return the lastPattern + */ + public String getLastPattern() + { + return lastPattern; + } + } + + private static class ExtensionsFieldEditor extends StringButtonFieldEditor { + + public ExtensionsFieldEditor(Composite parent) { + super(PreferenceConstants.P_INDEXABLE_EXTENSIONS, "Extensions of files to index", parent); + } + + @Override + protected String changePressed() { + String exts = this.getStringValue(); + + TypeFilteringDialog dialog = new TypeFilteringDialog(getPage().getShell(), + Arrays.asList(exts.split(","))); + + dialog.open(); + + Object[] newSelectedTypes = dialog.getResult(); + if( newSelectedTypes == null ) + return null; + + Arrays.sort(newSelectedTypes); + + return StringUtils.join(newSelectedTypes, ","); + } + + @Override + protected void doFillIntoGrid(Composite parent, int numColumns) { + super.doFillIntoGrid(parent, numColumns); + Text txt = getTextControl(); + GridData gd = (GridData) txt.getLayoutData(); + if( gd != null ) + gd.widthHint = 250; + } + }; +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/prefs/PreferenceConstants.java b/instasearch/src/it/unibz/instasearch/prefs/PreferenceConstants.java new file mode 100755 index 0000000..e37a088 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/prefs/PreferenceConstants.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.prefs; + +/** + * Constant definitions for plug-in preferences + */ +public class PreferenceConstants +{ + // Indexing + public static final String P_INDEX_ARCHIVES = "indexArchives"; + public static final String P_INDEXABLE_EXTENSIONS = "indexableExtensions"; + public static final String P_INDEX_EMPTY_EXTENSION = "indexEmptyExtension"; + public static final String P_EXCLUDE_DIRS = "excludedFolders"; + + // Searching + public static final String P_SEARCH_EXTENSIONS = "searchExtensions"; + public static final String P_FUZZY_SEARCH_AUTO = "fuzzySearchAuto"; + public static final String P_INCREMENTAL_SEARCH = "incrementalSearch"; + + // Appearance + public static final String P_SHOW_MATCH_COUNT = "showMatchCounts"; + public static final String P_SHOW_FULL_PATH = "showFullPath"; + + public static final String P_SHOWN_FILES_COUNT = "shownFilesCount"; + public static final String P_SHOWN_LINES_COUNT = "shownLineCount"; + public static final String P_DIALOG_ON_SHORTCUT = "dialogOnShortcut"; + + // General + public static final String P_CHECK_UPDATES = "checkUpdates"; + + // Internal + public static final String P_UPDATE_CHECK_DELAY = "updateCheckDelay"; + public static final String P_TYPING_SEARCH_DELAY = "typingSearchDelay"; + public static final String P_INDEX_UPDATE_INTERVAL = "indexUpdateInterval"; +} diff --git a/instasearch/src/it/unibz/instasearch/prefs/PreferenceInitializer.java b/instasearch/src/it/unibz/instasearch/prefs/PreferenceInitializer.java new file mode 100755 index 0000000..4e6dd93 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/prefs/PreferenceInitializer.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.prefs; + +import it.unibz.instasearch.InstaSearchPlugin; + +import java.util.Arrays; +import java.util.TreeSet; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.ui.IFileEditorMapping; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.internal.registry.EditorRegistry; + +/** + * Class used to initialize default preference values. + */ +@SuppressWarnings("restriction") +public class PreferenceInitializer extends AbstractPreferenceInitializer { + + private static final String DEFAULT_EXTENSIONS = "java,xml,xsd,txt,jsp,css,c,cpp,h,hpp,mf,properties,php,php4,php5,js,inc,ini,sql,sqlj,pl,sh,bat,cmd,htm,html"; + + /** + * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() + */ + public void initializeDefaultPreferences() + { + IPreferenceStore store = InstaSearchPlugin.getDefault().getPreferenceStore(); + store.setDefault(PreferenceConstants.P_CHECK_UPDATES, true); + store.setDefault(PreferenceConstants.P_SHOW_MATCH_COUNT, true); + store.setDefault(PreferenceConstants.P_INDEX_ARCHIVES, false); + store.setDefault(PreferenceConstants.P_INDEX_EMPTY_EXTENSION, false); + store.setDefault(PreferenceConstants.P_FUZZY_SEARCH_AUTO, true); + store.setDefault(PreferenceConstants.P_SHOW_FULL_PATH, true); + store.setDefault(PreferenceConstants.P_DIALOG_ON_SHORTCUT, false); + store.setDefault(PreferenceConstants.P_INCREMENTAL_SEARCH, true); + + store.setDefault(PreferenceConstants.P_SHOWN_FILES_COUNT, 25); + store.setDefault(PreferenceConstants.P_SHOWN_LINES_COUNT, 4); + + store.setDefault(PreferenceConstants.P_UPDATE_CHECK_DELAY, 10000); + store.setDefault(PreferenceConstants.P_TYPING_SEARCH_DELAY, 200); + store.setDefault(PreferenceConstants.P_INDEX_UPDATE_INTERVAL, 60000); + + String extensions = getIndexableExtensions(); + store.setDefault(PreferenceConstants.P_INDEXABLE_EXTENSIONS, extensions); + store.setDefault(PreferenceConstants.P_SEARCH_EXTENSIONS, ""); + store.setDefault(PreferenceConstants.P_EXCLUDE_DIRS, ""); + } + + /** + * Get extensions that Eclipse knows of and the default ones + * @return comma separated string of extensions + */ + public static String getIndexableExtensions() + { + String defaultExtArray[] = DEFAULT_EXTENSIONS.split(","); + + TreeSet extensions = new TreeSet(String.CASE_INSENSITIVE_ORDER); + extensions.addAll(Arrays.asList(defaultExtArray)); + + IFileEditorMapping[] allMappings = ((EditorRegistry)PlatformUI.getWorkbench() + .getEditorRegistry()).getUnifiedMappings(); + + IContentType text = Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT); + + for (int i = 0; i < allMappings.length; i++) { + if (allMappings[i].getName().equals("*")) { + String ext = allMappings[i].getExtension(); + IContentType type = Platform.getContentTypeManager().findContentTypeFor("." + ext); + + if( type != null && type.isKindOf(text)) + extensions.add( ext ); + } + } + + IContentType[] types = Platform.getContentTypeManager().getAllContentTypes(); + for(IContentType type: types) { + if( type.isKindOf(text)) { + String exts[] = type.getFileSpecs(IContentType.FILE_EXTENSION_SPEC); + extensions.addAll(Arrays.asList(exts)); + } + } + + return StringUtils.join(extensions.toArray(), ","); + } + +} diff --git a/instasearch/src/it/unibz/instasearch/ui/DropdownMenuProvider.java b/instasearch/src/it/unibz/instasearch/ui/DropdownMenuProvider.java new file mode 100755 index 0000000..17e60b3 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/DropdownMenuProvider.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.ToolItem; + +/** + * This class provides the "drop down" functionality for our dropdown tool items. + */ +class DropdownMenuProvider extends SelectionAdapter +{ + private MenuManager menuManager; + private ToolItem toolItem; + + /** + * Constructs a DropdownMenuProvider + * + * @param toolItem the dropdown this listener belongs to + */ + public DropdownMenuProvider(ToolItem toolItem) { + + toolItem.addSelectionListener(this); + this.menuManager = new MenuManager(); + this.toolItem = toolItem; + } + + /** + * @return the toolItem + */ + public ToolItem getToolItem() { + return toolItem; + } + + public T add(T action) + { + menuManager.add(action); + + return action; + } + + public void addSeparator() + { + menuManager.add(new Separator()); + } + + /** + * Called when either the button itself or the dropdown arrow is clicked + * + * @param event the event that trigged this call + */ + @Override + public void widgetSelected(SelectionEvent event) { + ToolItem item = (ToolItem) event.widget; + + if( item != toolItem ) + return; + + Rectangle rect = item.getBounds(); + Point pt = item.getParent().toDisplay(new Point(rect.x, rect.y)); + Menu menu = menuManager.createContextMenu(item.getParent()); + menu.setLocation(pt.x, pt.y + rect.height); + menu.setVisible(true); + + if (event.detail != SWT.ARROW) { + // They pushed the button; take appropriate action + //System.out.println("button pushed"); + } + } +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/ui/InstaSearchPage.java b/instasearch/src/it/unibz/instasearch/ui/InstaSearchPage.java new file mode 100755 index 0000000..2fb6bfd --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/InstaSearchPage.java @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.indexing.Field; +import it.unibz.instasearch.indexing.WorkspaceIndexerJDT; +import it.unibz.instasearch.indexing.SearchQuery; +import it.unibz.instasearch.prefs.PreferenceConstants; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeSet; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.dialogs.DialogPage; +import org.eclipse.jface.preference.StringButtonFieldEditor; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.search.ui.ISearchPage; +import org.eclipse.search.ui.ISearchPageContainer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Link; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.dialogs.TypeFilteringDialog; + +public class InstaSearchPage extends DialogPage implements ISearchPage +{ + public static final String ID = "it.unibz.instasearch.ui.InstaSearchPage"; + /** + * + */ + private ISearchPageContainer container; + private Text searchText; + private Button similarSearch; + private StringButtonFieldEditor extensionEditor; + //private Button jarSearch; + + public boolean performAction() + { + HashMap> filter = new HashMap>(); + + if( container.getSelectedScope() == ISearchPageContainer.SELECTED_PROJECTS_SCOPE + && container.getSelectedProjectNames().length != 0 ) // projects + { + TreeSet selectedProjects = new TreeSet(); + Collections.addAll(selectedProjects, container.getSelectedProjectNames()); + filter.put(Field.PROJ, selectedProjects); + + } else if( container.getSelectedScope() == ISearchPageContainer.WORKING_SET_SCOPE + && container.getSelectedWorkingSets().length != 0 ) { // working sets + + filter.put(Field.WS, getWorkingSetSearchString()); + + } else if( container.getSelectedScope() == ISearchPageContainer.SELECTION_SCOPE + && !container.getSelection().isEmpty() ) + { + getSelectedResources(filter); + } + + filter.put(Field.EXT, getSelectedExtensions()); + extensionEditor.store(); + + String searchString = searchText.getText(); + + InstaSearchView searchView = InstaSearchUI.showSearchView(); + + if( searchView != null ) { + int maxResults = SearchQuery.UNLIMITED_RESULTS; + searchString += convertFilterToString(filter); + SearchQuery searchQuery = new SearchQuery(searchString, maxResults); + searchQuery.setExact( similarSearch.getSelection() ); + searchQuery.setFilter(null); // put filters in search string instead + + searchView.setSearchString(searchString); // to display + searchView.search(searchQuery, false); + } + + return true; + } + + private void getSelectedResources(HashMap> filter) + { + if( container.getSelection() instanceof IStructuredSelection ) { + + IStructuredSelection sel = (IStructuredSelection) container.getSelection(); + + for(Object elem: sel.toArray()) + { + if( elem instanceof IAdaptable ) { + + IResource res = null; + + if( elem instanceof IResource) + res = (IResource) elem; + else { + IAdaptable adaptable = (IAdaptable) elem; + res = (IResource) adaptable.getAdapter(IResource.class); + } + + if( res == null ) continue; + + switch(res.getType()) + { + case IResource.PROJECT: + Set projects = filter.containsKey(Field.PROJ)?filter.get(Field.PROJ):new TreeSet(); + projects.add( ((IProject)res).getName() ); + filter.put(Field.PROJ, projects); + break; + case IResource.FILE: + Set files = filter.containsKey(Field.FILE)?filter.get(Field.FILE):new TreeSet(); + files.add( ((IFile)res).getFullPath().toString() ); + filter.put(Field.FILE, files); + break; + case IResource.FOLDER: + Set folders = filter.containsKey(Field.DIR)?filter.get(Field.DIR):new TreeSet(); + folders.add( res.getFullPath().toString() ); + filter.put(Field.DIR, folders); + break; + } + + } + } + } + } + + /** + * @param filter + * @return + */ + private static String convertFilterToString(HashMap> filter) { + + String filterString = ""; + + for(Entry> entry: filter.entrySet()) { + + String fieldFilterString = getFieldFilterString(entry.getKey(), entry.getValue()); + + if( !"".equals(fieldFilterString) ) + filterString += " " + fieldFilterString; + } + + return filterString; + } + + private Set getSelectedExtensions() { + + TreeSet extSet = new TreeSet(); + + String exts = extensionEditor.getStringValue(); + + if( exts != null && ! "".equals(exts) && ! "*".equals(exts)) { + exts = exts.replace(" ", ""); + exts = exts.replace("*.", ""); + Collections.addAll(extSet, exts.split(",")); + } + + return extSet; + } + + private Set getWorkingSetSearchString() { + + Set wsNames = new TreeSet(); + + for(IWorkingSet ws: container.getSelectedWorkingSets()) { + String workingSet = ws.getName(); + wsNames.add(workingSet); + } + + return wsNames; + } + + private static String getFieldFilterString(Field field, Set values) + { + String filterString = null; + + if( values.size() == 0 ) + return ""; + + for (String val : values) { + if( filterString == null ) filterString = ""; + else filterString += ","; + filterString += val; + } + + if( filterString.contains(" ") ) + filterString = '"' + filterString + '"'; + + return field.toString() + ':' + filterString; + } + + + + public void setContainer(ISearchPageContainer container) + { + this.container = container; + } + + public void createControl(Composite parent) + { + Composite pageComposite = new Composite(parent, SWT.FILL); + + GridLayout pageLayout = new GridLayout(); + pageLayout.numColumns = 1; + + pageComposite.setLayout(pageLayout); + pageComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true,false,1,1)); + + Label label = new Label(pageComposite, SWT.LEFT); + label.setText("Search:"); + label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false,false,1,1)); + + searchText = new Text(pageComposite, SWT.SINGLE | SWT.BORDER | SWT.FILL); + searchText.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,false,1,1)); + + if (container.getSelection() instanceof TextSelection) { + String selection = ((TextSelection) container.getSelection()).getText(); + searchText.setText(selection); + } + + createShowViewLink(pageComposite); + + similarSearch = new Button(pageComposite, SWT.CHECK); + similarSearch.setText("Find similar matches"); + similarSearch.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,false,1,1)); + + if( InstaSearchPlugin.getInstaSearch() != null && InstaSearchPlugin.getInstaSearch().getIndexer() instanceof WorkspaceIndexerJDT ) + { +// jarSearch = new Button(pageComposite, SWT.CHECK); +// jarSearch.setText("Exclude JAR files"); +// jarSearch.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,false,1,1)); + } + + createExtensionEditor(pageComposite); + + + setControl( searchText ); + } + + private void createExtensionEditor(Composite pageComposite) { + + GridLayout pageLayout = new GridLayout(); + pageLayout.numColumns = 1; + pageLayout.marginWidth = 1; + + Composite labelComposite = new Composite(pageComposite, SWT.FILL); + labelComposite.setLayout(pageLayout); + Label label = new Label(labelComposite, SWT.NONE ); + label.setText("File types:"); + labelComposite.setLayoutData(new GridData(GridData.BEGINNING,GridData.CENTER,true,false,1,1)); + + Composite extensionsComposite = new Composite(pageComposite, SWT.FILL); + extensionsComposite.setLayout(pageLayout); + extensionsComposite.setLayoutData(new GridData(GridData.FILL,GridData.CENTER,true,false,2,1)); + + extensionEditor = new StringButtonFieldEditor(PreferenceConstants.P_SEARCH_EXTENSIONS, "", extensionsComposite) { + protected String changePressed() { + String exts = this.getStringValue(); + exts = exts.replace(" ", ""); + + List extList = Arrays.asList(exts.split(",")); + TypeFilteringDialog dialog = new TypeFilteringDialog(getShell(), extList); + dialog.open(); + + Object[] newSelectedTypes = dialog.getResult(); + + return StringUtils.join(newSelectedTypes, ","); + } + + }; + extensionEditor.setChangeButtonText("Choose..."); + extensionEditor.setEmptyStringAllowed(true); + extensionEditor.setPreferenceStore(InstaSearchPlugin.getDefault().getPreferenceStore()); + extensionEditor.load(); + + Text txt = extensionEditor.getTextControl(extensionsComposite); + txt.setToolTipText("E.g:\njava, xml"); + } + + private void createShowViewLink(Composite pageComposite) + { + Composite linkComposite = new Composite(pageComposite, SWT.FILL); + GridLayout pageLayout = new GridLayout(); + pageLayout.numColumns = 2; + pageLayout.marginWidth = 1; + + linkComposite.setLayout(pageLayout); + linkComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false,1,1)); + + Link openViewLink = new Link(linkComposite, SWT.NONE); + openViewLink.setText("You can search directly from the search view"); + openViewLink.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + InstaSearchUI.showSearchView(); + } + }); + openViewLink.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false,false,1,1)); + } + + @Override + public void setVisible(boolean visible) + { + super.setVisible(visible); + searchText.setFocus(); + container.setPerformActionEnabled(true); + } + + +} diff --git a/instasearch/src/it/unibz/instasearch/ui/InstaSearchUI.java b/instasearch/src/it/unibz/instasearch/ui/InstaSearchUI.java new file mode 100755 index 0000000..a72bfd4 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/InstaSearchUI.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import it.unibz.instasearch.InstaSearchPlugin; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; + +/** + * Contains UI helper methods + */ +public class InstaSearchUI +{ + + public static Shell getActiveShell() { + if( PlatformUI.getWorkbench().getDisplay() != null ) + return PlatformUI.getWorkbench().getDisplay().getActiveShell(); + + return null; + } + + public static void showMessage(String message) { + + MessageDialog.openInformation( + getActiveShell(), + InstaSearchPlugin.getPluginName(), + message); + } + + public static void showError(Exception ex) { + String message = ex.getMessage(); + + if( message == null || "".equals(message) ) + message = ex.getClass().getName(); + + showError(ex, message); + } + + public static void showError(Throwable exception, String message) { + Status status = new Status(IStatus.ERROR, InstaSearchPlugin.getPluginId(), message, exception); + + showError(status, message); + } + + public static void showError(IStatus status, String message) { + + //status.getException().printStackTrace(); + + ReportErrorDialog.openReportError(getActiveShell(), InstaSearchPlugin.getPluginName(), message, status); + + InstaSearchPlugin.log(status); + } + + /** + * Opens and shows the search view + * Note: This method must be run from the UI thread + * @return InstaSearchView + */ + public static InstaSearchView showSearchView() + { + IWorkbenchWindow win = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + + if( win != null && win.getActivePage() != null ) + { + IViewPart view = null; + + try { + view = win.getActivePage().showView(InstaSearchView.ID); + } catch(PartInitException e) { + InstaSearchPlugin.log(e); + return null; + } + + if( view == null ) + return null; + + if( view instanceof InstaSearchView ) + return (InstaSearchView)view; + } + + return null; + } + + /** + * Checks weather the search view is visible + * Note: This method must be run from the UI thread + * @return InstaSearchView + */ + public static boolean isSearchViewVisible() + { + IWorkbenchWindow win = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + + if( win != null && win.getActivePage() != null ) + { + IViewPart view = win.getActivePage().findView(InstaSearchView.ID); + + return win.getActivePage().isPartVisible(view); + } + + return false; + } + + public static void showHomePage() throws MalformedURLException, PartInitException { + URL homePageUrl = new URL(InstaSearchPlugin.getHomePageLocation()); + PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser().openURL(homePageUrl); + } + + public static IWorkbenchWindow getWorkbenchWindow() { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + } + + public static String getActiveProject() { + + IEditorPart editor = getActiveEditor(); + + if( editor == null ) + return null; + + IAdaptable adaptable = editor.getEditorInput(); + + IProject project = (IProject) adaptable.getAdapter(IProject.class); + + if (project == null) { + IResource resource = (IResource) adaptable.getAdapter(IResource.class); + + if (resource != null) + project = resource.getProject(); + } + + if (project != null && project.isAccessible()) + return project.getName(); + + return null; + } + + /** + * Gets active editor + * Must be run from UI thread + * + * @return IEditorPart + */ + public static IEditorPart getActiveEditor() { + if( getWorkbenchWindow() == null ) + return null; + + IWorkbenchPage activePage= getWorkbenchWindow().getActivePage(); + if (activePage != null) { + IEditorPart activeEditor= activePage.getActiveEditor(); + return activeEditor; + } + + return null; + } + + public static Image getSharedImage(String img) { + return PlatformUI.getWorkbench().getSharedImages().getImage(img); + } +} diff --git a/instasearch/src/it/unibz/instasearch/ui/InstaSearchView.java b/instasearch/src/it/unibz/instasearch/ui/InstaSearchView.java new file mode 100755 index 0000000..d687472 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/InstaSearchView.java @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.actions.CheckUpdatesActionDelegate; +import it.unibz.instasearch.actions.ShowExceptionAction; +import it.unibz.instasearch.indexing.Field; +import it.unibz.instasearch.indexing.SearchQuery; +import it.unibz.instasearch.indexing.SearchResultDoc; +import it.unibz.instasearch.jobs.CheckUpdatesJob; +import it.unibz.instasearch.prefs.PreferenceConstants; +import it.unibz.instasearch.ui.ResultContentProvider.MatchLine; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import org.eclipse.core.runtime.ILogListener; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IContributionItem; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.text.IFindReplaceTarget; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider; +import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeViewerListener; +import org.eclipse.jface.viewers.TreeExpansionEvent; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerCell; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseTrackAdapter; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.part.ViewPart; + +/** + * + */ +public class InstaSearchView extends ViewPart implements ModifyListener, ILogListener, ITreeViewerListener, IPropertyChangeListener { + + /** The view ID */ + public static final String ID = InstaSearchView.class.getName(); // we have just one view + + /** Tree for results */ + private TreeViewer resultViewer; + /** Textbox for search query */ + private StyledText searchText; + + private IAction openAction; + private SearchJob searchJob; + private ExpandCollapseJob expandCollapseJob; + + private ResultContentProvider contentProvider; + private int lastIncrementalSearchPos = 0; + + // preferences + private int maxResults; + private int typingSearchDelay; + private boolean incrementalSearchEnabled; + + private SearchViewControl searchViewControl; + + /** + * + */ + public InstaSearchView() { + } + + @Override + public void init(IViewSite site) throws PartInitException + { + super.init(site); + + scheduleUpdateCheck(); // schedule update check if view is opened + + InstaSearchPlugin.getDefault().getLog().addLogListener(this); // listen for exceptions + + initPrefs(); + + InstaSearchPlugin.addPreferenceChangeListener(this); + } + + private void initPrefs() { + typingSearchDelay = InstaSearchPlugin.getIntPref(PreferenceConstants.P_TYPING_SEARCH_DELAY); + maxResults = InstaSearchPlugin.getIntPref(PreferenceConstants.P_SHOWN_FILES_COUNT); + incrementalSearchEnabled = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_INCREMENTAL_SEARCH); + } + + @Override + public void createPartControl(Composite parent) { + + this.searchViewControl = new SearchViewControl(parent, this); + + searchText = searchViewControl.getSearchText(); + resultViewer = searchViewControl.getResultViewer(); + + searchText.addModifyListener(this); + + contentProvider = new ResultContentProvider(); + IStyledLabelProvider labelProvider = new ResultLabelProvider(contentProvider); + IBaseLabelProvider decoratedLabelProvider = new DecoratingStyledCellLabelProvider(labelProvider, null, null); + + configureResultViewer(contentProvider, decoratedLabelProvider); + searchViewControl.setContentProposalAdapter(new SearchContentProposalProvider(contentProvider)); + + searchJob = new SearchJob(this); + expandCollapseJob = new ExpandCollapseJob(); + + makeActions(); + hookContextMenu(); + hookDoubleClickAction(); + } + + public void modifyText(ModifyEvent e) + { + searchJob.cancel(); + + StyleRange[] styleRanges = createStyledSearchString(searchText.getText()); + searchText.setStyleRanges(styleRanges); + + if( searchViewControl.isShowingSearchTip() ) return; // showing search tip + + searchJob.schedule(getSearchQuery(), false, typingSearchDelay); // start with a delay since user might still be typing + + if( incrementalSearchEnabled ) + doIncrementalSearch(); + } + + private void doIncrementalSearch() + { + IEditorPart editor = InstaSearchUI.getActiveEditor(); + + if( editor != null ) + { + IFindReplaceTarget target = (IFindReplaceTarget) editor.getAdapter(IFindReplaceTarget.class); + + if( target != null ) + lastIncrementalSearchPos = target.findAndSelect(lastIncrementalSearchPos, searchText.getText(), true, false, false) + searchText.getText().length(); + } + } + + /** + * Highlight fields + * + * @param text + * @return bold ranges + */ + private static StyleRange[] createStyledSearchString(String text) + { + //TODO: use parser + ArrayList styleRanges = new ArrayList(); + String lcaseText = text.toLowerCase(); + + ArrayList fieldsToHighlight = new ArrayList(Field.values().length); + for(Field field: Field.values()) // add all field names + fieldsToHighlight.add(field.toString()); + + for(String fieldName: fieldsToHighlight) + { + int pos = lcaseText.indexOf(fieldName + ':'); // should use a parser here + + while( pos != -1 ) { + styleRanges.add(new StyleRange(pos, fieldName.length(), null, null, SWT.BOLD)); + pos = lcaseText.indexOf(fieldName + ':', pos+fieldName.length()-1); // find next + } + } + + // ranges must be sorted by start position + Collections.sort(styleRanges, new Comparator() { + public int compare(StyleRange sr1, StyleRange sr2) { + return sr1.start - sr2.start; + } + }); + + //TODO: highlight AND, OR + return styleRanges.toArray(new StyleRange[styleRanges.size()]); + } + + void setSearchString(String searchString) + { + searchText.setText(searchString); + } + + /** + * Starts the search by giving search string as input to the viewer + * + * @param searchQuery + * @param selectLast whether to select the item which is currently last + */ + void search(SearchQuery searchQuery, boolean selectLast) { + searchJob.cancel(); // cancel previous search + searchQuery.setFilter( searchViewControl.getFilter() ); + searchJob.schedule(searchQuery, selectLast, 0); + } + + private SearchQuery getSearchQuery() + { + SearchQuery sq = new SearchQuery(getSearchText(), maxResults ); + sq.setFilter( searchViewControl.getFilter() ); + return sq; + } + + String getSearchText() { + return searchText.getText().trim(); + } + + TreeViewer getResultViewer() { + return resultViewer; + } + + public void treeExpanded(TreeExpansionEvent event) { + + if( event.getElement() instanceof SearchQuery ) { + search((SearchQuery)event.getElement(), true); + } + } + + public void treeCollapsed(TreeExpansionEvent event) { + } + + private void configureResultViewer(ResultContentProvider contentProvider, IBaseLabelProvider decoratedLabelProvider) { + + resultViewer.setContentProvider(contentProvider); + resultViewer.setLabelProvider(decoratedLabelProvider); + resultViewer.setSorter(null); + + getViewSite().setSelectionProvider(resultViewer); + resultViewer.addTreeListener(this); + + resultViewer.getControl().addMouseTrackListener(new MouseTrackAdapter() + { + public void mouseHover(MouseEvent e) + { + ViewerCell cell = resultViewer.getCell(new Point(e.x, e.y)); + + if( cell != null && cell.getElement() instanceof SearchResultDoc ) + { + SearchResultDoc doc = (SearchResultDoc) cell.getElement(); + resultViewer.getTree().setToolTipText(doc.getFilePath()); + } + else + { + resultViewer.getTree().setToolTipText(""); + } + } + }); + + KeyAdapter keyListener = new KeyAdapter() + { + public void keyReleased(KeyEvent e) + { + onSearchTextKeyPress(e); + } + }; + + resultViewer.getControl().addKeyListener(keyListener); + searchText.addKeyListener(keyListener); + } + + private void hookContextMenu() + { + MenuManager menuMgr = new MenuManager("#PopupMenu"); + + menuMgr.setRemoveAllWhenShown(true); + menuMgr.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + fillContextMenu(manager); + } + }); + + Menu menu = menuMgr.createContextMenu(resultViewer.getControl()); + resultViewer.getControl().setMenu(menu); + getSite().registerContextMenu(menuMgr, resultViewer); + } + + private void onSearchTextKeyPress(KeyEvent e) + { + if( e.keyCode == SWT.F5 ) + { + refreshSearch(); + } + if( e.keyCode == SWT.DEL ) + { + deleteSelectedMatch(); + } + if( e.keyCode == (int)'j' && (e.stateMask & SWT.CTRL)!=0 ) + { + doIncrementalSearch(); + } + else if( e.keyCode == SWT.TAB ) + { + resultViewer.getTree().setFocus(); + } + else if( e.keyCode == SWT.ESC ) + { + if( expandCollapseJob.getState() == Job.RUNNING ) + { + expandCollapseJob.cancel(); + } + else + { + if( searchText.getSelectionText().equals(searchText.getText()) ) + { + searchText.setText(""); + } + else + { + searchText.setFocus(); + searchText.selectAll(); + } + } + } + else if( e.getSource() == searchText && e.keyCode == SWT.CR && (e.stateMask & SWT.CTRL)!=0 ) + { + showAllResults(); + } + } + + private void fillContextMenu(IMenuManager manager) + { + boolean haveSelection = ! resultViewer.getSelection().isEmpty(); + SearchQuery sq = (SearchQuery) resultViewer.getInput(); + + openAction.setEnabled( haveSelection ); + manager.add(openAction); + + boolean showingItems = resultViewer.getTree().getItemCount() > 0; + + Action expandAll = new Action("Expand All", InstaSearchPlugin.getImageDescriptor("expandall")) { + public void run() { + expandAll(); + } + }; + expandAll.setEnabled( showingItems ); + manager.add(expandAll); + + Action collapseAll = new Action("Collapse All", InstaSearchPlugin.getImageDescriptor("collapseall")) { + public void run() { + collapseAll(); + } + }; + collapseAll.setEnabled( showingItems ); + manager.add(collapseAll); + + Action refresh = new Action("Refresh") { + public void run() { + refreshSearch(); + } + }; + refresh.setAccelerator(SWT.F5); + manager.add(refresh); + + Action delete = new Action("Delete Match") { + public void run() { + deleteSelectedMatch(); + } + }; + delete.setAccelerator(SWT.DEL); + manager.add(delete); + + Action moreResults = new Action("More Results...") { + public void run() { + showAllResults(); + } + }; + moreResults.setEnabled( showingItems ); + manager.add(moreResults); + + if( sq == null || !sq.isLimited() ) + moreResults.setEnabled(false); + + } + + + private void deleteSelectedMatch() { + if( getResultViewer().getSelection() == null ) + return; + IStructuredSelection selection = (IStructuredSelection)resultViewer.getSelection(); + getResultViewer().remove(selection.toArray()); + } + + /** + * + */ + public void showAllResults() { + SearchQuery sq = (SearchQuery)resultViewer.getInput(); + SearchQuery newSq = new SearchQuery(sq); + newSq.setMaxResults(SearchQuery.UNLIMITED_RESULTS); + search(newSq, false); + } + + /** + * + */ + public void expandAll() { + expandCollapseJob.schedule(true); + } + + /** + * + */ + public void collapseAll() { + expandCollapseJob.schedule(false); + } + + private void openSelection() throws Exception { + IStructuredSelection selection = (IStructuredSelection)resultViewer.getSelection(); + Object obj = selection.getFirstElement(); + + SearchResultDoc doc = null; + MatchLine selectedLineMatches = null; + + if(obj instanceof SearchResultDoc) { + doc = (SearchResultDoc) obj; + } else if(obj instanceof MatchLine) { + selectedLineMatches = (MatchLine) obj; + doc = selectedLineMatches.getResultDoc(); + } else if(obj instanceof Exception) { + InstaSearchUI.showError((Exception)obj); + return; + } else if(obj instanceof SearchQuery ) { + search( (SearchQuery) obj, true ); + return; + } else + return; + + + new MatchHighlightJob(doc, selectedLineMatches, contentProvider, searchJob, getSite().getPage()).schedule(); + } + + + + private void hookDoubleClickAction() { + resultViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + openAction.run(); + } + }); + } + + public void setFocus() { + searchText.setFocus(); + //searchText.selectAll(); + } + + private void makeActions() { + openAction = new Action("Open") { + public void run() { + try { + openSelection(); + } catch (Exception e) { + InstaSearchPlugin.log(e); + } + } + }; + } + + private void scheduleUpdateCheck() + { + boolean checkUpdates = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_CHECK_UPDATES); + if( !checkUpdates ) + return; + + CheckUpdatesJob checkUpdatesJob = new CheckUpdatesJob(); + checkUpdatesJob.setSystem(true); + checkUpdatesJob.addJobChangeListener(new UpdateJobChangeListener()); + checkUpdatesJob.schedule(InstaSearchPlugin.getIntPref(PreferenceConstants.P_UPDATE_CHECK_DELAY)); + } + + + /** + * Logging an error in the plugin + * Create an action that allows reporting it + */ + public void logging(IStatus status, String plugin) + { + IMenuManager menuManager = getViewSite().getActionBars().getMenuManager(); + + IContributionItem item = menuManager.find(ShowExceptionAction.ID); + + if( item != null ) + menuManager.remove(item); + + ShowExceptionAction action = new ShowExceptionAction(status); + action.setText("Report Bug"); + + menuManager.add(action); + } + + @Override + public void dispose() + { + super.dispose(); + + if( InstaSearchPlugin.getDefault() != null ) + { + InstaSearchPlugin.getDefault().getLog().removeLogListener(this); + InstaSearchPlugin.removePreferenceChangeListener(this); + } + } + + private void refreshSearch() + { + InstaSearchPlugin.getInstaSearch().updateIndex(); + + SearchQuery input = (SearchQuery) resultViewer.getInput(); + if( input == null ) return; + resultViewer.setInput(null); // clear cached search results + + searchJob.cancel(); + searchJob.schedule(input, false, typingSearchDelay); + } + + public void propertyChange(PropertyChangeEvent event) + { + typingSearchDelay = InstaSearchPlugin.getIntPref(PreferenceConstants.P_TYPING_SEARCH_DELAY); + maxResults = InstaSearchPlugin.getIntPref(PreferenceConstants.P_SHOWN_FILES_COUNT); + incrementalSearchEnabled = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_INCREMENTAL_SEARCH); + } + + /** + * Waits for {@link CheckUpdatesJob} to finish and notifies if update is available + * by placing an Update button in the view's toolbar + */ + private class UpdateJobChangeListener extends JobChangeAdapter { + + public void done(IJobChangeEvent event) + { + IStatus status = event.getResult(); + + if( status.getSeverity() == IStatus.OK ) + { + boolean updateAvailable = (status.getCode() == CheckUpdatesJob.UPDATE_AVAILABLE_CODE); + if( updateAvailable ) + { + getViewSite().getShell().getDisplay().asyncExec(new Runnable() { + public void run() + { + addUpdateAction(); + setTitleToolTip("New version available"); + getViewSite().getActionBars().getStatusLineManager().setMessage(getTitleImage(), "New version available"); + } + }); + } + + + } + } + + private void addUpdateAction() { + IAction updateAction = CheckUpdatesJob.createUpdateNotificationAction(); + updateAction.setImageDescriptor( InstaSearchPlugin.getImageDescriptor("lightbulb") ); + + IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager(); + mgr.add(updateAction); + mgr.update(true); + + IMenuManager menuMgr = getViewSite().getActionBars().getMenuManager(); + + menuMgr.add(updateAction); + + IContributionItem checkUpdatesItem = mgr.find(CheckUpdatesActionDelegate.ID); + if( checkUpdatesItem != null ) + checkUpdatesItem.setVisible(false); // hide Check for Updates action + } + } + + /** + * Background job that expands/collapses all entries + */ + private class ExpandCollapseJob extends Job implements ISchedulingRule { + + /** + */ + public ExpandCollapseJob() { + super("Expand All"); + + setRule(this); + //setUser(true); + + // listen to searchJob changes. stop expanding on new search + searchJob.addJobChangeListener(new JobChangeAdapter() { + public void scheduled(IJobChangeEvent event) { + cancel(); // new search + } + public void done(IJobChangeEvent event) { + cancel(); // canceled search + } + }); + + } + + public void schedule(boolean expandAll) { + + this.cancel(); + + if( !expandAll ) { + resultViewer.collapseAll(); + return; + } + + if( resultViewer.getTree().getItemCount() == 0 ) { + return; + } + + this.schedule(); + } + + protected IStatus run(IProgressMonitor monitor) { + + Display display = getViewSite().getShell().getDisplay(); + + Object[] elements = contentProvider.getElements(); + monitor.beginTask("InstaSearch Expanding", elements.length); + + for(int i = 0; i < elements.length && !monitor.isCanceled(); i++) { + final Object curDoc = elements[i]; + if( curDoc == null ) continue; + if( !(curDoc instanceof SearchResultDoc) ) continue; + + contentProvider.getChildren(curDoc); // get lines from file (they become cached) + + Runnable expander = new Runnable() { + public void run() { + resultViewer.setExpandedState(curDoc, true); + } + }; + display.syncExec(expander); // expand in UI thread + + monitor.worked(1); + } + + monitor.done(); + + return Status.OK_STATUS; + } + + public boolean contains(ISchedulingRule rule) { + return rule.getClass() == this.getClass(); + } + + public boolean isConflicting(ISchedulingRule rule) { + return rule.getClass() == this.getClass(); + } + + } + +} diff --git a/instasearch/src/it/unibz/instasearch/ui/MatchHighlightJob.java b/instasearch/src/it/unibz/instasearch/ui/MatchHighlightJob.java new file mode 100755 index 0000000..d442ea4 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/MatchHighlightJob.java @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.indexing.SearchResultDoc; +import it.unibz.instasearch.ui.ResultContentProvider.MatchLine; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.search.ui.NewSearchUI; +import org.eclipse.search.ui.text.Match; +import org.eclipse.ui.IEditorDescriptor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IPartListener; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.part.MultiPageEditorPart; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.MarkerUtilities; + +class MatchHighlightJob extends Job implements ISchedulingRule, IPartListener +{ + private SearchResultDoc doc; + private MatchLine selectedLineMatches; + private ResultContentProvider contentProvider; + private ITextEditor editor; + private Job searchJob; + private IDocument document; + private IWorkbenchPage workbenchPage; + private IFile file; + + /** + * @param doc + * @param selectedLineMatches + * @param contentProvider + * @param workbenchPage + * @throws Exception + */ + public MatchHighlightJob(SearchResultDoc doc, MatchLine selectedLineMatches, ResultContentProvider contentProvider, Job searchJob, IWorkbenchPage workbenchPage) throws Exception + { + super("Highlight Matches"); + + this.doc = doc; + this.selectedLineMatches = selectedLineMatches; + this.contentProvider = contentProvider; + this.searchJob = searchJob; + this.workbenchPage = workbenchPage; + + IEditorInput input = contentProvider.getEditorInput(doc); + IEditorDescriptor editorDesc = IDE.getEditorDescriptor(doc.getFileName()); + + IEditorPart editorPart = IDE.openEditor(workbenchPage, input, editorDesc.getId()); + this.editor = getTextEditor(input, editorPart); + this.document = editor.getDocumentProvider().getDocument(editor.getEditorInput()); + + IStorage storage = contentProvider.getStorage(doc); + this.file = null; + if( storage instanceof IFile ) + file = (IFile) storage; + } + + @Override + protected IStatus run(IProgressMonitor monitor) + { + try { + if( editor != null ) + { + workbenchPage.addPartListener(this); + + findAndHighlightMatches(doc, monitor); + } + } catch (Exception e) { + InstaSearchPlugin.log(e); + } finally { + workbenchPage.removePartListener(this); + } + + return Status.OK_STATUS; + } + + private void findAndHighlightMatches(SearchResultDoc doc, final IProgressMonitor monitor) + throws Exception, BadLocationException, CoreException + { + if( file != null ) + { + deleteMarkers(); + addMarkerRemover(file); + } + + MatchHighliter highlighter = new MatchHighliter(monitor); + + if( selectedLineMatches != null ) + highlighter.highlightMatchLine(file, selectedLineMatches); + + contentProvider.getMatchLines(doc, false, highlighter); + + //highlightMatches(file, selectedLineMatches, lineMatchesList, monitor); + } + + private class MatchHighliter implements ResultContentProvider.MatchFindCallback + { + private IProgressMonitor monitor; + private boolean matchSelected = false; + + /** + * @param monitor + */ + public MatchHighliter(IProgressMonitor monitor) + { + this.monitor = monitor; + } + + public void matchFound(MatchLine line) + { + try + { + highlightMatchLine(file, line); + } + catch (Exception e) + { + InstaSearchPlugin.log(e); + monitor.setCanceled(true); + } + } + + public boolean isCanceled() + { + return monitor.isCanceled(); + } + + /** + * @param file + * @throws CoreException + * @throws BadLocationException + */ + protected void highlightMatchLine(IFile file, MatchLine lineMatches) throws CoreException, BadLocationException + { + int lineNum = lineMatches.getLineNumber(); + + if( document.getNumberOfLines() < lineNum ) + return; + + if( selectedLineMatches == null ) selectedLineMatches = lineMatches; // pick first + + int pos = document.getLineOffset(lineNum-1); + + for(Match match: lineMatches.getMatches()) + { + if( monitor.isCanceled() ) break; + + editor.setHighlightRange(pos+match.getOffset(), match.getLength(), false); + + IMarker marker = createMarker(pos, lineNum, match, file, editor); + + if(selectedLineMatches != null && lineNum == selectedLineMatches.getLineNumber()) + { + if( marker != null && ! matchSelected ) + { + gotoEditorMarker(marker); + matchSelected = true; + } + + if( !matchSelected ) { + int selectedOffset = pos+match.getOffset(); + int selectedLength = match.getLength(); + editor.setHighlightRange(selectedOffset, selectedLength, true); + matchSelected = true; + } + } + } + } + + private IMarker createMarker(int pos, int lineNumber, Match match, IFile file, ITextEditor textEditor) throws CoreException { + + if( file == null ) + return null; + + IMarker marker = null; + + marker = file.createMarker(NewSearchUI.SEARCH_MARKER); + marker.setAttribute(IMarker.TRANSIENT, true); + marker.setAttribute(IMarker.MESSAGE, match.getElement()); + + MarkerUtilities.setLineNumber(marker, lineNumber); + MarkerUtilities.setCharStart(marker, pos + match.getOffset()); + MarkerUtilities.setCharEnd(marker, pos + match.getOffset() + match.getLength()); + + return marker; + } + + private void gotoEditorMarker(final IMarker selectedMarker) + { + if( selectedMarker == null ) + return; + + Runnable runnable = new Runnable() + { + public void run() + { + IDE.gotoMarker(editor, selectedMarker); + } + }; + + editor.getSite().getShell().getDisplay().asyncExec(runnable); + } + + } + + private ITextEditor getTextEditor(IEditorInput input, IEditorPart editor) + { + if( editor instanceof MultiPageEditorPart ) + { + MultiPageEditorPart multiPageEditor = (MultiPageEditorPart) editor; + IEditorPart[] editors = multiPageEditor.findEditors(input); + + for(IEditorPart ed: editors) + { + if( ed instanceof ITextEditor ) + { + multiPageEditor.setActiveEditor(ed); + return (ITextEditor) ed; + } + } + } + else if( editor instanceof ITextEditor ) + { + return (ITextEditor) editor; + } + + return null; + } + + /** + * Remove markers when new search is made + * @param file + */ + private void addMarkerRemover(final IFile file) + { + searchJob.addJobChangeListener(new JobChangeAdapter(){ + public void done(IJobChangeEvent event) { + try { + cancel(); + deleteMarkers(); + } finally { + searchJob.removeJobChangeListener(this); + } + } + }); + } + + public boolean contains(ISchedulingRule rule) { + return rule.getClass() == this.getClass(); + } + + public boolean isConflicting(ISchedulingRule rule) { + return rule.getClass() == this.getClass(); + } + + + public void partClosed(IWorkbenchPart part) + { + if( part == editor ) // if closing editor + { + this.cancel(); // cancel highlight job + deleteMarkers(); + } + } + + private void deleteMarkers() + { + try + { + if( file != null ) + file.deleteMarkers(NewSearchUI.SEARCH_MARKER, true, IResource.DEPTH_INFINITE); + } + catch (CoreException e) + { + InstaSearchPlugin.log(e); + } + } + + public void partDeactivated(IWorkbenchPart part) + { + } + + public void partOpened(IWorkbenchPart part) + { + } + + public void partActivated(IWorkbenchPart part) + { + } + + public void partBroughtToTop(IWorkbenchPart part) + { + } + +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/ui/ReportErrorDialog.java b/instasearch/src/it/unibz/instasearch/ui/ReportErrorDialog.java new file mode 100755 index 0000000..a4fdc19 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/ReportErrorDialog.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import it.unibz.instasearch.InstaSearchPlugin; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.methods.PostMethod; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Link; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.osgi.framework.Constants; + +public class ReportErrorDialog extends ErrorDialog +{ + private static final int REPORT_BUTTON_ID = IDialogConstants.CLIENT_ID + 1; + private IStatus status; + private Link newTicketLink; + + /** + * @param parentShell + * @param dialogTitle + * @param message + * @param status + * @param displayMask + */ + public ReportErrorDialog(Shell parentShell, String dialogTitle, + String message, IStatus status, int displayMask) + { + super(parentShell, dialogTitle, message, status, displayMask); + + this.status = status; + } + + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.ErrorDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) + */ + @Override + protected void createButtonsForButtonBar(Composite parent) + { + super.createButtonsForButtonBar(parent); + + createButton(parent, REPORT_BUTTON_ID, "Report", true); + } + + @Override + protected List createDropDownList(Composite parent) + { + List list = super.createDropDownList(parent); + + if( newTicketLink == null ) { + newTicketLink = new Link(parent, SWT.NONE); + newTicketLink.setText("You can also open a new ticket"); + newTicketLink.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) + { + try + { + InstaSearchUI.showHomePage(); + } catch (Exception ex) + { + InstaSearchPlugin.log(ex); + newTicketLink.setEnabled(false); + } + } + }); + + GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL + | GridData.GRAB_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL + | GridData.GRAB_VERTICAL ); // + data.horizontalSpan = 2; + newTicketLink.setLayoutData( data ); + } + + list.addDisposeListener(new DisposeListener(){ + public void widgetDisposed(DisposeEvent e) + { + newTicketLink.dispose(); + newTicketLink = null; + } + }); + + return list; + } + + public static void openReportError(Shell parentShell, String title, + String message, IStatus status) { + + int displayMask = IStatus.OK | IStatus.INFO | IStatus.WARNING | IStatus.ERROR; + final ReportErrorDialog dialog = new ReportErrorDialog(parentShell, title, message, status, displayMask); + + Display display = PlatformUI.getWorkbench().getDisplay(); + if(display == null || display.isDisposed() ) + return; + + display.asyncExec(new Runnable() { + public void run() + { + dialog.open(); + } + }); + + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.ErrorDialog#buttonPressed(int) + */ + @Override + protected void buttonPressed(int id) + { + if( id == REPORT_BUTTON_ID ) { + try { + reportError(); + close(); + } catch (Exception e) { + e.printStackTrace(); + InstaSearchPlugin.log(e); + InstaSearchUI.showMessage("Unable to send. Please open a ticket in project's site"); + } + } else + super.buttonPressed(id); + } + + + /** + * @throws IOException + * @throws HttpException + * + */ + private void reportError() throws HttpException, IOException + { + HttpClient httpClient = new HttpClient(); + PostMethod postMethod = new PostMethod(InstaSearchPlugin.getErrorReportURL()); + + postMethod.addParameter("subj", message); + postMethod.addParameter("attn", "Exception"); + postMethod.addParameter("notes", getStatusContent(status)); + postMethod.addParameter("visitor", "InstaSearch Plugin " + InstaSearchPlugin.getVersion()); + + httpClient.executeMethod(postMethod); + + postMethod.releaseConnection(); + } + + private String getStatusContent(IStatus status) { + + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + + addProperty(printWriter, "version", InstaSearchPlugin.getVersion()); + + addSystemProperty(printWriter, "osgi.framework.version"); + addSystemProperty(printWriter, "eclipse.buildId"); + addSystemProperty(printWriter, "java.version"); + + addBundleProperty(printWriter, Constants.FRAMEWORK_VERSION); + addBundleProperty(printWriter, Constants.FRAMEWORK_OS_NAME); + addBundleProperty(printWriter, Constants.FRAMEWORK_OS_VERSION); + + addStatusContent(printWriter, status); + + for(IStatus st: status.getChildren()) + addStatusContent(printWriter, st); + + return stringWriter.toString(); + } + + private void addBundleProperty(PrintWriter b, String prop) { + addProperty(b, prop, InstaSearchPlugin.getDefault().getBundle().getBundleContext().getProperty(prop)); + } + + private void addSystemProperty(PrintWriter b, String prop) { + addProperty(b, prop, System.getProperty(prop)); + } + + private void addProperty(PrintWriter b, String prop, String val) { + b.print(prop); + b.print(": "); + b.println(val); + } + + private void addStatusContent(PrintWriter b, IStatus status) { + b.print("Status: "); + b.println(status.getMessage()); + status.getException().printStackTrace(b); + b.println(); + } +} diff --git a/instasearch/src/it/unibz/instasearch/ui/ResultContentProvider.java b/instasearch/src/it/unibz/instasearch/ui/ResultContentProvider.java new file mode 100755 index 0000000..2ba2e31 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/ResultContentProvider.java @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import it.unibz.instasearch.InstaSearch; +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.indexing.Field; +import it.unibz.instasearch.indexing.WorkspaceIndexer; +import it.unibz.instasearch.indexing.SearchQuery; +import it.unibz.instasearch.indexing.SearchResult; +import it.unibz.instasearch.indexing.SearchResultDoc; +import it.unibz.instasearch.indexing.Searcher; +import it.unibz.instasearch.indexing.StorageIndexer; +import it.unibz.instasearch.prefs.PreferenceConstants; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IStorage; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.search.ui.text.Match; +import org.eclipse.ui.IEditorInput; + +class ResultContentProvider implements ITreeContentProvider { + + private static final String[] NO_INDEX_MESSAGE = new String[] {"Index is not built"}; + private static final String[] NO_FILE_MESSAGE = new String[] {"File missing"}; + private static final String NO_RESULTS_MESSAGE = "0 matches"; + + public static final double MAX_LINE_SIMILARITY = 0.9; // if above that, only one of the similar lines is kept + public static final int MAX_LINES_TO_PROCESS = 5000; // max nr of lines to read from files (prevent slowdown on huge files) + + private WorkspaceIndexer indexer; + private Searcher searcher; + + /** + * Map of search terms to their boost score + */ + private SearchQuery currentSearchQuery; + private Map searchTerms; + + private Object[] cachedResults; + private SearchResultDoc cachedResultDoc; + private Object[] cachedChildren; + private int resultCount; + + + public ResultContentProvider() { + InstaSearch instaSearch = InstaSearchPlugin.getInstaSearch(); + + this.indexer = instaSearch.getIndexer(); + this.searcher = instaSearch.getSearcher(); + } + + public void inputChanged(Viewer v, Object oldInput, Object newSearch) { + if( newSearch==null || !(newSearch instanceof SearchQuery) ) { + currentSearchQuery = null; // clear cache + cachedResults = null; + } + } + + public void dispose() { + } + + public Object[] getElements(Object searchQueryObj) + { + if( searchQueryObj==null || !(searchQueryObj instanceof SearchQuery) ) + return Collections.EMPTY_LIST.toArray(); // not searching + + SearchQuery searchQuery = (SearchQuery) searchQueryObj; + String searchString = searchQuery.getSearchString(); + + if( searchString==null || searchString.toString().length() < Searcher.MIN_QUERY_LENGTH ) + return Collections.EMPTY_LIST.toArray(); + + try + { + if( ! indexer.isIndexed() ) + return NO_INDEX_MESSAGE; + } catch(Exception e) + { + InstaSearchPlugin.log(e); + return new Exception[]{e}; + } + + if( searchQuery.equals(currentSearchQuery) && cachedResults != null ) // same query + return cachedResults; + + SearchResult result = null; + cachedResults = null; + resultCount = 0; + Object[] resultArray = null; + + if(searchString != null) + { + try { + result = searcher.search(searchQuery); // do the search + currentSearchQuery = searchQuery; + + if( result == null ) { + if( !searchQuery.isFuzzy() ) { + SearchQuery newQuery = new SearchQuery(searchQuery); + newQuery.setExact(false); + newQuery.setFuzzy(true); + resultArray = new Object[]{NO_RESULTS_MESSAGE, newQuery}; // add fuzzy query + } else { + resultArray = new Object[]{NO_RESULTS_MESSAGE}; + } + + cachedResults = resultArray; + + return resultArray; + } + + searchTerms = result.getSearchTerms(); + + } catch (Exception e) { + InstaSearchPlugin.log(e); + return new Exception[]{e}; + } + } + + List resultDocs = result.getResultDocs(); + this.resultCount = resultDocs.size(); + + boolean addMoreResults = false, addFindSimilar = false; + + if( searchQuery.isLimited() && result.isFull() ) { // if only showing limited number of matches + addMoreResults = true; + } + else + { + if( searchQuery.isExact() && !searchQuery.isFuzzy() ) // if query is exact, can try search for individual tokens + addFindSimilar = true; + } + + if( addMoreResults || addFindSimilar ) + resultArray = new Object[resultCount + 1]; // +1 because we append "More..." element (a SearchQuery object) + else + resultArray = new Object[resultCount]; + + resultDocs.toArray(resultArray); + + if( addMoreResults ) { // if more results, create More result entry (return all elements) + SearchQuery moreResultsQuery = new SearchQuery(currentSearchQuery); + moreResultsQuery.setMaxResults(SearchQuery.UNLIMITED_RESULTS); // all results + resultArray[resultCount] = moreResultsQuery; + } + else if( addFindSimilar ) + { + SearchQuery findSimilarQuery = new SearchQuery(currentSearchQuery); + findSimilarQuery.setExact(false); + resultArray[resultCount] = findSimilarQuery; + } + + cachedResults = resultArray; + + return resultArray; + } + + /** + * Count of search result docs from last search + * @return result count + * + */ + public int getResultCount() + { + return resultCount; + } + + /** + * Returns last search result elements. + * Includes search result docs and additional action entries (eg More results) + * + * @return array of last search result elements + */ + public Object[] getElements() { + return cachedResults; + } + + public Object[] getChildren(Object parent) + { + if( parent instanceof SearchResultDoc ) { + + SearchResultDoc doc = (SearchResultDoc) parent; + + if( cachedResultDoc != null && doc.equals(cachedResultDoc) ) + return cachedChildren; // cache results + + List matches = null; + Object[] children = null; + + try { + matches = getMatchLines(doc, true, null); + if( matches != null ) + children = matches.toArray(); + } catch (Exception e) { + InstaSearchPlugin.log(e); + } + + if( matches == null ) + children = NO_FILE_MESSAGE; + + cachedResultDoc = doc; + cachedChildren = children; + + return children; + } + else if( parent instanceof Exception ) { + Exception e = (Exception) parent; + return e.getStackTrace(); + } + + return Collections.EMPTY_LIST.toArray(); + } + + public interface MatchFindCallback + { + void matchFound(MatchLine line); + boolean isCanceled(); + } + + /** + * Returns matched lines + * @param doc + * @param limit + * @return + * @throws Exception + */ + List getMatchLines(SearchResultDoc doc, boolean limit, MatchFindCallback callback) throws Exception { + + if( searchTerms == null || currentSearchQuery == null ) + return Collections.emptyList(); + + int maxMatches = InstaSearchPlugin.getIntPref(PreferenceConstants.P_SHOWN_LINES_COUNT); + List matchedLines = new ArrayList(); + int matchCount = doc.getMatchCount(); + String searchString = currentSearchQuery.getSearchString().toLowerCase(); + + IStorage f = getStorage(doc); + if( f == null ) { + // index might be outdated (disabled updating) + //TODO: remove file from index (update index) + return null; + } + + InputStream fileInputStream = null; + + if( f instanceof IFile ) { + IFile file = (IFile) f; + if( !file.exists() ) + return null; + fileInputStream = file.getContents(true); + } else { + fileInputStream = f.getContents(); + } + + LineNumberReader lineReader = new LineNumberReader(new InputStreamReader(fileInputStream)); // is a buffered reader + + String line; + + // Read through file one line at a time + while ( (line = lineReader.readLine()) != null ) { + + if( callback != null && callback.isCanceled() ) break; + //if( currentSearchQuery.isCanceled() ) break; + + if( "".equals(line) ) continue; + + Map> lineTerms = StorageIndexer.extractTextTerms(line); + if( lineTerms.isEmpty() ) continue; + + HashSet matchedTerms = new HashSet(searchTerms.keySet()); // search terms that appear on this line + matchedTerms.retainAll(lineTerms.keySet()); + + if( matchedTerms.isEmpty() && matchCount != 0 && limit ) // if have matches in general, but not on this line, then skip + continue; + + float[] lineTermScoreVector = doc.getTermScoreVector(lineTerms.keySet()); + float[] matchedTermScoreVector = doc.getTermScoreVector(matchedTerms); + + MatchLine matchLine = new MatchLine(doc, line, lineReader.getLineNumber(), matchedTerms, lineTermScoreVector, matchedTermScoreVector); + matchedLines.add(matchLine); + + addMatches(matchLine, lineTerms, matchedTerms, searchString); + if( callback != null ) + callback.matchFound(matchLine); + + if( lineReader.getLineNumber() > MAX_LINES_TO_PROCESS ) + break; + + //TODO: break if all current matches have high score (eg >0.9) + } + + lineReader.close(); + + if(limit && matchedLines.size() > maxMatches) { + matchedLines = getTopMatchLines(maxMatches, matchedLines); // return TOP N lines + return matchedLines; + + } else + return matchedLines; + } + + private List getTopMatchLines(int maxMatchLines, List matchedLines) { + Collections.sort(matchedLines); // sort by match count, score, line + removeSimilarLines(matchedLines, maxMatchLines); + matchedLines = matchedLines.subList(0, maxMatchLines); // top N results + + Collections.sort(matchedLines, new Comparator() { // sort by line number for display + public int compare(MatchLine l1, MatchLine l2) { + return l1.getLineNumber() - l2.getLineNumber(); + } + }); + + return matchedLines; + } + + /** + * Find matches on the line + * + * @param matchLine + * @param terms + * @param matchedTerms + * @param searchString + * @return + */ + private float addMatches(MatchLine matchLine, Map> terms, + Set matchedTerms, String searchString) { + + String lcaseLine = matchLine.getLine().toLowerCase(); + + if( !matchedTerms.contains(searchString) && !currentSearchQuery.isFuzzy() ) { // check for exact match on the line + + int pos = lcaseLine.indexOf(searchString); + + while( pos != -1 ) { + Match m = new Match(searchString, pos, searchString.length()); + matchLine.add(m, true); + pos = lcaseLine.indexOf(searchString, pos + searchString.length() - 1); + } + } + + float matchedTermBoost = 0; + + for(String term: matchedTerms) { + List offsets = terms.get(term); + + for(int offset: offsets) { + int pos = lcaseLine.indexOf(term, offset); + if( pos == -1 ) continue; + Match m = new Match(term, pos, term.length()); + matchLine.add(m); + } + + float boost = searchTerms.get(term); + + matchedTermBoost += boost; + } + + matchLine.setMatchedTermBoost(matchedTermBoost); + + return matchedTermBoost; + } + + /** + * Removes similar lines from line matches. + * Even if they are high scored, we don not want to see the same lines again + * Line similarity is based on Cosine between their corresponding term vectors + * + * @param matchedLines + * @param maxMatches + */ + private void removeSimilarLines(List matchedLines, int maxMatches) + { + MatchLine curMatchLine = null; + + int lineNr = 0; + for (Iterator iterator = matchedLines.iterator(); + iterator.hasNext() && matchedLines.size()>maxMatches; ) + { + MatchLine matchLine = iterator.next(); + + if( curMatchLine == null ) { + curMatchLine = matchLine; + lineNr++; + continue; + } + + double similarity = getLineSimilarity(curMatchLine, matchLine); + + if( similarity > MAX_LINE_SIMILARITY ) + iterator.remove(); // since lines are sorted by score, lowest score line will be removed + else { + curMatchLine = matchLine; + lineNr++; + } + + if( lineNr == maxMatches ) + break; + } + } + + /** + * Calculates similarity based on the Cosine angle between score vectors of each line. + * + * @param lineMatches1 + * @param lineMatches2 + * @return + */ + private double getLineSimilarity(MatchLine lineMatches1, MatchLine lineMatches2) + { + float[] vect1 = lineMatches1.getScoreVector(); + float[] vect2 = lineMatches2.getScoreVector(); + + double dotProduct = 0.0; + double magnitude1 = 0.0; + double magnitude2 = 0.0; + for (int i = 0; i < vect1.length ; i++) { + double val1 = vect1[i]; + double val2 = vect2[i]; + magnitude1 += val1 * val1; + magnitude2 += val2 * val2; + dotProduct += val1 * val2; + } + magnitude1 = Math.sqrt(magnitude1); + magnitude2 = Math.sqrt(magnitude2); + return (magnitude1 == 0 || magnitude2 == 0) + ? 0 + : dotProduct / (magnitude1 * magnitude2); + + } + + public Object getParent(Object element) { + return null; + } + + public boolean hasChildren(Object element) { + return ( element instanceof SearchResultDoc ) || ( element instanceof SearchQuery ); + } + + public Collection getSearchTerms() { + return searchTerms.keySet(); + } + + public IEditorInput getEditorInput(SearchResultDoc doc) throws Exception { + return indexer.getEditorInput(doc); + } + + public IStorage getStorage(SearchResultDoc doc) throws Exception { + return indexer.getStorage(doc); + } + + public List getProposals(String prefix, Field field) throws IOException + { + List ucaseProposals = searcher.getProposals(prefix.toUpperCase(), field); + + if( prefix.toUpperCase().equals(prefix.toLowerCase())) + return ucaseProposals; + + List lcaseProposals = searcher.getProposals(prefix.toLowerCase(), field); + + ucaseProposals.addAll(lcaseProposals); + Collections.sort(ucaseProposals, String.CASE_INSENSITIVE_ORDER); + + return ucaseProposals; + } + + /** + * A class representing a line in a document and containing some keyword matches + */ + class MatchLine implements Comparable { + + private String lineText; + private List matches = new LinkedList(); + private SearchResultDoc doc; + private int lineNumber; + + private double termScore; + private double matchedTermScore; + private float[] scoreVector; + private float matchedTermBoost; + private int exactMatches; + private int matchedTermCount; + + private MatchLine(SearchResultDoc doc, String lineText, int lineNumber, Set matchedTerms, float[] termScoreVector, float[] matchedTermScoreVector) throws IOException { + this.doc = doc; + this.lineText = lineText; + this.lineNumber = lineNumber; + this.scoreVector = termScoreVector; + + termScore = getMagnitude(termScoreVector); + matchedTermScore = getMagnitude(matchedTermScoreVector); + matchedTermCount = matchedTerms.size(); + } + + public void setMatchedTermBoost(float matchedTermBoost) + { + this.matchedTermBoost = matchedTermBoost; + } + + public float getMatchedTermBoost() + { + return matchedTermBoost; + } + + public void add(Match m) { + matches.add(m); + } + + public void add(Match m, boolean isExactMatch) { + matches.add(m); + if( isExactMatch ) + this.exactMatches++; + } + + public List getMatches() { + return matches; + } + + public String getLine() { + return lineText; + } + + public int getLineNumber() { + return lineNumber; + } + + public double getTermScore() + { + return termScore; + } + + public float[] getScoreVector() + { + return scoreVector; + } + + public double getMatchedTermScore() + { + return matchedTermScore; + } + + public int compareTo(MatchLine lineMatches) { // to sort by match count and then by line number + int diff = lineMatches.exactMatches - exactMatches; + if( diff == 0 ) + diff = lineMatches.matchedTermCount - matchedTermCount; + if( diff == 0 ) + Double.compare(lineMatches.matchedTermBoost, matchedTermBoost); + if(diff == 0) + diff = Double.compare(lineMatches.termScore, termScore); + if(diff == 0) + return getLineNumber() - lineMatches.lineNumber; // smaller to bigger + return diff; + } + + public SearchResultDoc getResultDoc() + { + return doc; + } + + /** + * Vector magnitude + * + * @param vect + * @return + */ + private double getMagnitude(float[] vect) + { + double magnitude = 0; + + for(float value: vect) + magnitude+=value*value; + + magnitude = Math.sqrt(magnitude); + + return magnitude; + } + + @Override + public String toString() + { + return "Line " + lineNumber + ": (" + matchedTermCount + ")" + lineText; + } + } +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/ui/ResultLabelProvider.java b/instasearch/src/it/unibz/instasearch/ui/ResultLabelProvider.java new file mode 100755 index 0000000..0e8b5d6 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/ResultLabelProvider.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.indexing.SearchQuery; +import it.unibz.instasearch.indexing.SearchResultDoc; +import it.unibz.instasearch.prefs.PreferenceConstants; +import it.unibz.instasearch.ui.ResultContentProvider.MatchLine; + +import java.util.Collection; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.StyledString; +import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; +import org.eclipse.jface.viewers.StyledString.Styler; +import org.eclipse.search.ui.text.Match; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.model.WorkbenchLabelProvider; + +class ResultLabelProvider extends LabelProvider implements IStyledLabelProvider, IPropertyChangeListener { + + /** + * + */ + private static final String HIGHLIGHT_COLOR_NAME = "it.unibz.instasearch.ui.HighlightColor"; + private static final String IMG_OBJ_TEXT_SEARCH_LINE = "org.eclipse.search.ui.line_match"; + private static final String MORE_RESULTS_LABEL = "More..."; + private static final String FIND_SIMILAR_LABEL = "Find similar..."; + private static final String DOWN_ARROW_IMG_KEY = "down_arrow"; + + private ImageRegistry imageRegistry = new ImageRegistry(); + private Styler highlightStyle; + + private WorkbenchLabelProvider labelProvider; + private ResultContentProvider contentProvider; + + private Image matchImage; + private boolean showMatchCount; + private boolean showFullPath; + + public ResultLabelProvider(ResultContentProvider contentProvider) { + JFaceResources.getColorRegistry().put(HIGHLIGHT_COLOR_NAME, new RGB(206, 204, 247)); + + this.labelProvider = new WorkbenchLabelProvider(); + this.highlightStyle = StyledString.createColorRegistryStyler(null, HIGHLIGHT_COLOR_NAME); + this.contentProvider = contentProvider; + this.matchImage = InstaSearchUI.getSharedImage(IMG_OBJ_TEXT_SEARCH_LINE); + + imageRegistry.put(DOWN_ARROW_IMG_KEY, InstaSearchPlugin.getImageDescriptor(DOWN_ARROW_IMG_KEY)); + + this.showMatchCount = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_SHOW_MATCH_COUNT); + this.showFullPath = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_SHOW_FULL_PATH); + + InstaSearchPlugin.addPreferenceChangeListener(this); + } + + public StyledString getStyledText(Object element) { + + if(element instanceof SearchResultDoc) { + SearchResultDoc doc = (SearchResultDoc) element; + + return decorateFile(doc); + + } else if(element instanceof MatchLine) { + MatchLine lineMatches = (MatchLine) element; + return decorateLineMatches(lineMatches); + + } else if( element instanceof SearchQuery ) { + // we have search query in 2 cases: + SearchQuery query = (SearchQuery) element; + + if( !query.isLimited() ) + return new StyledString(MORE_RESULTS_LABEL); + else + return new StyledString(FIND_SIMILAR_LABEL); + } + + return new StyledString(element.toString()); + } + + private StyledString decorateFile(SearchResultDoc doc) { + + String fileName = doc.getFileName(); + StyledString str = new StyledString(fileName); + + Collection searchTerms = contentProvider.getSearchTerms(); + + for(String searchTerm: searchTerms) // highlight matches + { + int termPos = fileName.toLowerCase().indexOf(searchTerm); + + if( termPos != -1 ) + str.setStyle(termPos, searchTerm.length(), highlightStyle); + } + + int matchCount = doc.getMatchCount(); + + if( matchCount > 1 && showMatchCount ) + { + str.append(" (", StyledString.COUNTER_STYLER); + str.append(Integer.toString(matchCount), StyledString.COUNTER_STYLER); + str.append(" matches)", StyledString.COUNTER_STYLER); + } + + str.append(" - ", StyledString.QUALIFIER_STYLER); + str.append(doc.getProjectName(), StyledString.QUALIFIER_STYLER); + + if( showFullPath ) + { + String filePath = getCompactFilePath(doc, fileName); + + if( !"".equals(filePath) ) + { + str.append(" - ", StyledString.QUALIFIER_STYLER); + str.append(filePath, StyledString.QUALIFIER_STYLER); + } + } + + if( InstaSearchPlugin.isDebug() ) + { + str.append(" - [", StyledString.DECORATIONS_STYLER); + str.append(String.format("%.03f", doc.getScore()), StyledString.DECORATIONS_STYLER); + str.append("]", StyledString.DECORATIONS_STYLER); + } + + return str; + } + + /** + * File path without the project name and without the filename + * + * @param doc + * @param fileName + * @return + */ + private String getCompactFilePath(SearchResultDoc doc, String fileName) { + + String projectName = doc.getProjectName(); + String filePath = doc.getFilePath(); + + int end = filePath.length()-1, start = filePath.indexOf(projectName); + if( start == -1 ) + start = 0; + else + start = start + projectName.length() + 1; + + if( filePath.endsWith(fileName) ) + end = filePath.length() - fileName.length() - 1; + + if( start > end ) + return ""; + + filePath = filePath.substring(start, end); + + return filePath; + } + + private StyledString decorateLineMatches(MatchLine lineMatches) { + + String line = lineMatches.getLine(); + StyledString str = new StyledString(line); + + for(Match m: lineMatches.getMatches()) + { + str.setStyle(m.getOffset(), m.getLength(), highlightStyle); + } + + StyledString ret = new StyledString(); + ret.append(lineMatches.getLineNumber() + ": ", StyledString.QUALIFIER_STYLER); + ret.append(str); + + return ret; + } + + public Image getImage(Object element) { + try { + if(element instanceof SearchResultDoc) { + SearchResultDoc doc = (SearchResultDoc) element; + + Image image = null; + + if( !doc.isInJar() ) + image = labelProvider.getImage(doc.getFile()); + + if( image == null ) + image = getFileImage(doc); + + if( image == null ) + image = InstaSearchUI.getSharedImage(ISharedImages.IMG_OBJ_FILE); + + return image; + + } else if( element instanceof MatchLine ) + return matchImage ; + else if( element instanceof Exception ) + return InstaSearchUI.getSharedImage(ISharedImages.IMG_OBJS_WARN_TSK); + else if( element instanceof SearchQuery ) + return imageRegistry.get(DOWN_ARROW_IMG_KEY); + + } catch(Exception e) { + InstaSearchPlugin.log(e); + return InstaSearchUI.getSharedImage(ISharedImages.IMG_OBJS_WARN_TSK); + } + + return InstaSearchUI.getSharedImage(ISharedImages.IMG_OBJS_INFO_TSK); // no results + } + + private Image getFileImage(SearchResultDoc doc) + { + String ext = doc.getFileExtension(); + Image fileImage = imageRegistry.get(ext); + + if( fileImage == null ) { + ImageDescriptor imageDescriptor = PlatformUI.getWorkbench().getEditorRegistry().getImageDescriptor(doc.getFileName()); + fileImage = imageDescriptor.createImage(true); + imageRegistry.put(ext, fileImage); // cache created images for extensions + } + + return fileImage; + } + + public void propertyChange(PropertyChangeEvent event) { + // update preferences + if( PreferenceConstants.P_SHOW_MATCH_COUNT.equals(event.getProperty())) + showMatchCount = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_SHOW_MATCH_COUNT); + else if( PreferenceConstants.P_SHOW_FULL_PATH.equals(event.getProperty())) + showFullPath = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_SHOW_FULL_PATH); + } + + @Override + public void dispose() + { + super.dispose(); + imageRegistry.dispose(); + InstaSearchPlugin.removePreferenceChangeListener(this); + } +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/ui/SearchContentProposalProvider.java b/instasearch/src/it/unibz/instasearch/ui/SearchContentProposalProvider.java new file mode 100755 index 0000000..fe790df --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/SearchContentProposalProvider.java @@ -0,0 +1,199 @@ +/* Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.indexing.Field; +import it.unibz.instasearch.indexing.Searcher; +import it.unibz.instasearch.indexing.querying.ModifiedTimeConverter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.jface.fieldassist.IContentProposal; +import org.eclipse.jface.fieldassist.SimpleContentProposalProvider; + +class SearchContentProposalProvider extends SimpleContentProposalProvider +{ + private final IContentProposal[] EMPTY_PROPOSALS = new IContentProposal[]{}; + private ResultContentProvider contentProvider; + + public SearchContentProposalProvider(ResultContentProvider contentProvider) + { + super(new String[]{}); + this.contentProvider = contentProvider; + } + + @Override + public IContentProposal[] getProposals(String contents, int position) + { + String curText = contents.substring(0, position); + String rest = contents.substring(position); + + if( curText.endsWith(" ") ) + return EMPTY_PROPOSALS; + + //TODO: use parser + int colIdx = curText.lastIndexOf(':'); + int spaceIdx = curText.lastIndexOf(' '); + + if( colIdx == -1 || spaceIdx > colIdx ) + return getPrefixProposals(curText, Field.CONTENTS, rest); + + String beforeCol = curText.substring(0, colIdx); + String fieldName = beforeCol; + if( spaceIdx != -1 ) + fieldName = beforeCol.substring(spaceIdx+1); + + fieldName = fieldName.toLowerCase(); + List proposalNames = null; + + int commaIdx = curText.lastIndexOf(','); + String prevProposal = ""; + + if( commaIdx > colIdx && commaIdx < position ) { + prevProposal = curText.substring(colIdx+1, commaIdx+1); + colIdx = commaIdx; + } + + String prefix = curText.substring(colIdx+1).toLowerCase(); // filtering text + Field field = Field.getByName(fieldName); + + if( field == null ) + return EMPTY_PROPOSALS; + + proposalNames = getFieldProposals(field, prefix); + if( proposalNames.size() == 0 ) + return EMPTY_PROPOSALS; + + ArrayList proposals = new ArrayList(); + + if( "".equals(prefix) && field == Field.PROJ ) + addCurrentProjectProposal(rest, beforeCol, prevProposal, proposals); + + for(String proposalName: proposalNames) { + if( proposalName.toLowerCase().startsWith(prefix) ) { + String label = proposalName; + proposalName = prevProposal + proposalName; + + if( proposalName.contains(" ") && !proposalName.contains("\"") ) + proposalName = "\"" + proposalName + "\""; + + String proposalContent = beforeCol + ':' + proposalName + rest; + int pos = beforeCol.length() + 1 + proposalName.length(); + + proposals.add( makeContentProposal(proposalContent, label, pos) ); + } + } + + return proposals.toArray(new IContentProposal[proposals.size()]); + } + + public List getFieldProposals(Field field, String prefix) { + + List proposalNames; + + switch(field) + { + case PROJ: proposalNames = InstaSearchPlugin.getProjectNames(); break; + case WS: proposalNames = InstaSearchPlugin.getWorkingSets(); break; + case MODIFIED: proposalNames = ModifiedTimeConverter.getDurationNames(); break; + case FILE: return Collections.emptyList(); + case DIR: return Collections.emptyList(); + default: proposalNames = getIndexedProposals(prefix, field); break; + } + + return proposalNames; + } + + private void addCurrentProjectProposal(String rest, String beforeCol, + String prevProposal, ArrayList proposals) { + if( InstaSearchUI.getActiveProject() != null ) { + String content = beforeCol + ":" + prevProposal + Searcher.CURRENT_PROJECT_CHAR + rest; + proposals.add( makeContentProposal(content, + Searcher.CURRENT_PROJECT_CHAR + " (Current Project)", beforeCol.length()+2) ); + } + } + + /** + * @param rest + * @param curText + * @return + */ + private IContentProposal[] getPrefixProposals(String text, Field field, String rest) { + + if( "".equals(text.trim())) + return EMPTY_PROPOSALS; + + String before, prefix; + + int spaceIdx = text.lastIndexOf(' '); + + if( spaceIdx != -1 ) { + prefix = text.substring(spaceIdx+1); + before = text.substring(0, spaceIdx+1); + } else { // whole prefix + prefix = text; + before = ""; + } + + ArrayList contentProposals = new ArrayList(); + + List proposals = getIndexedProposals(prefix, field); + if( proposals == null ) + return EMPTY_PROPOSALS; + + for(String proposal: proposals) { + if( proposal.toLowerCase().startsWith(prefix) ) { + String label = proposal; + + String proposalContent = before + proposal + rest; + int pos = before.length() + proposal.length(); + + contentProposals.add( makeContentProposal(proposalContent, label, pos) ); + } + } + + return contentProposals.toArray(new IContentProposal[contentProposals.size()]); + } + + private List getIndexedProposals(String prefix, Field field) { + List proposals = null; + try { + proposals = contentProvider.getProposals(prefix, field); + } catch (IOException e) { + return null; + } + return proposals; + } + + private IContentProposal makeContentProposal(final String proposalContent, final String label, final int position) { + return new IContentProposal() { + public String getContent() { + return proposalContent; + } + + public String getDescription() { + return null; + } + + public String getLabel() { + return label; + } + + public int getCursorPosition() { + return position; + } + }; + } +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/ui/SearchJob.java b/instasearch/src/it/unibz/instasearch/ui/SearchJob.java new file mode 100755 index 0000000..94e90ea --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/SearchJob.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import it.unibz.instasearch.indexing.SearchQuery; +import it.unibz.instasearch.indexing.SearchResultDoc; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.TreeItem; + +/** + * A search job that runs search in UI thread. + * Is used to start search after user has stopped typing + */ +public class SearchJob extends Job { + + /** + * + */ + private TreeViewer resultViewer = null; + private SearchQuery searchQuery = null; + private boolean selectLast = false; + private InstaSearchView searchView; + private IStatusLineManager statusLineManager; + + public SearchJob(InstaSearchView searchView) + { + super("Search"); + + this.searchView = searchView; + this.resultViewer = searchView.getResultViewer(); + this.statusLineManager = searchView.getViewSite().getActionBars().getStatusLineManager(); + + this.addJobChangeListener(new JobChangeAdapter(){ + public void done(IJobChangeEvent event) { + if( event.getResult() == Status.CANCEL_STATUS ) + cancelSearch(); + } + }); + + setPriority(Job.INTERACTIVE); + } + + public void schedule(SearchQuery searchQuery, boolean selectLast, long delay) { + cancelSearch(); + + this.searchQuery = searchQuery; + this.selectLast = selectLast; + + if( this.searchQuery != null ) { + this.searchQuery.setCanceled(false); + this.searchQuery.setCurrentProject( InstaSearchUI.getActiveProject() ); + + schedule(delay); + } + } + + /** + * Cancel current search + */ + private void cancelSearch() { + if( searchQuery != null ) + searchQuery.setCanceled(true); + } + + protected IStatus run(IProgressMonitor monitor) + { + ResultContentProvider prov = (ResultContentProvider) resultViewer.getContentProvider(); + + if( prov == null || monitor.isCanceled() || searchQuery == null || searchQuery.isCanceled() ) return Status.CANCEL_STATUS; + + prov.getElements(searchQuery); // runs query and caches result. running in this job to avoid UI freeze + + if( monitor.isCanceled() || searchQuery.isCanceled() ) return Status.CANCEL_STATUS; // perhaps we cancelled while executing query + + Display display = resultViewer.getControl().getDisplay(); + + display.syncExec(new Runnable() { + public void run() { + search(); // run in UI + } + }); + + return Status.OK_STATUS; + } + + private void search() { + int items = resultViewer.getTree().getItemCount(); + + resultViewer.setInput(searchQuery); // run in UI, displays cached results immediately + + int newItems = resultViewer.getTree().getItemCount(); + + if( selectLast && items != 0 && newItems >= items ) + resultViewer.getTree().setSelection(resultViewer.getTree().getItem(items-1)); // show previous selection + + int resultCount = countSearchResults(newItems); + String resultsDesc = " " + (searchQuery.isExact() ? "exact" : "similar") + " results"; + + if( searchQuery.isLimited() ) // limited + { + if( resultCount >= searchQuery.getMaxResults() ) + statusLineManager.setMessage(searchView.getTitleImage(), searchQuery.getMaxResults() + "+" + resultsDesc + " (Ctrl+Enter to see all)"); + else + statusLineManager.setMessage(searchView.getTitleImage(), resultCount + resultsDesc); + } + else { // not limited + statusLineManager.setMessage(searchView.getTitleImage(), resultCount + resultsDesc); + } + } + + /** + * @param newItems + * @return + */ + private int countSearchResults(int newItems) { + + int i, allItems = resultViewer.getTree().getItemCount(); + + for(i = allItems-1; i >= 0; i--) + { + TreeItem treeItem = resultViewer.getTree().getItem(i); + + if( treeItem == null || treeItem.getData() == null ) + continue; + + if( treeItem.getData() instanceof SearchResultDoc ) // from now on we have results + return i+1; + } + + return 0; + } + + +} \ No newline at end of file diff --git a/instasearch/src/it/unibz/instasearch/ui/SearchViewControl.java b/instasearch/src/it/unibz/instasearch/ui/SearchViewControl.java new file mode 100755 index 0000000..dd82681 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/SearchViewControl.java @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import it.unibz.instasearch.InstaSearchPlugin; +import it.unibz.instasearch.indexing.Field; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.bindings.keys.KeyStroke; +import org.eclipse.jface.fieldassist.ContentProposalAdapter; +import org.eclipse.jface.fieldassist.IContentProposalProvider; +import org.eclipse.jface.fieldassist.IControlContentAdapter; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorRegistry; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE.SharedImages; + +/** + * + */ +public class SearchViewControl implements DisposeListener { + + private static final String PROPOSAL_KEYSTROKE = "Ctrl+Space"; + private static final String SEARCH_TEXT_TIP = "search text " + Field.PROJ + ":MyProject " + Field.EXT + ":xml,java"; + + private TreeViewer resultViewer; + private StyledText searchText; + private ImageRegistry imageRegistry = new ImageRegistry(); + private ToolBar filterBar; + private SearchContentProposalProvider proposalProvider; + private Composite parent; + private int itemInsertIndex = 0; + private ModifyListener modifyListener; //TODO: new interface + + private Color searchTipColor = getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY); + private Color defaultSearchColor = getDisplay().getSystemColor(SWT.COLOR_BLACK); + /** + * @param parent + */ + public SearchViewControl(Composite parent, ModifyListener modifyListener) { + + this.parent = parent; + this.modifyListener = modifyListener; + + createControl(parent); + parent.addDisposeListener(this); + } + + /** + * @return the searchText + */ + public StyledText getSearchText() { + return searchText; + } + + /** + * @return the resultViewer + */ + public TreeViewer getResultViewer() { + return resultViewer; + } + + /** + * @param parent + */ + private void createControl(Composite parent) { + + GridLayout parentLayout = new GridLayout(); + //parentLayout.marginTop = 2; + parentLayout.marginLeft = 0; + parentLayout.horizontalSpacing = 0; + parentLayout.verticalSpacing = 0; + parentLayout.marginWidth = 0; + parentLayout.marginHeight = 2; + parent.setLayout( parentLayout ); + + Composite textComposite = new Composite(parent, SWT.NONE); + GridData textCompositeGridData = new GridData(GridData.FILL, GridData.BEGINNING, true, false); + textComposite.setLayoutData( textCompositeGridData ); + + GridLayout layout = new GridLayout(2, false); + layout.marginLeft = 2; + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + layout.marginWidth = 0; + layout.marginHeight = 0; + textComposite.setLayout( layout ); + + createSearchTextControl( textComposite ); + createFilterBar(textComposite); + + Composite viewComposite = new Composite(parent, SWT.NONE); + viewComposite.setLayoutData( new GridData(GridData.FILL, GridData.FILL, true, true) ); + FillLayout fillLayout = new FillLayout(); + fillLayout.marginHeight = 0; + fillLayout.marginWidth = 0; + fillLayout.spacing = 0; + viewComposite.setLayout( fillLayout ); + + resultViewer = new TreeViewer(viewComposite, SWT.FULL_SELECTION); + } + + private void createFilterBar(Composite parent) { + + filterBar = new ToolBar(parent, SWT.FLAT | SWT.RIGHT); + GridData gridData = new GridData(GridData.END, GridData.CENTER, false, false); + filterBar.setLayoutData(gridData); + + ToolItem clearItem = new ToolItem(filterBar, SWT.NONE); + clearItem.setImage( getPluginImage("close") ); + clearItem.setToolTipText("Clear search text"); + clearItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + searchText.setText(""); + searchText.setFocus(); + } + }); + + new ToolItem(filterBar, SWT.SEPARATOR); + itemInsertIndex = filterBar.getItemCount(); // so we insert after separator + + ToolItem filterItem = new ToolItem(filterBar, SWT.DROP_DOWN); + filterItem.setToolTipText("Filter by..."); + filterItem.setImage( getPluginImage("filter") ); + + DropdownMenuProvider dropdown = new DropdownMenuProvider(filterItem); + dropdown.add( new ProjFilterAction(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(SharedImages.IMG_OBJ_PROJECT)) ); + dropdown.add( new ExtensionFilterAction(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJ_FILE)) ); + dropdown.add( new FieldFilterAction(Field.WS, InstaSearchPlugin.getImageDescriptor("workingsets")) ); + dropdown.add( new FieldFilterAction(Field.MODIFIED, InstaSearchPlugin.getImageDescriptor("dates")) ); + + filterBar.update(); + } + + private abstract class FilterChangeAction extends Action + { + public FilterChangeAction(String proposal, ImageDescriptor imageDescriptor) { + super(proposal, imageDescriptor); + } + + public FilterChangeAction(String string) { + super(string); + } + + @Override + final public void run() { + runAction(); + updateSearch(); + } + + abstract protected void runAction(); + } + + private class FieldFilterAction extends FilterChangeAction + { + private Field field; + + public FieldFilterAction(Field field, ImageDescriptor img) { + super(field.getTitle(), img); + + this.field = field; + } + + protected Image getImage(String proposal) + { + String key = field + ":" + proposal; + Image img = imageRegistry.get(key); + + if( img == null ) img = imageRegistry.get(field + ":"); + + if( img == null ) + { + imageRegistry.put(key, getImageDescriptor()); + img = imageRegistry.get(key); + } + + return img; + } + + @Override + public void runAction() { + + final ToolItem fieldItem = new ToolItem(filterBar, SWT.DROP_DOWN, itemInsertIndex); + fieldItem.setToolTipText("Filter by " + field.getTitle()); + fieldItem.setImage( getImage("") ); + fieldItem.setData(field); + + DropdownMenuProvider dropdown = new DropdownMenuProvider(fieldItem); + addRemoveAction(fieldItem, dropdown); + dropdown.addSeparator(); + + List proposals = proposalProvider.getFieldProposals(field, ""); + FilterChangeAction firstAction = null; + + for(String proposal: proposals) + { + FilterChangeAction action = addAction(dropdown, proposal); + + if( firstAction == null ) firstAction = action; + } + + if( "".equals(fieldItem.getText()) && firstAction != null ) + firstAction.run(); + + parent.layout(true, true); + } + + private void addRemoveAction(final ToolItem fieldItem, + DropdownMenuProvider dropdown) + { + FilterChangeAction removeAction = new FilterChangeAction("Remove") { + @Override + public void runAction() { + fieldItem.dispose(); + parent.layout(true, true); + } + }; + removeAction.setImageDescriptor(InstaSearchPlugin.getImageDescriptor("close")); + dropdown.add(removeAction); + } + + /** + * @param dropdown + * + */ + protected FilterChangeAction addAction(final DropdownMenuProvider dropdown, final String proposal) + { + FilterChangeAction action = new FilterChangeAction(proposal, getImageDescriptor()) + { + @Override + public void runAction() + { + dropdown.getToolItem().setText(getText()); + dropdown.getToolItem().setImage(getImage(proposal)); + parent.layout(true, true); + } + }; + + dropdown.add(action); + return action; + } + } + + private class ProjFilterAction extends FieldFilterAction + { + public ProjFilterAction(ImageDescriptor img) { + super(Field.PROJ, img); + } + + @Override + protected FilterChangeAction addAction( + DropdownMenuProvider dropdown, + String proposal) { + + FilterChangeAction action = super.addAction(dropdown, proposal); + + if( proposal.equals(InstaSearchUI.getActiveProject()) ) // active project + action.run(); // add it + + return action; + } + } + + private class ExtensionFilterAction extends FieldFilterAction + { + public ExtensionFilterAction(ImageDescriptor img) { + super(Field.EXT, img); + } + + @Override + protected Image getImage(String proposal) { + + getExtImageDescriptor(proposal); + + return imageRegistry.get(Field.EXT + ":" + proposal); + } + + @Override + protected FilterChangeAction addAction(DropdownMenuProvider dropdown, String proposal) { + FilterChangeAction action = super.addAction(dropdown, proposal); + ImageDescriptor imgDesc = getExtImageDescriptor(proposal); + + if( imgDesc != null ) + action.setImageDescriptor(imgDesc); + + IEditorPart editor = InstaSearchUI.getActiveEditor(); + + if( editor != null ) + { + IAdaptable adaptable = editor.getEditorInput(); + + if( adaptable != null ) + { + // get current edited file + IResource res = (IResource) adaptable.getAdapter(IResource.class); + + if( res != null && proposal.equals(res.getFileExtension())) + action.run(); // set as active extension + } + } + + return action; + } + } + + private void updateSearch() + { + modifyListener.modifyText(null); // notify view + } + + private void createSearchTextControl(Composite textComposite) { + searchText = new StyledText(textComposite, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.CANCEL); + + textComposite.setTabList(new Control[]{searchText}); + + GridData searchTextGridData = new GridData(GridData.FILL, GridData.CENTER, true, false); + searchText.setLayoutData( searchTextGridData ); + + FocusListener focusListener = new FocusListener() { // to set search tip + + public void focusGained(FocusEvent e) + { + if (searchText.isDisposed()) + return; + + if( isShowingSearchTip() ) + { + searchText.setForeground( defaultSearchColor ); + + if( SEARCH_TEXT_TIP.equals(searchText.getText()) ) + searchText.setText(""); + } + } + + public void focusLost(FocusEvent e) + { + if( searchText.getText().length() == 0 ) + { + searchText.setForeground( searchTipColor ); + searchText.setText(SEARCH_TEXT_TIP); + } + } + }; + + searchText.addFocusListener(focusListener); + + searchText.setToolTipText(SEARCH_TEXT_TIP + "\n(" + PROPOSAL_KEYSTROKE + " for autocompletion)"); + } + + public boolean isShowingSearchTip() + { + return searchText.getForeground().equals( searchTipColor ); + } + + /** + * @return display + * + */ + private Display getDisplay() { + return Display.getCurrent(); + } + + public void setContentProposalAdapter(SearchContentProposalProvider provider) + { + this.proposalProvider = provider; + KeyStroke keyStroke = null; + + try { + keyStroke = KeyStroke.getInstance(PROPOSAL_KEYSTROKE); + } catch(Exception e) { + InstaSearchPlugin.log(e); + } + + char[] autoActivationCharacters = new char[]{':', ','}; + + ContentProposalAdapter adapter = new SearchContentProposalAdapter( + searchText, new StyledTextContentAdapter(), + provider, keyStroke, autoActivationCharacters ); + + adapter.setPopupSize(new Point(300, 150)); + adapter.setPropagateKeys(true); + adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE); + } + + private Image getPluginImage(String name) + { + Image img = imageRegistry.get(name); + if( img == null ) + { + imageRegistry.put(name, InstaSearchPlugin.getImageDescriptor(name)); + img = imageRegistry.get(name); + } + + return img; + } + + private ImageDescriptor getExtImageDescriptor(String ext) + { + String key = Field.EXT + ":" + ext; + ImageDescriptor fileImage = imageRegistry.getDescriptor(key); + + if( fileImage == null ) { + IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry(); + fileImage = registry.getImageDescriptor("*." + ext); + imageRegistry.put(key, fileImage); // cache created images for extensions + } + + return fileImage; + } + + public void widgetDisposed(DisposeEvent e) { + imageRegistry.dispose(); + } + + private class SearchContentProposalAdapter extends ContentProposalAdapter + { + /** + * @param control + * @param controlContentAdapter + * @param proposalProvider + * @param keyStroke + * @param autoActivationCharacters + */ + public SearchContentProposalAdapter(Control control, + IControlContentAdapter controlContentAdapter, + IContentProposalProvider proposalProvider, KeyStroke keyStroke, + char[] autoActivationCharacters) + { + super(control, controlContentAdapter, proposalProvider, keyStroke, + autoActivationCharacters); + } + + @Override + protected void closeProposalPopup() { // workaround to keep popup open + String content = getControlContentAdapter().getControlContents(getControl()); + int pos = getControlContentAdapter().getCursorPosition(getControl()); + + if( content.length() == 0 || pos == 0 ) { + super.closeProposalPopup(); + return; + } + + String prefix = content.substring(0, pos); + if( prefix.length() == 0 || prefix.endsWith(" ") ) { + super.closeProposalPopup(); + return; + } + + } + + @Override + public int getProposalAcceptanceStyle() { // workaround to have the popup at insert positon + return ContentProposalAdapter.PROPOSAL_INSERT; + } + } + + public Map> getFilter() + { + HashMap> filters = new HashMap>(); + + for(ToolItem item: filterBar.getItems()) + { + Object data = item.getData(); + if( data== null ) continue; + if( data instanceof Field ) + { + Field field = (Field) data; + String value = item.getText(); + + if( "".equals(value) ) continue; + + Set values = filters.get(field); + if( values == null ) { + values = new TreeSet(); + filters.put(field, values); + } + values.add(value); + } + } + + return filters; + } + + /** + * @param filter + */ + public void setFilter(Map> filter) + { + clearFilter(); + + + } + + private void clearFilter() + { + for(ToolItem item: filterBar.getItems()) + { + Object data = item.getData(); + if( data== null ) continue; + if( data instanceof Field ) + item.dispose(); + } + } +} diff --git a/instasearch/src/it/unibz/instasearch/ui/StyledTextContentAdapter.java b/instasearch/src/it/unibz/instasearch/ui/StyledTextContentAdapter.java new file mode 100755 index 0000000..76357e6 --- /dev/null +++ b/instasearch/src/it/unibz/instasearch/ui/StyledTextContentAdapter.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.ui; + +import org.eclipse.jface.fieldassist.TextContentAdapter; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Control; + +/** + * @see org.eclipse.jface.fieldassist.TextContentAdapter + */ +public class StyledTextContentAdapter extends TextContentAdapter +{ + @Override + public String getControlContents(Control control) { + return ((StyledText) control).getText(); + } + + @Override + public void setControlContents(Control control, String text, + int cursorPosition) { + ((StyledText) control).setText(text); + ((StyledText) control).setSelection(cursorPosition, cursorPosition); + } + + @Override + public void insertControlContents(Control control, String text, + int cursorPosition) { + Point selection = ((StyledText) control).getSelection(); + ((StyledText) control).insert(text); + + if (cursorPosition < text.length()) { + ((StyledText) control).setSelection(selection.x + cursorPosition, + selection.x + cursorPosition); + } + } + + @Override + public int getCursorPosition(Control control) { + return ((StyledText) control).getCaretOffset(); + } + + @Override + public Rectangle getInsertionBounds(Control control) { + StyledText text = (StyledText) control; + Point caretOrigin = text.getCaret().getLocation(); + + return new Rectangle(caretOrigin.x + text.getClientArea().x, + caretOrigin.y + text.getClientArea().y + 3, 1, text.getLineHeight()); + } + + @Override + public void setCursorPosition(Control control, int position) { + ((StyledText) control).setSelection(new Point(position, position)); + } + + @Override + public Point getSelection(Control control) { + return ((StyledText) control).getSelection(); + } + + @Override + public void setSelection(Control control, Point range) { + ((StyledText) control).setSelection(range); + } +} diff --git a/instasearch/test/it/unibz/instasearch/indexing/SearcherTest.java b/instasearch/test/it/unibz/instasearch/indexing/SearcherTest.java new file mode 100755 index 0000000..e6f8f1f --- /dev/null +++ b/instasearch/test/it/unibz/instasearch/indexing/SearcherTest.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.List; + +import org.apache.lucene.index.IndexWriter; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.runtime.CoreException; +import org.junit.Before; +import org.junit.Test; + +/** + * + */ +public class SearcherTest +{ + private TestSearcher searcher; + private StorageIndexer indexer; + + @Before + public void setUp() throws IOException, CoreException + { + this.indexer = new StorageIndexer(); + indexTestFiles(); + this.searcher = new TestSearcher(indexer.getIndexDir()); + } + + @Test + public void testSimpleText() throws Exception + { + List docs = search("unique"); + assertEquals(1, docs.size()); + + docs = search("another"); + assertEquals(3, docs.size()); + + docs = search("another other"); + assertEquals(2, docs.size()); + + docs = search("another_other"); + assertEquals(4, docs.size()); + } + + @Test + public void testCodeSearches() throws Exception + { + assertFileMatches("file5.txt", "HTTP_REFERER"); + assertFileMatches("file5.txt", "HTTP_REFER"); + assertFileMatches("file5.txt", "attp refered"); // approximate + assertFileMatches("file5.txt", "$_POST['HTTP_REFERER']"); + assertFileMatches("file5.txt", "redirect($_POST['HTTP_REFERER']);"); + assertFileMatches("file5.txt", "redirect http referer"); + + assertFileMatches("file6.txt", "TOPIC_OF_INTEREST"); + assertFileMatches("file6.1.txt", "\"TOPIC OF INTEREST\""); + assertFileMatches("file6.txt", "iNTEReST TOpIc"); + + List docs = search("TOPIC_OF_INTEREST"); + assertEquals(1, docs.size()); // contain topic + + docs = search("TOPIC"); + assertEquals(4, docs.size()); // contain topic + + assertFileMatches("file7.txt", "driveLetter"); + assertFileMatches("file7.txt", "server.driveLetter"); + assertFileMatches("file7.txt", "server driveLetter"); + assertFileMatches("file7.txt", "server drive Letter"); + assertFileMatches("file7.txt", "getText(server.driveLetter, int a);"); + assertFileMatches("file7.txt", "getString(my.variable, int var2) { }"); + + assertFileMatches("file1.txt", "file1.txt", "file8.txt"); + assertFileMatches("file2.txt", "file2.txt", "file8.txt"); + assertFileMatches("file4.xml", "file4.xml", "file8.txt"); + + assertFileMatches("file9.txt", "idl_Ty"); + assertFileMatches("file10.txt", "idlTypeForNonGeneratedPorts"); + assertFileMatches("file10.txt", "idl Type For_Non"); + + assertFileMatches("file11.txt", "pointer->execMethod"); + assertFileMatches("file11.txt", "test3_mtdDecl"); + } + + @Test + public void testCamelCaseSearch() throws Exception + { + assertFileMatches("file12.txt", "mainTopicHandler"); + assertFileMatches("file4.xml", "MyFirstServer"); + } + + @Test + public void testFieldSearches() throws Exception + { + assertFileMatches("file8.txt", "name:file8.txt"); + assertFileMatches("file8.txt", "name:file8"); + assertFileMatches("file8.txt", "name:file8*"); + + assertFileMatches("FileWithoutExtension", "name:FWE"); + assertFileMatches("FileWithoutExtension", "without extension"); + assertFileMatches("FileWithoutExtension", "FileWithoutExtension"); + assertFileMatches("FileWithoutExtension", "FileWithoutExt"); + + assertFileMatches("file4.xml", "ext:xml"); + + List docs = search("proj:proj1"); + assertEquals(11, docs.size()); + + docs = search("proj:\"proj three\""); + assertEquals(3, docs.size()); + } + + @Test + public void testWildcardExcludeFilters() + { + + } + + private void assertFileMatches(String expectedFile, String searchString, String...otherFiles) throws Exception + { + List docs = search(searchString); + assertEquals(expectedFile, docs.get(0).getFileName()); + + assertEquals(true, docs.size() > otherFiles.length); + + for(int i = 0; i < otherFiles.length && i+1 < docs.size(); i++) + { + assertEquals(otherFiles[i], docs.get(i+1).getFileName()); + } + } + + private void indexTestFiles() throws IOException, CoreException + { + IndexWriter writer = indexer.createIndexWriter(true); + + indexFile(writer, "/path/FileWithoutExtension", "a file without an extension"); + + indexFile(writer, "/path/file1.txt", "this is a text file with some unique contents"); + indexFile(writer, "/path/file2.txt", "this is another text file with some other contents"); + indexFile(writer, "/path/file3.txt", "this is yet another text file with some other contents"); + + indexFile(writer, "/path/file4.xml", "", "proj2"); + indexFile(writer, "/path/file5.txt", "if(true)\n{redirect($_POST['HTTP_REFERER']);\n}", "proj three"); + indexFile(writer, "/path/file6.txt", "this is yet another text file with TOPIC_OF_INTEREST"); + indexFile(writer, "/path/file6.1.txt", "this is some other text file with TOPIC of INTEREST", "proj three"); + indexFile(writer, "/path/file6.2.txt", "this file contains a TOPIC", "proj three"); + indexFile(writer, "/path/file7.txt", "getText(server.driveLetter, int a); getString(my.variable, int var2) { }"); + + indexFile(writer, "/path/file8.txt", "/path/file1.txt \"file2.txt\" file3.txt;file4.xml"); + indexFile(writer, "/path/file9.txt", ""); + indexFile(writer, "/path/file10.txt", "String s = \"idlTypeForNonGeneratedPorts\";"); + indexFile(writer, "/path/file11.txt", "pointer->execMethod(); new Main()->test3_mtdDecl();"); + indexFile(writer, "/path/file12.txt", "public void mainTopicHandler(){ }"); + + writer.close(); + } + + private void indexFile(IndexWriter writer, String path, String contents) throws CoreException, IOException + { + indexFile(writer, path, contents, "proj1"); + } + + private void indexFile(IndexWriter writer, String path, String contents, String proj) throws CoreException, IOException + { + IStorage file1 = new TestStorage(path, contents); + + indexer.indexStorage(writer, file1, proj, System.currentTimeMillis(), null); + } + + private List search(String searchString) throws Exception + { + SearchResult res = searcher.search(new SearchQuery(searchString, SearchQuery.UNLIMITED_RESULTS)); + return res.getResultDocs(); + } +} diff --git a/instasearch/test/it/unibz/instasearch/indexing/TestSearcher.java b/instasearch/test/it/unibz/instasearch/indexing/TestSearcher.java new file mode 100755 index 0000000..a7f9247 --- /dev/null +++ b/instasearch/test/it/unibz/instasearch/indexing/TestSearcher.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import java.io.IOException; + +import org.apache.lucene.store.Directory; +import org.junit.Ignore; + +@Ignore +class TestSearcher extends Searcher +{ + private Directory dir; + + public TestSearcher(Directory dir) { + this.dir = dir; + } + + @Override + protected Directory getIndexDir() throws IOException { + return dir; + } + + @Override + protected void initPrefs() { + } +} \ No newline at end of file diff --git a/instasearch/test/it/unibz/instasearch/indexing/TestStorage.java b/instasearch/test/it/unibz/instasearch/indexing/TestStorage.java new file mode 100755 index 0000000..d316bef --- /dev/null +++ b/instasearch/test/it/unibz/instasearch/indexing/TestStorage.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009 Andrejs Jermakovics. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrejs Jermakovics - initial implementation + */ +package it.unibz.instasearch.indexing; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.junit.Ignore; + +@Ignore +class TestStorage implements IStorage +{ + private IPath path; + private InputStream contents; + + TestStorage(String fullPath, String contentsText) + { + this(fullPath, new ByteArrayInputStream(contentsText.getBytes())); + } + + private TestStorage(String fullPath, InputStream contents) + { + this.path = new Path(fullPath); + this.contents = contents; + } + + public InputStream getContents() throws CoreException { + return contents; + } + + public IPath getFullPath() { + return path; + } + + public String getName() { + return path.lastSegment(); + } + + public boolean isReadOnly() { + return false; + } + + @SuppressWarnings("rawtypes") + public Object getAdapter(Class adapter) { + return null; + } +} \ No newline at end of file