From 3c7c4a749baafcf375f4785a7668d3a25c9063e3 Mon Sep 17 00:00:00 2001 From: lresende Date: Fri, 13 Nov 2009 01:42:27 +0000 Subject: Moving 1.x trunk git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835700 13f79535-47bb-0310-9956-ffa450edef68 --- .../tuscany/sca/domain/search/DocumentMap.java | 60 ++++ .../sca/domain/search/DocumentProcessor.java | 64 ++++ .../sca/domain/search/DocumentProcessorsMap.java | 106 ++++++ .../tuscany/sca/domain/search/DomainSearch.java | 108 ++++++ .../tuscany/sca/domain/search/IndexException.java | 45 +++ .../apache/tuscany/sca/domain/search/Result.java | 121 +++++++ .../tuscany/sca/domain/search/ResultFactory.java | 51 +++ .../tuscany/sca/domain/search/ResultProcessor.java | 50 +++ .../search/impl/ArtifactDocumentProcessor.java | 107 ++++++ .../search/impl/BindingDocumentProcessor.java | 82 +++++ .../search/impl/ComponentDocumentProcessor.java | 200 +++++++++++ .../impl/ComponentTypeDocumentProcessor.java | 186 +++++++++++ .../search/impl/CompositeDocumentProcessor.java | 128 +++++++ .../search/impl/ContributionDocumentProcessor.java | 154 +++++++++ .../sca/domain/search/impl/DefaultFileContent.java | 57 ++++ .../search/impl/DefaultFileDocumentProcessor.java | 87 +++++ .../tuscany/sca/domain/search/impl/Document.java | 113 +++++++ .../sca/domain/search/impl/DomainPathAnalyzer.java | 233 +++++++++++++ .../domain/search/impl/DomainSearchAnalyzer.java | 36 ++ .../impl/DomainSearchDocumentProcessorsMap.java | 50 +++ .../impl/DomainSearchFileDocumentProcessor.java | 35 ++ .../domain/search/impl/DomainSearchFormatter.java | 68 ++++ .../sca/domain/search/impl/DomainSearchImpl.java | 371 +++++++++++++++++++++ .../search/impl/DomainSearchResultFactory.java | 40 +++ .../search/impl/DomainSearchResultProcessor.java | 40 +++ .../sca/domain/search/impl/FileContent.java | 40 +++ .../search/impl/FileContentResultProcessor.java | 105 ++++++ .../domain/search/impl/FileDocumentProcessor.java | 108 ++++++ .../sca/domain/search/impl/HighlightingUtil.java | 186 +++++++++++ .../sca/domain/search/impl/NamingAnalyzer.java | 48 +++ .../sca/domain/search/impl/NamingTokenizer.java | 149 +++++++++ .../sca/domain/search/impl/ParentField.java | 206 ++++++++++++ .../impl/PriorityFieldListResultFactory.java | 58 ++++ .../search/impl/PropertyDocumentProcessor.java | 88 +++++ .../tuscany/sca/domain/search/impl/ResultImpl.java | 270 +++++++++++++++ .../domain/search/impl/ResultProcessorList.java | 186 +++++++++++ .../sca/domain/search/impl/SearchFields.java | 73 ++++ .../sca/domain/search/impl/SystemFileContent.java | 76 +++++ .../sca/domain/search/impl/WrappedFileContent.java | 73 ++++ .../domain/search/impl/ZipDocumentProcessor.java | 103 ++++++ .../sca/domain/search/impl/ZipFileContent.java | 321 ++++++++++++++++++ 41 files changed, 4682 insertions(+) create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentMap.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentProcessorsMap.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DomainSearch.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/IndexException.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/Result.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/ResultFactory.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/ResultProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ArtifactDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/BindingDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ComponentDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ComponentTypeDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/CompositeDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ContributionDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DefaultFileContent.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DefaultFileDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/Document.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainPathAnalyzer.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchAnalyzer.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchDocumentProcessorsMap.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchFileDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchFormatter.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchImpl.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchResultFactory.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchResultProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileContent.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileContentResultProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/HighlightingUtil.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/NamingAnalyzer.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/NamingTokenizer.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ParentField.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/PriorityFieldListResultFactory.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/PropertyDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ResultImpl.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ResultProcessorList.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/SearchFields.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/SystemFileContent.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/WrappedFileContent.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ZipDocumentProcessor.java create mode 100644 sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ZipFileContent.java (limited to 'sca-java-1.x/trunk/modules/domain-search/src/main/java/org') diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentMap.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentMap.java new file mode 100644 index 0000000000..47deb41a6f --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentMap.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search; + +import java.util.HashMap; + +import org.apache.tuscany.sca.domain.search.impl.Document; + +/** + * A map that holds a collection of {@link Document}s. Each {@link Document} key + * should ideally be something that is unique across the entire contribution + * documents. This class overrides {@link HashMap#get(Object)} method, so it + * adds an empty {@link Document} object if the specified key is not found in + * the map. + * + * @version $Rev$ $Date$ + */ +public class DocumentMap extends HashMap { + + private static final long serialVersionUID = -2402910290314939928L; + + /** + * Returns a {@link Document} object mapped from the specified key. If no + * {@link Document} object is found from the specified key, a empty + * {@link Document} object is created and added to the map. + * + * @param key the {@link Document} key + * @return the {@link Document} object mapped from the key + */ + @Override + public Document get(Object key) { + Document doc = super.get(key); + + if (doc == null) { + doc = new Document(); + put(key, doc); + + } + + return doc; + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentProcessor.java new file mode 100644 index 0000000000..0f183e8875 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentProcessor.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search; + +import org.apache.tuscany.sca.domain.search.impl.Document; + +/** + * A {@link DocumentProcessor} implementations knows how to extract data from a + * contribution {@link Object}. The extract data is added to a {@link Document}, + * which is stored in a {@link DocumentMap}. + * + * @version $Rev$ $Date$ + */ +public interface DocumentProcessor { + + final public static Document FAKE_DOCUMENT = new Document(); + + /** + * Process a contribution {@link Object}, extracting from it data that + * should be indexed. The data should be add to a {@link Document} object, + * which can be found accessing the {@link DocumentMap} if it's not passed + * as an argument. The key used to find the {@link Document} object should + * be the one returned by {@link #getDocumentKey(Object)} method. + * + * @param parentProcessor the processor that invoked this processor, if any + * @param documents the {@link DocumentMap} object + * @param object the object where data should be extracted from + * @param document the {@link Document} object to store the extracted data + * @param parent string that represent the object's parent path in the + * contribution + * @return the resulted {@link Document} object + */ + Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document document, + String parent); + + /** + * Returns a object key generated from object passed as argument. The key + * should be unique in a contribution. + * + * @param object the object + * @return a key generated from the object + */ + Object getDocumentKey(Object object); + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentProcessorsMap.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentProcessorsMap.java new file mode 100644 index 0000000000..3f8ae0026b --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DocumentProcessorsMap.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search; + +import java.util.HashMap; + +import org.apache.tuscany.sca.domain.search.impl.Document; + +/** + * This class is a {@link DocumentProcessor} that holds a map from {@link Class} + * -> {@link DocumentProcessor}, and based on this map this processor delegates + * the object to be processed to its respective {@link DocumentProcessor}. + * + * @version $Rev$ $Date$ + */ +public class DocumentProcessorsMap extends HashMap, DocumentProcessor> implements DocumentProcessor { + + private static final long serialVersionUID = 3967390896890947159L; + + private DocumentProcessor findDocumentProcessor(Object object, Class clazz) { + DocumentProcessor processor = get(clazz); + + if (processor == null) { + Class[] interfaces = clazz.getInterfaces(); + + for (Class interfac : interfaces) { + processor = findDocumentProcessor(object, interfac); + + if (processor != null) { + return processor; + } + + } + + if (!clazz.isInterface()) { + return findDocumentProcessor(object, clazz.getSuperclass()); + } + + } + + return processor; + + } + + /** + * @see DocumentProcessor#getDocumentKey(Object) + */ + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document document, + String parent) { + + DocumentProcessor processor = findDocumentProcessor(object, object.getClass()); + + if (processor == null) { + throw new IllegalArgumentException(); + } + + if (document == null) { + document = documents.get(processor.getDocumentKey(object)); + + if (document == null) { + document = FAKE_DOCUMENT; + } + + } + + processor.process(parentProcessor, documents, object, document, parent); + + return document; + + } + + /** + * @see DocumentProcessor#getDocumentKey(Object) + */ + public Object getDocumentKey(Object object) { + DocumentProcessor processor = findDocumentProcessor(object, object.getClass()); + + if (processor != null) { + return processor.getDocumentKey(object); + + } else { + return null; + } + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DomainSearch.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DomainSearch.java new file mode 100644 index 0000000000..be7f603b0b --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/DomainSearch.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search; + +import java.io.IOException; + +import org.apache.lucene.index.CorruptIndexException; +import org.apache.lucene.queryParser.ParseException; +import org.apache.lucene.search.Query; +import org.apache.tuscany.sca.contribution.Contribution; +import org.osoa.sca.annotations.Remotable; + +/** + * This is the interface that must be implemented by the service that provides + * the functionality index/search and search contribution data. + * + * @version $Rev$ $Date$ + */ +@Remotable +public interface DomainSearch { + + /** + * Returns true if the index is somehow created already, otherwise false. + * + * @return true if the index is somehow created already, otherwise false + */ + boolean indexExists(); + + /** + * Parse a query string, execute it against the index and return the results. + * + * @param searchQuery the string containing the search query + * @param highlight true if the results should be highlighted + * + * @return an array containing the search results + * + * @throws CorruptIndexException + * @throws IOException + * @throws ParseException + */ + Result[] parseAndSearch(String searchQuery, boolean highlight) throws IndexException, ParseException; + + /** + * Executes a search query against the index and return the results. + * + * @param searchQuery the search query + * @param hightlight highlight true if the results should be highlighted + * + * @return an array containing the search results + * + * @throws CorruptIndexException + * @throws IOException + */ + Result[] search(Query searchQuery, boolean hightlight) throws IndexException; + + /** + * Highlights in the specified text strings that matches the specified search query. The matches can be filtered by field. + * + * @param field the field to filter + * @param text the text to be highlighted + * @param searchQuery the search query + * + * @return the text highlighted + * + * @throws ParseException + * @throws IOException + */ + String highlight(String field, String text, String searchQuery) throws ParseException; + + /** + * Adds a contribution to the index. + * + * @param contribution the contribution to be added + */ + void addContribution(Contribution contribution) throws IndexException; + + /** + * Removes a contribution from the index. + * + * @param contribution the contribution to be removed + */ + void removeContribution(Contribution contribution) throws IndexException; + + /** + * Updates a contribution in the index. + * + * @param oldContribution the old contribution state + * @param contribution the new contribution state + */ + void updateContribution(Contribution oldContribution, Contribution contribution) throws IndexException; + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/IndexException.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/IndexException.java new file mode 100644 index 0000000000..6c74c86387 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/IndexException.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.tuscany.sca.domain.search; + +/** + * Exception thrown when a exception occurs while accessing the index. + * + * @version $Rev$ $Date$ + */ +public class IndexException extends Exception { + + private static final long serialVersionUID = -6395734136706805723L; + + /** + * @see Exception#Exception(String) + */ + public IndexException(String message) { + super(message); + } + + /** + * @see Exception#Exception(String,Throwable) + */ + public IndexException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/Result.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/Result.java new file mode 100644 index 0000000000..edbebac6b4 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/Result.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search; + +import java.io.Serializable; +import java.util.Map; + +/** + *

+ * The object that implements this interface carries a search's result data. + *

+ *

+ * A result contains a value, which is the value displayed to the user. It also + * contains a field name, which is the field the value is related to. + *

+ *

+ * A search result may be split into different {@link Result} objects, each one + * contained inside other, representing a complex result hierarchy. For example: + * a result structure may represent as result a folder and files/folders + * contained in it. + *

+ * + * @see ResultProcessor + * @see ResultFactory + * + * @version $Rev$ $Date$ + */ +public interface Result extends Serializable { + + /** + * Returns the value held by this object. + * + * @return the value held by this object + */ + String getValue(); + + /** + * Sets the result value. + * + * @param value the result value + */ + void setValue(String value); + + /** + * Returns the {@link Result} object that contains this object or + * null if it's not contained in any object. + * + * @return the {@link Result} object that contains this object or + * null if it's not contained in any object + */ + Result getContainer(); + + /** + * A {@link Map} containing {@link Result} objects contained in this + * {@link Object}. The contents are mapped from a key, which may be any kind + * of identifier, the identifier is chosen by the {@link Result} + * implementation. + * + * @return the contents map + */ + Map getContents(); + + /** + * Adds a {@link Result} content to this result. + * + * @param artifactResult the {@link Result} content + * @throw {@link UnsupportedOperationException} if the {@link Result} + * implementations does not support this operation + * @see #getContents() + */ + void addContent(Result artifactResult); + + /** + * Removes a {@link Result} content from this result. + * + * @param artifactResult the {@link Result} content + * @throw {@link UnsupportedOperationException} if the {@link Result} + * implementations does not support this operation + * @see #getContents() + */ + void removeContent(Result artifactResult); + + /** + * Sets this object's container. + * + * @param container the object's container + * @see #getContainer() + */ + void setContainer(Result container); + + /** + * Returns the field related to the result's value. + * + * @return the field name + */ + String getField(); + + /** + * Sets the field related to the result's value. + * + * @param field the field name + */ + void setField(String field); + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/ResultFactory.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/ResultFactory.java new file mode 100644 index 0000000000..7a4fb1f5f4 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/ResultFactory.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search; + +import org.apache.lucene.document.Document; + +/** + * This interface should be implemented to provide a way to create + * {@link Result} objects from a field name and its value or a {@link Document} + * resulted from a search. + * + * @see Result + * @version $Rev$ $Date$ + */ +public interface ResultFactory { + + /** + * Creates a {@link Result} instance from a field name and its value. + * + * @param field the field name + * @param value the value + * @return the {@link Result} instance + */ + T createResult(String field, String value); + + /** + * Creates a {@link Result} instance from a {@link Document} object resulted + * from a search. + * + * @param document the result {@link Document} + * @return the {@link Result} instance + */ + T createResult(Document document); + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/ResultProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/ResultProcessor.java new file mode 100644 index 0000000000..8dee35623e --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/ResultProcessor.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search; + +import org.apache.lucene.document.Document; + +/** + * This interface should be implemented by classes that process a + * {@link Document} object resulted from a search and create a {@link Result} + * object from it. + * + * @version $Rev$ $Date$ + */ +public interface ResultProcessor { + + /** + *

+ * Process the {@link Document} object and returns a {@link Result} object + * containing the processed data. + *

+ *

+ * A {@link Result} object may be specified to hold the processed data. If + * no object is specified, the implementation must create a new object a + * return it. + *

+ * + * @param document the {@link Document} object resulted from a search + * @param result the {@link Result} object that will hold the processed data + * or null a new object should be returned. + * @return a {@link Result} object containing the processed data + */ + Result process(Document document, Result result); + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ArtifactDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ArtifactDocumentProcessor.java new file mode 100644 index 0000000000..fcfce34d88 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ArtifactDocumentProcessor.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.IOException; +import java.net.URL; + +import org.apache.lucene.document.Field; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DocumentProcessor; + +/** + * @version $Rev$ $Date$ + */ +public class ArtifactDocumentProcessor implements DocumentProcessor { + + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document document, + String parent) { + + if (object instanceof Artifact) { + Artifact artifact = (Artifact)object; + + if (!(object instanceof Contribution)) { + + String location = artifact.getLocation(); + + try { + + if (document == null) { + document = documents.get(SearchFields.ARTIFACT_FIELD + location); + } + + FileContent fileContent = new WrappedFileContent(new URL(location)); + + document.add(new Field(SearchFields.ARTIFACT_FIELD, fileContent.getName(), Field.Store.YES, + Field.Index.ANALYZED)); + + parent += + DomainPathAnalyzer.PATH_SEPARATOR + SearchFields.ARTIFACT_FIELD + + DomainPathAnalyzer.TYPE_SEPARATOR + + location + + DomainPathAnalyzer.URI_SEPARATOR + + fileContent.getName(); + + // parent += DomainPathAnalyzer.PATH_SEPARATOR + // + SearchFields.FILE_FIELD + // + DomainPathAnalyzer.TYPE_SEPARATOR + location + + // DomainPathAnalyzer.URI_SEPARATOR + fileContent.getName(); + + Document fileDoc = parentProcessor.process(parentProcessor, documents, fileContent, null, parent); + + fileDoc.add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, Field.Index.ANALYZED)); + + } catch (IOException e) { + // ignore location + } + + } + + return document == null ? FAKE_DOCUMENT : document; + + } + + throw new IllegalArgumentException(); + + } + + public Object getDocumentKey(Object obj) { + + if (obj instanceof Artifact) { + Artifact artifact = (Artifact)obj; + String uri = artifact.getLocation(); + + if (uri != null && uri.length() == 0) { + return null; + } + + return SearchFields.ARTIFACT_FIELD + uri; + + } + + throw new IllegalArgumentException(); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/BindingDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/BindingDocumentProcessor.java new file mode 100644 index 0000000000..6ae0ff3d57 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/BindingDocumentProcessor.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import org.apache.lucene.document.Field; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DocumentProcessor; + +/** + * + * @version $Rev$ $Date$ + */ +public class BindingDocumentProcessor implements DocumentProcessor { + + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document document, + String parent) { + + if (object instanceof Binding) { + Binding binding = (Binding)object; + String uri = binding.getURI(); + + if (uri != null && uri.length() == 0) { + uri = null; + } + + if (uri != null) { + + if (document == null) { + document = documents.get(uri); + } + + document.add(new Field(SearchFields.BINDING_FIELD, uri, Field.Store.YES, Field.Index.ANALYZED)); + + } + + return document == null ? FAKE_DOCUMENT : document; + + } + + throw new IllegalArgumentException(); + + } + + public Object getDocumentKey(Object obj) { + + if (obj instanceof Binding) { + Binding binding = (Binding)obj; + String uri = binding.getURI(); + + if (uri != null && uri.length() == 0) { + return null; + } + + return uri; + + } + + throw new IllegalArgumentException(); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ComponentDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ComponentDocumentProcessor.java new file mode 100644 index 0000000000..28099f055c --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ComponentDocumentProcessor.java @@ -0,0 +1,200 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import org.apache.lucene.document.Field; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DocumentProcessor; +import org.apache.tuscany.sca.domain.search.Result; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * + * @version $Rev$ $Date$ + */ +public class ComponentDocumentProcessor implements DocumentProcessor { + + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document doc, + String parent) { + + if (object instanceof Component) { + Component component = (Component)object; + String uri = component.getURI(); + String name = component.getName(); + + uri = (uri == null ? "" : uri) + (name == null ? "" : name); + + if (uri.length() == 0) { + uri = null; + } + + if (uri != null) { + + if (doc == null) { + doc = documents.get(uri); + } + + parent += + DomainPathAnalyzer.PATH_SEPARATOR + SearchFields.COMPONENT_FIELD + + DomainPathAnalyzer.TYPE_SEPARATOR + + uri + + DomainPathAnalyzer.URI_SEPARATOR + + component.getName(); + + doc.add(new Field(SearchFields.COMPONENT_FIELD, uri, Field.Store.YES, Field.Index.ANALYZED)); + + for (ComponentService service : component.getServices()) { + Document serviceDoc = documents.get(uri + ':' + service.getName()); + + serviceDoc.add(new Field(SearchFields.SERVICE_NAME_FIELD, service.getName(), Field.Store.YES, + Field.Index.ANALYZED)); + + InterfaceContract interfaceContract = service.getInterfaceContract(); + + if (interfaceContract != null) { + + for (Operation operation : interfaceContract.getInterface().getOperations()) { + + serviceDoc.add(new Field(SearchFields.SERVICE_INTERFACE_FIELD, operation.getName(), + Field.Store.YES, Field.Index.ANALYZED)); + + } + + for (Operation operation : interfaceContract.getCallbackInterface().getOperations()) { + + serviceDoc.add(new Field(SearchFields.SERVICE_INTERFACE_CALLBACK_FIELD, + operation.getName(), Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + serviceDoc.add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, Field.Index.ANALYZED)); + + } + + for (ComponentReference reference : component.getReferences()) { + Document referenceDoc = documents.get(uri + ':' + reference.getName()); + + referenceDoc.add(new Field(SearchFields.REFERENCE_NAME_FIELD, reference.getName(), Field.Store.YES, + Field.Index.ANALYZED)); + + InterfaceContract interfaceContract = reference.getInterfaceContract(); + + if (interfaceContract != null) { + + for (Operation operation : interfaceContract.getInterface().getOperations()) { + + referenceDoc.add(new Field(SearchFields.REFERENCE_INTERFACE_FIELD, operation.getName(), + Field.Store.YES, Field.Index.ANALYZED)); + + } + + for (Operation operation : interfaceContract.getCallbackInterface().getOperations()) { + + referenceDoc.add(new Field(SearchFields.REFERENCE_INTERFACE_CALLBACK_FIELD, operation + .getName(), Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + referenceDoc + .add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + Document implementationDoc = + parentProcessor.process(parentProcessor, documents, component.getImplementation(), null, parent); + + if (uri != null && implementationDoc != null) { + + implementationDoc.add(new Field(SearchFields.PARENT_FIELD, uri, Field.Store.YES, Field.Index.ANALYZED)); + + } + + for (ComponentProperty componentProperty : component.getProperties()) { + + Property property = componentProperty.getProperty(); + + if (property != null) { + Document propertyDoc = parentProcessor.process(parentProcessor, documents, property, null, parent); + + if (uri != null) { + propertyDoc.add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, + Field.Index.ANALYZED)); + + } + + } + + } + + return doc == null ? FAKE_DOCUMENT : doc; + + } + + throw new IllegalArgumentException(); + + } + + public Object getDocumentKey(Object obj) { + + if (obj instanceof Component) { + Component component = (Component)obj; + String uri = component.getURI(); + String name = component.getName(); + + uri = (uri == null ? "" : uri) + (name == null ? "" : name); + + if (uri.length() == 0) { + return null; + } + + return uri; + + } + + throw new IllegalArgumentException(); + + } + + public Result processDocument(org.apache.lucene.document.Document document, Result result) { + String componentName = document.get(SearchFields.COMPONENT_FIELD); + + if (componentName != null) { + + } + + return null; + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ComponentTypeDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ComponentTypeDocumentProcessor.java new file mode 100644 index 0000000000..6c6f7e2194 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ComponentTypeDocumentProcessor.java @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import org.apache.lucene.document.Field; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DocumentProcessor; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * + * @version $Rev$ $Date$ + */ +public class ComponentTypeDocumentProcessor implements DocumentProcessor { + + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document doc, + String parent) { + + if (object instanceof ComponentType) { + ComponentType componentType = (ComponentType)object; + String uri = componentType.getURI(); + + if (uri != null && uri.length() == 0) { + uri = null; + } + + if (doc == null) { + + if (uri != null) { + doc = documents.get(uri); + + } else { + doc = FAKE_DOCUMENT; + } + + } + + if (uri != null) { + + parent += + DomainPathAnalyzer.PATH_SEPARATOR + SearchFields.COMPONENT_TYPE_FIELD + + DomainPathAnalyzer.TYPE_SEPARATOR + + uri; + + doc.add(new Field(SearchFields.COMPONENT_TYPE_FIELD, uri, Field.Store.YES, Field.Index.ANALYZED)); + + for (Service service : componentType.getServices()) { + Document serviceDoc = documents.get(uri + ':' + service.getName()); + + serviceDoc.add(new Field(SearchFields.SERVICE_NAME_FIELD, service.getName(), Field.Store.YES, + Field.Index.ANALYZED)); + + InterfaceContract interfaceContract = service.getInterfaceContract(); + + if (interfaceContract != null) { + + Interface interfac = interfaceContract.getInterface(); + + if (interfac != null) { + + for (Operation operation : interfac.getOperations()) { + + serviceDoc.add(new Field(SearchFields.SERVICE_INTERFACE_FIELD, operation.getName(), + Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + interfac = interfaceContract.getCallbackInterface(); + + if (interfac != null) { + + for (Operation operation : interfac.getOperations()) { + + serviceDoc.add(new Field(SearchFields.SERVICE_INTERFACE_CALLBACK_FIELD, operation + .getName(), Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + } + + serviceDoc.add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, Field.Index.ANALYZED)); + + } + + for (Reference reference : componentType.getReferences()) { + Document referenceDoc = documents.get(componentType.getURI() + ':' + reference.getName()); + + referenceDoc.add(new Field(SearchFields.REFERENCE_NAME_FIELD, reference.getName(), Field.Store.YES, + Field.Index.ANALYZED)); + + InterfaceContract interfaceContract = reference.getInterfaceContract(); + + if (interfaceContract != null) { + + for (Operation operation : interfaceContract.getInterface().getOperations()) { + + referenceDoc.add(new Field(SearchFields.REFERENCE_INTERFACE_FIELD, operation.getName(), + Field.Store.YES, Field.Index.ANALYZED)); + + } + + for (Operation operation : interfaceContract.getCallbackInterface().getOperations()) { + + referenceDoc.add(new Field(SearchFields.REFERENCE_INTERFACE_CALLBACK_FIELD, operation + .getName(), Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + referenceDoc + .add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + for (Property property : componentType.getProperties()) { + Document propertyDoc = parentProcessor.process(parentProcessor, documents, property, null, parent); + + if (uri != null) { + + propertyDoc + .add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + return doc; + + } + + throw new IllegalArgumentException(); + + } + + public Object getDocumentKey(Object object) { + + if (object instanceof ComponentType) { + ComponentType componentType = (ComponentType)object; + String uri = componentType.getURI(); + + if (uri == null || uri.length() == 0) { + return null; + + } else { + return uri; + } + + } + + throw new IllegalArgumentException(); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/CompositeDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/CompositeDocumentProcessor.java new file mode 100644 index 0000000000..07002daa8d --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/CompositeDocumentProcessor.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import javax.xml.namespace.QName; + +import org.apache.lucene.document.Field; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DocumentProcessor; + +/** + * + * @version $Rev$ $Date$ + */ +public class CompositeDocumentProcessor implements DocumentProcessor { + + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document doc, + String parent) { + + if (object instanceof Composite) { + Composite composite = (Composite)object; + QName name = composite.getName(); + String uri = (name == null ? "" : name.getNamespaceURI() + ';' + name.getLocalPart()); + + if (uri.length() == 0) { + uri = null; + + } else if (doc == null) { + doc = documents.get(uri); + } + + if (uri != null) { + parent += + DomainPathAnalyzer.PATH_SEPARATOR + SearchFields.COMPOSITE_FIELD + + DomainPathAnalyzer.TYPE_SEPARATOR + + uri; + } + + for (Component component : composite.getComponents()) { + + Document componentDoc = parentProcessor.process(parentProcessor, documents, component, null, parent); + + if (uri != null) { + + componentDoc + .add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + if (uri != null) { + + doc.add(new Field(SearchFields.COMPOSITE_FIELD, uri, Field.Store.YES, Field.Index.ANALYZED)); + + } + + for (Composite include : composite.getIncludes()) { + Document compositeDoc = parentProcessor.process(parentProcessor, documents, include, null, parent); + + if (uri != null) { + + compositeDoc.add(new Field(SearchFields.INCLUDEDBY_FIELD, uri, Field.Store.YES, + Field.Index.ANALYZED)); + + } + + } + + for (Component component : composite.getComponents()) { + Document componentDoc = parentProcessor.process(parentProcessor, documents, component, null, parent); + + if (uri != null) { + + componentDoc + .add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + return doc == null ? FAKE_DOCUMENT : doc; + + } + + throw new IllegalArgumentException(); + + } + + public Object getDocumentKey(Object object) { + + if (object instanceof Composite) { + Composite composite = (Composite)object; + String uri = composite.getURI(); + QName name = composite.getName(); + + uri = (uri == null ? "" : uri) + (name == null ? "" : name.toString()); + + return uri.length() == 0 ? null : uri; + + } + + throw new IllegalArgumentException(); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ContributionDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ContributionDocumentProcessor.java new file mode 100644 index 0000000000..7735f9ef1e --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ContributionDocumentProcessor.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import org.apache.lucene.document.Field; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DocumentProcessor; + +/** + * + * @version $Rev$ $Date$ + */ +public class ContributionDocumentProcessor implements DocumentProcessor { + + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document doc, + String parent) { + + if (object instanceof Contribution) { + Contribution contribution = (Contribution)object; + String uri = contribution.getURI(); + + if (uri != null) { + + if (uri.length() == 0) { + uri = null; + + } else { + + parent += + Character.toString(DomainPathAnalyzer.PATH_START) + SearchFields.CONTRIBUTION_FIELD + + DomainPathAnalyzer.TYPE_SEPARATOR + + uri; + + } + + } + + if (uri != null) { + + if (doc == null) { + doc = documents.get(uri); + } + + doc.add(new Field(SearchFields.CONTRIBUTION_FIELD, uri, Field.Store.YES, Field.Index.ANALYZED)); + + } else { + doc = FAKE_DOCUMENT; + } + + for (Artifact artifact : contribution.getArtifacts()) { + Document artifactDoc = parentProcessor.process(parentProcessor, documents, artifact, null, parent); + + if (uri != null) { + + artifactDoc + .add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, Field.Index.ANALYZED)); + + } + + } + + // for (Import imprt : contribution.getImports()) { + // Document importDoc = processors.process(processors, documents, + // imprt, null); + // + // if (uri != null) { + // + // importDoc.add(new Field(SearchFields.IMPORTEDBY_FIELD, uri, + // Field.Store.YES, Field.Index.ANALYZED)); + // + // } + // + // } + // + // for (Export export : contribution.getExports()) { + // Document exportDoc = processors.process(processors, documents, + // export, null); + // + // if (uri != null) { + // + // exportDoc.add(new Field(SearchFields.EXPORTEDBY_FIELD, uri, + // Field.Store.YES, Field.Index.ANALYZED)); + // + // } + // + // } + + if (!object.getClass().getSimpleName().contains("Workspace")) { + + for (Composite composite : contribution.getDeployables()) { + Document compositeDoc = + parentProcessor.process(parentProcessor, documents, composite, null, parent); + + if (uri != null) { + + compositeDoc.add(new Field(SearchFields.PARENT_FIELD, parent, Field.Store.YES, + Field.Index.ANALYZED)); + + } + + } + + } + + return doc; + + } + + throw new IllegalArgumentException(); + + } + + public Object getDocumentKey(Object object) { + + if (object instanceof Contribution) { + Contribution contribution = (Contribution)object; + String uri = contribution.getURI(); + + if (uri != null && uri.length() == 0) { + return null; + } + + return uri; + + } + + throw new IllegalArgumentException(); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DefaultFileContent.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DefaultFileContent.java new file mode 100644 index 0000000000..1c32d0cb5e --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DefaultFileContent.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +/** + * + * @version $Rev$ $Date$ + */ +public class DefaultFileContent implements FileContent { + + final private URL url; + + public DefaultFileContent(URL url) { + this.url = url; + } + + public FileContent[] getChildren() { + return new FileContent[0]; + } + + public InputStream getInputStream() throws IOException { + return this.url.openStream(); + } + + public String getName() { + return this.url.getFile(); + } + + public String getPath() { + return this.url.getPath(); + } + + public boolean isLeaf() { + return false; + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DefaultFileDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DefaultFileDocumentProcessor.java new file mode 100644 index 0000000000..e997b8f1f2 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DefaultFileDocumentProcessor.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; + +import org.apache.lucene.document.Field; +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DocumentProcessor; + +/** + * + * @version $Rev$ $Date$ + */ +public class DefaultFileDocumentProcessor implements DocumentProcessor { + + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document doc, + String parent) { + + if (object instanceof FileContent) { + FileContent file = (FileContent)object; + + Reader reader; + try { + reader = new InputStreamReader(file.getInputStream()); + + if (doc == null) { + doc = documents.get(file.getPath()); + } + + doc.add(new Field(SearchFields.FILE_CONTENT_FIELD, reader)); + + doc.add(new Field(SearchFields.FILE_CONTENT_FIELD, "", Field.Store.YES, Field.Index.ANALYZED)); + + return doc; + + } catch (IOException e) { + // ignore the file + } + + } + + return null; + + } + + public Object getDocumentKey(Object object) { + + if (object instanceof File) { + File file = (File)object; + String path = file.getPath(); + + if (path != null && path.length() == 0) { + return null; + } + + return path; + + } + + throw new IllegalArgumentException(); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/Document.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/Document.java new file mode 100644 index 0000000000..ad50468ed6 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/Document.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.util.Collection; +import java.util.Collections; +import java.util.Hashtable; +import java.util.LinkedList; + +import org.apache.lucene.document.Fieldable; + +/** + * + * @version $Rev$ $Date$ + */ +public class Document { + + private Hashtable> fieldablesTable = + new Hashtable>(); + + private Hashtable> readerMap = new Hashtable>();; + + public Document() { + // empty constructor + } + + public void add(Fieldable fieldable) { + + String strValue = fieldable.stringValue(); + + if (strValue != null) { + + Hashtable fieldables = this.fieldablesTable.get(fieldable.name()); + + if (fieldables == null) { + fieldables = new Hashtable(); + this.fieldablesTable.put(fieldable.name(), fieldables); + + } + + fieldables.put(strValue, fieldable); + + } else { + + LinkedList fieldables = this.readerMap.get(fieldable.name()); + + if (fieldables == null) { + fieldables = new LinkedList(); + this.readerMap.put(fieldable.name(), fieldables); + + } + + fieldables.add(fieldable); + + } + + } + + public org.apache.lucene.document.Document createLuceneDocument() { + org.apache.lucene.document.Document doc = new org.apache.lucene.document.Document(); + + for (Hashtable fieldables : this.fieldablesTable.values()) { + + for (Fieldable fieldable : fieldables.values()) { + doc.add(fieldable); + } + + } + + for (LinkedList fieldables : this.readerMap.values()) { + + for (Fieldable fieldable : fieldables) { + doc.add(fieldable); + } + + } + + return doc; + + } + + public Collection getFieldValues(String field) { + Hashtable fieldables = this.fieldablesTable.get(field); + + if (fieldables != null) { + return fieldables.keySet(); + } + + return Collections.emptyList(); + + } + + public boolean containsField(String field) { + return this.fieldablesTable.containsKey(field); + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainPathAnalyzer.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainPathAnalyzer.java new file mode 100644 index 0000000000..c0b5bcb218 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainPathAnalyzer.java @@ -0,0 +1,233 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.IOException; +import java.io.Reader; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.Token; +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.analysis.Tokenizer; + +/** + * + * @version $Rev$ $Date$ + */ +public class DomainPathAnalyzer extends Analyzer { + + final public static char PATH_START = '\u0001'; + + final public static char PATH_SEPARATOR = '\u0002'; + + final public static char TYPE_SEPARATOR = '\u0003'; + + final public static char URI_SEPARATOR = '\u0004'; + + final public static char ARCHIVE_SEPARATOR = '!'; + + static class DomainPathTokenizer extends Tokenizer { + + private int offset = 0, bufferIndex = 0, dataLen = 0; + private static final int MAX_WORD_LEN = 1024; + private static final int IO_BUFFER_SIZE = 4096; + private final char[] ioBuffer = new char[IO_BUFFER_SIZE]; + private boolean typeCharFound = false; + private boolean uriCharFound = false; + + public DomainPathTokenizer(Reader reader) { + super(reader); + } + + @Override + public void reset() throws IOException { + super.reset(); + + typeCharFound = false; + uriCharFound = false; + + } + + @Override + public void reset(Reader input) throws IOException { + super.reset(input); + + uriCharFound = false; + typeCharFound = false; + + } + + @Override + public Token next(Token reusableToken) throws IOException { + assert reusableToken != null; + reusableToken.clear(); + int length = 0; + int start = bufferIndex; + char[] buffer = reusableToken.termBuffer(); + + boolean lowercaseCharFound = false; + boolean digitFound = false; + + while (true) { + + if (bufferIndex >= dataLen) { + offset += dataLen; + int incr; + + if (lowercaseCharFound || length == 0) { + incr = 0; + + } else { + incr = 2; + ioBuffer[0] = ioBuffer[bufferIndex - 1]; + ioBuffer[1] = ioBuffer[bufferIndex]; + + } + + dataLen = input.read(ioBuffer, incr, ioBuffer.length - incr); + if (dataLen == -1) { + if (length > 0) + break; + else + return null; + } + bufferIndex = incr; + dataLen += incr; + + } + + final char c = ioBuffer[bufferIndex++]; + boolean breakChar = true; + boolean includeChar = false; + + if (c == PATH_START || c == PATH_SEPARATOR) { + + if (length == 0) { + includeChar = true; + + } else { + bufferIndex--; + } + + typeCharFound = false; + uriCharFound = false; + + } else if (c == TYPE_SEPARATOR && !typeCharFound || c == URI_SEPARATOR && !uriCharFound) { + length = 0; + breakChar = false; + lowercaseCharFound = false; + digitFound = false; + + } else { + + if (Character.isDigit(c)) { + + if (digitFound || length == 0) { + breakChar = false; + digitFound = true; + + } else { + bufferIndex--; + } + + // TODO: normalize accent, it does not index accents for + // now + } else if (c >= 65 && c <= 90 || c >= 97 && c <= 122) { + + if (digitFound) { + bufferIndex--; + + } else if (Character.isLowerCase(c)) { + + if (!(lowercaseCharFound || length <= 1)) { + length--; + bufferIndex -= 2; + + } else { + lowercaseCharFound = true; + breakChar = false; + + } + + } else if (!lowercaseCharFound) { // && uppercase + breakChar = false; + + } else { + bufferIndex--; + } + + } + + } + + if (!breakChar || includeChar) { + + if (length == 0) // start of token + start = offset + bufferIndex - 1; + else if (length == buffer.length) + buffer = reusableToken.resizeTermBuffer(1 + length); + + if (c == TYPE_SEPARATOR && !typeCharFound) { + typeCharFound = true; + + } else if (c == URI_SEPARATOR && !uriCharFound) { + typeCharFound = true; + + } else { + buffer[length++] = Character.toLowerCase(c); // buffer + // it, + // normalized + } + + if (length == MAX_WORD_LEN || (breakChar && length > 0)) // buffer + // overflow! + break; + + } else if (length > 0) {// at non-Letter w/ chars + + break; // return 'em + + } + + } + + reusableToken.setTermLength(length); + reusableToken.setStartOffset(start); + reusableToken.setEndOffset(start + length); + + return reusableToken; + + } + } + + public TokenStream tokenStream(String fieldName, Reader reader) { + return new DomainPathTokenizer(reader); + } + + public TokenStream reusableTokenStream(String fieldName, Reader reader) throws IOException { + Tokenizer tokenizer = (Tokenizer)getPreviousTokenStream(); + if (tokenizer == null) { + tokenizer = new DomainPathTokenizer(reader); + setPreviousTokenStream(tokenizer); + } else + tokenizer.reset(reader); + return tokenizer; + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchAnalyzer.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchAnalyzer.java new file mode 100644 index 0000000000..1514a13096 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchAnalyzer.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import org.apache.lucene.analysis.PerFieldAnalyzerWrapper; + +/** + * + * @version $Rev$ $Date$ + */ +public class DomainSearchAnalyzer extends PerFieldAnalyzerWrapper { + + public DomainSearchAnalyzer() { + super(new NamingAnalyzer()); + + addAnalyzer(SearchFields.PARENT_FIELD, new DomainPathAnalyzer()); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchDocumentProcessorsMap.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchDocumentProcessorsMap.java new file mode 100644 index 0000000000..554da34ea1 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchDocumentProcessorsMap.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.domain.search.DocumentProcessorsMap; + +/** + * @version $Rev$ $Date$ + */ +public class DomainSearchDocumentProcessorsMap extends DocumentProcessorsMap { + + private static final long serialVersionUID = -4651637686945322606L; + + public DomainSearchDocumentProcessorsMap() { + put(Contribution.class, new ContributionDocumentProcessor()); + put(Artifact.class, new ArtifactDocumentProcessor()); + put(Property.class, new PropertyDocumentProcessor()); + put(ComponentType.class, new ComponentTypeDocumentProcessor()); + put(Binding.class, new BindingDocumentProcessor()); + put(Component.class, new ComponentDocumentProcessor()); + put(Composite.class, new CompositeDocumentProcessor()); + put(FileContent.class, new DomainSearchFileDocumentProcessor()); + put(Property.class, new PropertyDocumentProcessor()); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchFileDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchFileDocumentProcessor.java new file mode 100644 index 0000000000..ae6821e8ed --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchFileDocumentProcessor.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +/** + * + * @version $Rev$ $Date$ + */ +public class DomainSearchFileDocumentProcessor extends FileDocumentProcessor { + + private static final long serialVersionUID = -2725616937948969598L; + + public DomainSearchFileDocumentProcessor() { + add(new ZipDocumentProcessor()); + add(new DefaultFileDocumentProcessor()); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchFormatter.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchFormatter.java new file mode 100644 index 0000000000..e9ddf036a0 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchFormatter.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import org.apache.lucene.search.highlight.Formatter; +import org.apache.lucene.search.highlight.TokenGroup; + +/** + * + * @version $Rev$ $Date$ + */ +public class DomainSearchFormatter implements Formatter { + + final public static String HIGHLIGHT_START = "\u0005\u0005\u0006"; + + final public static String HIGHLIGHT_END = "\u0006\u0005\u0005"; + + private StringBuilder sb = new StringBuilder(); + + public String highlightTerm(String originalText, TokenGroup tokenGroup) { + + if (tokenGroup.getTotalScore() > 0) { + sb.setLength(0); + + sb.append(HIGHLIGHT_START).append(originalText).append(HIGHLIGHT_END); + + return sb.toString(); + + } else { + return originalText; + } + + } + + public static boolean isHighlighted(String text) { + int start = text.indexOf(HIGHLIGHT_START); + int end = text.indexOf(HIGHLIGHT_END); + + if (start < end && start != -1) { + start = text.indexOf(HIGHLIGHT_START, start + 1); + + if (start > end || start == -1) { + return true; + } + + } + + return false; + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchImpl.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchImpl.java new file mode 100644 index 0000000000..59b80ac026 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchImpl.java @@ -0,0 +1,371 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.index.CorruptIndexException; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.queryParser.MultiFieldQueryParser; +import org.apache.lucene.queryParser.ParseException; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +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.apache.lucene.store.RAMDirectory; +import org.apache.lucene.store.SimpleFSLockFactory; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DomainSearch; +import org.apache.tuscany.sca.domain.search.IndexException; +import org.apache.tuscany.sca.domain.search.Result; +import org.osoa.sca.annotations.AllowsPassByReference; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Scope; + +/** + * @version $Rev$ $Date$ + */ +@Scope("COMPOSITE") +public class DomainSearchImpl implements DomainSearch { + + @Property + public String indexDirectoryPath; + + private Directory dir; + + private Analyzer analyzer = new DomainSearchAnalyzer(); + + private MultiFieldQueryParser qp = + new MultiFieldQueryParser(new String[] {SearchFields.ARTIFACT_FIELD, SearchFields.BINDING_FIELD, + SearchFields.COMPONENT_FIELD, SearchFields.COMPOSITE_FIELD, + SearchFields.CONTRIBUTION_FIELD, SearchFields.EXPORTEDBY_FIELD, + SearchFields.FILE_CONTENT_FIELD, SearchFields.IMPLEMENTS_FIELD, + SearchFields.IMPORTEDBY_FIELD, SearchFields.INCLUDEDBY_FIELD, + SearchFields.PROPERTY_KEY_FIELD, SearchFields.REFERENCE_FIELD, + SearchFields.REFERENCE_INTERFACE_CALLBACK_FIELD, + SearchFields.REFERENCE_INTERFACE_FIELD, + SearchFields.REFERENCE_NAME_FIELD, SearchFields.SERVICE_FIELD, + SearchFields.SERVICE_INTERFACE_CALLBACK_FIELD, + SearchFields.SERVICE_INTERFACE_FIELD, SearchFields.SERVICE_NAME_FIELD, + SearchFields.TYPE_FIELD, SearchFields.VALUE_FIELD}, this.analyzer); + + public DomainSearchImpl() { + this.qp.setAllowLeadingWildcard(true); + } + + private Directory getIndexDirectory() throws IOException { + + if (this.dir == null) { + + if (this.indexDirectoryPath == null || this.indexDirectoryPath.length() == 0) { + this.dir = new RAMDirectory(); + + } else { + + try { + this.dir = + new FSDirectory(new File(this.indexDirectoryPath), + new SimpleFSLockFactory(this.indexDirectoryPath)); + + } catch (IOException e) { + System.err.println("Could not open index at " + this.indexDirectoryPath); + + throw e; + + } + + } + + } + + return this.dir; + + } + + @AllowsPassByReference + public void addContribution(Contribution contribution) throws IndexException { + + IndexWriter indexWriter = null; + + try { + indexWriter = new IndexWriter(getIndexDirectory(), this.analyzer, IndexWriter.MaxFieldLength.UNLIMITED); + + contributionAdded(contribution, indexWriter); + + indexWriter.commit(); + + } catch (Exception e) { + + if (indexWriter != null) { + + try { + indexWriter.rollback(); + + } catch (Exception e1) { + // ignore exception + } + + } + + throw new IndexException(e.getMessage(), e); + + } finally { + + if (indexWriter != null) { + + try { + indexWriter.close(); + + } catch (Exception e) { + // ignore exception + } + + } + + } + + } + + @AllowsPassByReference + public void removeContribution(Contribution contribution) throws IndexException { + + IndexWriter indexWriter = null; + + if (indexExists()) { + + try { + indexWriter = new IndexWriter(getIndexDirectory(), this.analyzer, IndexWriter.MaxFieldLength.UNLIMITED); + + contributionRemoved(contribution, indexWriter); + + indexWriter.commit(); + + } catch (Exception e) { + + if (indexWriter != null) { + + try { + indexWriter.rollback(); + + } catch (Exception e1) { + // ignore exception + } + + } + + throw new IndexException(e.getMessage(), e); + + } finally { + + if (indexWriter != null) { + + try { + indexWriter.close(); + + } catch (Exception e) { + // ignore exception + } + + } + + } + + } + + } + + private void contributionRemoved(Contribution contribution, IndexWriter indexWriter) throws IndexException { + + String contributionURI = contribution.getURI(); + StringBuilder sb = new StringBuilder(SearchFields.PARENT_FIELD); + sb.append(":\""); + sb.append(DomainPathAnalyzer.PATH_START); + sb.append(contributionURI); + sb.append("\" OR "); + sb.append(SearchFields.CONTRIBUTION_FIELD); + sb.append(":\""); + sb.append(contributionURI); + sb.append('"'); + + try { + Query query = this.qp.parse(sb.toString()); + indexWriter.deleteDocuments(query); + + } catch (ParseException e) { + // ignore exception + + } catch (CorruptIndexException ex) { + throw new IndexException(ex.getMessage(), ex); + + } catch (IOException ex) { + throw new IndexException(ex.getMessage(), ex); + } + + } + + private void contributionAdded(Contribution contribution, IndexWriter indexWriter) throws IndexException { + DomainSearchDocumentProcessorsMap docProcessors = new DomainSearchDocumentProcessorsMap(); + DocumentMap docs = new DocumentMap(); + + try { + docProcessors.process(docProcessors, docs, contribution, null, ""); + + } catch (Exception e) { + e.printStackTrace(); + } + + // FileWriter writer = new FileWriter("indexed.txt"); + for (Document doc : docs.values()) { + org.apache.lucene.document.Document luceneDoc = doc.createLuceneDocument(); + // writer.write(luceneDoc.toString()); + // writer.write('\n'); + // writer.write('\n'); + + try { + indexWriter.addDocument(luceneDoc); + + } catch (CorruptIndexException e) { + throw new IndexException(e.getMessage(), e); + + } catch (IOException e) { + throw new IndexException(e.getMessage(), e); + } + + } + // writer.close(); + + } + + @AllowsPassByReference + public void updateContribution(Contribution oldContribution, Contribution contribution) throws IndexException { + + IndexWriter indexWriter = null; + + try { + indexWriter = new IndexWriter(getIndexDirectory(), this.analyzer, IndexWriter.MaxFieldLength.UNLIMITED); + + contributionRemoved(oldContribution, indexWriter); + contributionAdded(contribution, indexWriter); + + indexWriter.commit(); + + } catch (Exception e) { + + if (indexWriter != null) { + + try { + indexWriter.rollback(); + + } catch (Exception e1) { + // ignore exception + } + + } + + throw new IndexException(e.getMessage(), e); + + } finally { + + if (indexWriter != null) { + + try { + indexWriter.close(); + + } catch (Exception e) { + // ignore exception + } + + } + + } + + } + + public Result[] parseAndSearch(String searchQuery, final boolean highlight) throws IndexException, ParseException { + return search(this.qp.parse(searchQuery), highlight); + } + + public Result[] search(Query searchQuery, boolean highlight) throws IndexException { + + try { + final IndexSearcher searcher = new IndexSearcher(getIndexDirectory()); + DomainSearchResultProcessor resultProcessor = + new DomainSearchResultProcessor(new DomainSearchResultFactory()); + TopDocs topDocs = searcher.search(searchQuery, 1000); + + int indexed = 0; + HashSet set = new HashSet(); + for (ScoreDoc scoreDoc : topDocs.scoreDocs) { + org.apache.lucene.document.Document luceneDocument = searcher.doc(scoreDoc.doc); + + resultProcessor.process(luceneDocument, null); + + indexed++; + set.add(luceneDocument.toString()); + + } + + Result[] results = resultProcessor.createResultRoots(); + + if (highlight) { + + for (Result result : results) { + HighlightingUtil.highlightResult(result, searchQuery); + } + + } + + return results; + + } catch (CorruptIndexException ex) { + throw new IndexException(ex.getMessage(), ex); + + } catch (IOException ex) { + throw new IndexException(ex.getMessage(), ex); + } + + } + + public String highlight(String field, String text, String searchQuery) throws ParseException { + final Query query = this.qp.parse(searchQuery); + + return HighlightingUtil.highlight(field, query, text); + + } + + public boolean indexExists() { + + if ((this.indexDirectoryPath == null || this.indexDirectoryPath.length() == 0) && this.dir == null) { + + return false; + + } else { + return this.dir != null || IndexReader.indexExists(new File(this.indexDirectoryPath)); + } + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchResultFactory.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchResultFactory.java new file mode 100644 index 0000000000..6a5b875586 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchResultFactory.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +/** + * + * @version $Rev$ $Date$ + */ +public class DomainSearchResultFactory extends PriorityFieldListResultFactory { + + private static final long serialVersionUID = -7421799172738469027L; + + public DomainSearchResultFactory() { + add(SearchFields.COMPOSITE_FIELD); + add(SearchFields.COMPONENT_FIELD); + add(SearchFields.COMPONENT_TYPE_FIELD); + add(SearchFields.CONTRIBUTION_FIELD); + add(SearchFields.BINDING_FIELD); + add(SearchFields.FILE_CONTENT_FIELD); + add(SearchFields.ARTIFACT_FIELD); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchResultProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchResultProcessor.java new file mode 100644 index 0000000000..ee2268b922 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/DomainSearchResultProcessor.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import org.apache.tuscany.sca.domain.search.Result; +import org.apache.tuscany.sca.domain.search.ResultFactory; + +/** + * + * @version $Rev$ $Date$ + */ +public class DomainSearchResultProcessor extends ResultProcessorList { + + private static final long serialVersionUID = 792292814333612713L; + + public DomainSearchResultProcessor(ResultFactory resultFactory) { + + super(new DomainSearchResultFactory()); + + add(new FileContentResultProcessor()); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileContent.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileContent.java new file mode 100644 index 0000000000..923eff998a --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileContent.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.IOException; +import java.io.InputStream; + +/** + * + * @version $Rev$ $Date$ + */ +public interface FileContent { + + String getPath(); + + String getName(); + + FileContent[] getChildren(); + + boolean isLeaf(); + + InputStream getInputStream() throws IOException; + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileContentResultProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileContentResultProcessor.java new file mode 100644 index 0000000000..f6253d6a17 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileContentResultProcessor.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; + +import org.apache.lucene.document.Document; +import org.apache.tuscany.sca.domain.search.Result; +import org.apache.tuscany.sca.domain.search.ResultProcessor; + +/** + * + * @version $Rev$ $Date$ + */ +public class FileContentResultProcessor implements ResultProcessor { + + public Result process(Document document, Result result) { + + if (document.getFieldable(SearchFields.FILE_CONTENT_FIELD) != null) { + Reader reader; + + ParentField parentField = new ParentField(document.get(SearchFields.PARENT_FIELD)); + + int lastParentElementIndex = parentField.getElementsCount() - 1; + String parentURI; + + if (SearchFields.ARTIFACT_FIELD.equals(parentField.getElementType(lastParentElementIndex))) { + parentURI = parentField.getElementURI(lastParentElementIndex); + + // if (parentURI.startsWith("jar:")) { + + try { + reader = new InputStreamReader(new URL(parentURI).openStream()); + + } catch (IOException e) { + return result; + } + + // } else { + // + // try { + // reader = new InputStreamReader(new FileInputStream( + // new File(parentURI + (parentURI.length() > 0 ? "/" : "") + + // name))); + // + // } catch (FileNotFoundException e) { + // return result; + // } + // + // } + + try { + + StringBuilder sb = new StringBuilder(); + int c; + + // TODO: load the chars into an array buffer instead of one + // at a + // time + while ((c = reader.read()) != -1) { + char character = (char)c; + + if (!Character.isIdentifierIgnorable(character)) { + sb.append(character); + } + + } + + result.setValue(sb.toString()); + + } catch (Exception e) { + // ignore content loading, TODO: maybe it should return an + // error + // message as the content + + } + + } + + } + + return result; + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileDocumentProcessor.java new file mode 100644 index 0000000000..553a5b57cd --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/FileDocumentProcessor.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.util.LinkedList; + +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DocumentProcessor; + +/** + * + * @version $Rev$ $Date$ + */ +public class FileDocumentProcessor extends LinkedList implements DocumentProcessor { + + private static final long serialVersionUID = 7843338343970738591L; + + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document doc, + String parent) { + + if (object instanceof FileContent) { + FileContent file = (FileContent)object; + + if (!file.isLeaf()) { + + if (doc == null) { + doc = documents.get(SearchFields.FILE_CONTENT_FIELD + file.getPath()); + } + + // FileContent[] files = file.getChildren(); + + // for (FileContent childFile : files) { + // // Document fileDoc = parentProcessor.process( + // // parentProcessor, documents, childFile, null, + // // parent); + // + // Document fileDoc = null; + // + // fileDoc = process(this, documents, childFile, null, parent); + // + // if (fileDoc == null) { + // continue; + // } + // + // fileDoc.add(new Field(SearchFields.PARENT_FIELD, parent, + // Field.Store.YES, Field.Index.ANALYZED)); + // + // } + + return doc; + + } else { + + for (DocumentProcessor processor : this) { + Document newDoc = processor.process(this, documents, file, doc, parent); + + if (newDoc != null) { + return newDoc; + } + + } + + } + + } + + return doc; + + } + + public Object getDocumentKey(Object object) { + + if (object instanceof FileContent) { + FileContent file = (FileContent)object; + String path = file.getPath(); + + if (path != null && path.length() == 0) { + return null; + } + + return SearchFields.FILE_CONTENT_FIELD + path; + + } + + throw new IllegalArgumentException(); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/HighlightingUtil.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/HighlightingUtil.java new file mode 100644 index 0000000000..356eb88070 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/HighlightingUtil.java @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.IOException; +import java.io.StringReader; +import java.util.Map; + +import org.apache.lucene.analysis.CachingTokenFilter; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.highlight.Fragmenter; +import org.apache.lucene.search.highlight.Highlighter; +import org.apache.lucene.search.highlight.InvalidTokenOffsetsException; +import org.apache.lucene.search.highlight.NullFragmenter; +import org.apache.lucene.search.highlight.SimpleFragmenter; +import org.apache.lucene.search.highlight.SpanScorer; +import org.apache.tuscany.sca.domain.search.Result; + +/** + * @version $Rev$ $Date$ + */ +final public class HighlightingUtil { + + public static void highlightResult(Result result, Query query) { + highlightResult(result, query, new SimpleFragmenter(70)); + } + + public static void highlightResult(Result result, Query query, Fragmenter fragmenter) { + Map contents = result.getContents(); + + if (contents != null) { + + for (Result content : contents.values()) { + highlightResult(content, query, fragmenter); + } + + } + + String highlightedText = + HighlightingUtil.bestFragmentHighlighted(result.getField(), query, result.getValue(), fragmenter); + + // checks if something was highlighted before resetting the value + if (highlightedText != null && highlightedText.length() > 0) { + result.setValue(highlightedText); + } + + } + + public static String highlight(String field, Query query, String text) { + String highlightedText = bestFragmentHighlighted(field, query, text, new NullFragmenter()); + + if (highlightedText == null || text.length() >= highlightedText.length()) { + return text; + } + + return highlightedText; + + } + + public static String bestFragmentHighlighted(String field, Query query, String text) throws IOException { + return bestFragmentHighlighted(field, query, text, new SimpleFragmenter(100)); + } + + public static String bestFragmentHighlighted(String field, Query query, String text, Fragmenter fragmenter) { + + try { + CachingTokenFilter tokenStream = + new CachingTokenFilter(new DomainSearchAnalyzer().tokenStream(field, new StringReader(text))); + + Highlighter highlighter = + new Highlighter(new DomainSearchFormatter(), new SpanScorer(query, field, tokenStream, "")); + highlighter.setTextFragmenter(fragmenter); + tokenStream.reset(); + + try { + return highlighter.getBestFragments(tokenStream, text, 2, " ... "); + + } catch (InvalidTokenOffsetsException e) { + // could not create fragments, return empty string + } + + } catch (IOException ex) { + // should never happen + } + + return ""; + + } + + public static String replaceHighlightMarkupBy(CharSequence text, String startHighlight, String endHighlight) { + StringBuilder sb = new StringBuilder(); + int start = 0; + int end = 0; + + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + + if (start > 0) { + + if (c == DomainSearchFormatter.HIGHLIGHT_START.charAt(start)) { + start++; + + if (start == DomainSearchFormatter.HIGHLIGHT_START.length()) { + sb.append(startHighlight); + start = 0; + + } + + } else { + + for (int j = 0; j < start; j++) { + sb.append(DomainSearchFormatter.HIGHLIGHT_START.charAt(j)); + } + + start = 0; + + } + + } else if (end > 0) { + + if (c == DomainSearchFormatter.HIGHLIGHT_END.charAt(end)) { + end++; + + if (end == DomainSearchFormatter.HIGHLIGHT_END.length()) { + sb.append(endHighlight); + end = 0; + + } + + } else { + + for (int j = 0; j < end; j++) { + sb.append(DomainSearchFormatter.HIGHLIGHT_END.charAt(j)); + } + + end = 0; + + } + + } else if (c == DomainSearchFormatter.HIGHLIGHT_START.charAt(0)) { + start = 1; + + } else if (c == DomainSearchFormatter.HIGHLIGHT_END.charAt(0)) { + end = 1; + + } else { + sb.append(c); + } + + } + + if (start > 0) { + + for (int j = 0; j < start; j++) { + sb.append(DomainSearchFormatter.HIGHLIGHT_START.charAt(j)); + } + + } else if (end > 0) { + + for (int j = 0; j < start; j++) { + sb.append(DomainSearchFormatter.HIGHLIGHT_END.charAt(j)); + } + + } + + return sb.toString(); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/NamingAnalyzer.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/NamingAnalyzer.java new file mode 100644 index 0000000000..2f06b179e4 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/NamingAnalyzer.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.IOException; +import java.io.Reader; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.analysis.Tokenizer; + +/** + * + * @version $Rev$ $Date$ + */ +public class NamingAnalyzer extends Analyzer { + + public TokenStream tokenStream(String fieldName, Reader reader) { + return new NamingTokenizer(reader); + } + + public TokenStream reusableTokenStream(String fieldName, Reader reader) throws IOException { + Tokenizer tokenizer = (Tokenizer)getPreviousTokenStream(); + if (tokenizer == null) { + tokenizer = new NamingTokenizer(reader); + setPreviousTokenStream(tokenizer); + } else + tokenizer.reset(reader); + return tokenizer; + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/NamingTokenizer.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/NamingTokenizer.java new file mode 100644 index 0000000000..280039a67e --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/NamingTokenizer.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.IOException; +import java.io.Reader; + +import org.apache.lucene.analysis.Token; +import org.apache.lucene.analysis.Tokenizer; + +/** + * + * @version $Rev$ $Date$ + */ +public class NamingTokenizer extends Tokenizer { + + private int offset = 0, bufferIndex = 0, dataLen = 0; + private static final int MAX_WORD_LEN = 255; + private static final int IO_BUFFER_SIZE = 4096; + private final char[] ioBuffer = new char[IO_BUFFER_SIZE]; + + public NamingTokenizer(Reader reader) { + super(reader); + } + + @Override + public Token next(Token reusableToken) throws IOException { + assert reusableToken != null; + reusableToken.clear(); + int length = 0; + int start = bufferIndex; + char[] buffer = reusableToken.termBuffer(); + + boolean lowercaseCharFound = false; + boolean digitFound = false; + + while (true) { + + if (bufferIndex >= dataLen) { + offset += dataLen; + int incr; + + if (lowercaseCharFound || length == 0) { + incr = 0; + + } else { + incr = 2; + ioBuffer[0] = ioBuffer[bufferIndex - 1]; + ioBuffer[1] = ioBuffer[bufferIndex]; + + } + + dataLen = input.read(ioBuffer, incr, ioBuffer.length - incr); + if (dataLen == -1) { + if (length > 0) + break; + else + return null; + } + bufferIndex = incr; + dataLen += incr; + + } + + final char c = ioBuffer[bufferIndex++]; + boolean breakChar = true; + + if (Character.isDigit(c)) { + + if (digitFound || length == 0) { + breakChar = false; + digitFound = true; + + } else { + bufferIndex--; + } + + // TODO: normalize accent, it does not index accents for now + } else if (c >= 65 && c <= 90 || c >= 97 && c <= 122) { + + if (digitFound) { + bufferIndex--; + + } else if (Character.isLowerCase(c)) { + + if (!(lowercaseCharFound || length <= 1)) { + length--; + bufferIndex -= 2; + + } else { + lowercaseCharFound = true; + breakChar = false; + + } + + } else if (!lowercaseCharFound) { // && uppercase + breakChar = false; + + } else { + bufferIndex--; + } + + } + + if (!breakChar) { + + if (length == 0) // start of token + start = offset + bufferIndex - 1; + else if (length == buffer.length) + buffer = reusableToken.resizeTermBuffer(1 + length); + + buffer[length++] = Character.toLowerCase(c); // buffer it, + // normalized + + if (length == MAX_WORD_LEN) // buffer overflow! + break; + + } else if (length > 0) {// at non-Letter w/ chars + + break; // return 'em + + } + + } + + reusableToken.setTermLength(length); + reusableToken.setStartOffset(start); + reusableToken.setEndOffset(start + length); + + return reusableToken; + + } +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ParentField.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ParentField.java new file mode 100644 index 0000000000..862db63b2c --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ParentField.java @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @version $Rev$ $Date$ + */ +public class ParentField implements Serializable { + + private static final long serialVersionUID = -2090538050273088026L; + + final private List elements; + + public ParentField(String parentFieldValue) { + int length = parentFieldValue.length(); + + if (length == 0) { + this.elements = Collections.emptyList(); + + return; + + } + + this.elements = new ArrayList(); + + ParentFieldElement element = null; + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < length; i++) { + char c = parentFieldValue.charAt(i); + + if (c == DomainPathAnalyzer.PATH_SEPARATOR || c == DomainPathAnalyzer.PATH_START) { + + if (sb.length() > 0 || element != null) { + + if (element == null) { + element = new ParentFieldElement(); + } + + if (element.type == null) { + element.type = ""; + } + + if (element.uri == null) { + element.uri = element.name = sb.toString(); + + } else { + element.name = sb.toString(); + } + + sb.setLength(0); + this.elements.add(element); + element = null; + + } + + } else if (c == DomainPathAnalyzer.TYPE_SEPARATOR) { + + if (element == null) { + element = new ParentFieldElement(); + } + + element.type = sb.toString(); + + sb.setLength(0); + + } else if (c == DomainPathAnalyzer.URI_SEPARATOR) { + + if (element == null) { + element = new ParentFieldElement(); + } + + element.uri = sb.toString(); + + sb.setLength(0); + + } else { + sb.append(c); + } + + } + + if (sb.length() > 0 || element != null) { + + if (element == null) { + element = new ParentFieldElement(); + } + + if (element.type == null) { + element.type = ""; + } + + if (element.uri == null) { + element.uri = element.name = sb.toString(); + + } else { + element.name = sb.toString(); + } + + sb.setLength(0); + this.elements.add(element); + element = null; + + } + + } + + public static String getURIPath(ParentField parentField) { + return getURIPath(parentField, System.getProperty("file.separator")); + } + + public static String getURIPath(ParentField parentField, String pathSeparator) { + StringBuilder sb = new StringBuilder(); + sb.append(pathSeparator); + int elementsCount = parentField.getElementsCount(); + + for (int i = 0; i < elementsCount; i++) { + sb.append(parentField.getElementName(i)); + sb.append(pathSeparator); + + } + + if (sb.length() > pathSeparator.length()) { + sb.setLength(sb.length() - pathSeparator.length()); + } + + return sb.toString(); + + } + + public static int getParentElementsCount(String parent) { + int length = parent.length(); + + if (length == 0) { + return 0; + } + + boolean pathSeparatorBefore = true; + int count = 1; + + for (int i = 0; i < length - 1; i++) { + char c = parent.charAt(i); + + if (c == DomainPathAnalyzer.PATH_SEPARATOR && !pathSeparatorBefore) { + pathSeparatorBefore = true; + count++; + + } else { + pathSeparatorBefore = false; + } + + } + + return count; + + } + + public int getElementsCount() { + return this.elements.size(); + } + + public String getElementType(int index) { + return this.elements.get(index).type; + } + + public String getElementURI(int index) { + return this.elements.get(index).uri; + } + + public String getElementName(int index) { + return this.elements.get(index).name; + } + + final private static class ParentFieldElement { + + String type; + + String uri; + + String name; + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/PriorityFieldListResultFactory.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/PriorityFieldListResultFactory.java new file mode 100644 index 0000000000..bd1912af49 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/PriorityFieldListResultFactory.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.util.LinkedList; + +import org.apache.lucene.document.Document; +import org.apache.tuscany.sca.domain.search.Result; +import org.apache.tuscany.sca.domain.search.ResultFactory; + +/** + * + * @version $Rev$ $Date$ + */ +public class PriorityFieldListResultFactory extends LinkedList implements ResultFactory { + + private static final long serialVersionUID = 6806221945324235828L; + + public PriorityFieldListResultFactory() { + // empty constructor + } + + public Result createResult(Document document) { + + for (String field : this) { + String value = document.get(field); + + if (value != null) { + return new ResultImpl(field, value); + } + + } + + return null; + + } + + public Result createResult(String field, String value) { + return new ResultImpl(field, value); + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/PropertyDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/PropertyDocumentProcessor.java new file mode 100644 index 0000000000..20b6635e05 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/PropertyDocumentProcessor.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.lang.reflect.Array; + +import org.apache.lucene.document.Field; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DocumentProcessor; + +/** + * + * @version $Rev$ $Date$ + */ +public class PropertyDocumentProcessor implements DocumentProcessor { + + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document doc, + String parent) { + + if (object instanceof Property) { + Property property = (Property)object; + String name = property.getName(); + + if (name != null && name.length() > 0) { + + if (doc == null) { + doc = documents.get(name); + } + + Object value = property.getValue(); + + if (value.getClass().isArray()) { + int arraySize = Array.getLength(value); + + for (int i = 0; i < arraySize; i++) { + Object arrayValue = Array.get(value, i); + + doc.add(new Field(SearchFields.VALUE_FIELD, arrayValue.toString(), Field.Store.YES, + Field.Index.ANALYZED)); + + } + + } else { + + doc + .add(new Field(SearchFields.VALUE_FIELD, value.toString(), Field.Store.YES, + Field.Index.ANALYZED)); + + } + + return doc == null ? FAKE_DOCUMENT : doc; + + } else { + return FAKE_DOCUMENT; + } + + } + + throw new IllegalArgumentException(); + + } + + public Object getDocumentKey(Object object) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ResultImpl.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ResultImpl.java new file mode 100644 index 0000000000..66e2b73723 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ResultImpl.java @@ -0,0 +1,270 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.domain.search.Result; + +/** + * + * @version $Rev$ $Date$ + */ +final public class ResultImpl implements Result { + + private static final long serialVersionUID = 7084570994751217396L; + + private Result container; + + private HashMap contents; + + private String value; + + private String field; + + public ResultImpl() { + // empty constructor + } + + public ResultImpl(String field, String value) { + setValue(value); + setField(field); + + } + + public String getField() { + return this.field; + } + + public void setField(String field) { + this.field = field; + } + + public Result getContainer() { + return this.container; + } + + public Map getContents() { + + if (this.contents == null) { + return Collections.emptyMap(); + } + + return Collections.unmodifiableMap(this.contents); + + } + + public String getValue() { + return this.value; + } + + public void setContainer(Result container) { + + if (container != this.container) { + + if (this.container != null) { + this.container.removeContent(this); + } + + this.container = container; + + if (container != null) { + container.addContent(this); + } + + } + + } + + @Override + public boolean equals(Object obj) { + + if (obj instanceof Result) { + Result artifactResult = (Result)obj; + + if (artifactResult.getValue() == this.value || this.value != null + && this.value.equals(artifactResult.getValue())) { + + if (artifactResult.getContainer() == this.container || this.container != null + && this.container.equals(artifactResult.getContainer())) { + + Map contents = artifactResult.getContents(); + + if (this.contents == null) { + return contents.isEmpty(); + + } else if (this.contents.equals(contents)) { + return true; + } + + } + + } + + } + + return false; + + } + + public void addContent(Result artifactResult) { + internalGetContents().put(artifactResult.getValue(), artifactResult); + + if (artifactResult.getContainer() != this) { + artifactResult.setContainer(this); + } + + } + + private HashMap internalGetContents() { + + if (this.contents == null) { + this.contents = new HashMap(); + } + + return this.contents; + + } + + public void removeContent(Result artifactResult) { + + if (this.contents != null) { + this.contents.remove(artifactResult); + + artifactResult.setContainer(null); + + if (this.contents.isEmpty()) { + this.contents = null; + } + + } + + } + + @Override + public int hashCode() { + int hash = 11; + + hash = hash * 31 + (this.container == null ? 7 : this.container.hashCode()); + hash = hash * 31 + (this.contents == null || this.contents.isEmpty() ? 13 : this.contents.hashCode()); + hash = hash * 31 + (this.value == null ? 17 : this.value.hashCode()); + + return hash; + + } + + public void setValue(String value) { + this.value = value; + } + + public String toString() { + StringBuilder sb = new StringBuilder("<"); + Result container = getContainer(); + + sb.append(getClass().getName()).append(" name='").append(getValue()).append("' container='") + .append(container != null ? container.getValue() : null).append("'>\n"); + + Method[] methods = getClass().getMethods(); + + for (Method method : methods) { + String methodName = method.getName(); + + if (method.getReturnType() != void.class) { + + if (method.getParameterTypes().length == 0) { + + if (methodName.startsWith("get") && !"getName".equals(methodName) + && !"getContainer".equals(methodName)) { + + try { + Object returnedObj = method.invoke(this); + + sb.append('\t'); + + if (returnedObj instanceof Map) { + + sb.append("\n"); + + for (Object obj : ((Map)returnedObj).values()) { + + sb.append("\t\t").append(obj.toString()).append("\n"); + + } + + sb.append("\t\n"); + + } else if (returnedObj instanceof Collection) { + + sb.append("\n"); + + for (Object obj : (Collection)returnedObj) { + + sb.append("\t\t").append(obj.toString()).append("\n"); + + } + + sb.append("\t\n"); + + } else if (returnedObj.getClass().isArray()) { + + sb.append("\n"); + + int length = Array.getLength(returnedObj); + + for (int i = 0; i < length; i++) { + + sb.append("\t\t").append(Array.get(returnedObj, i).toString()).append("\n"); + + } + + sb.append("\t\n"); + + } else { + + sb.append('\t').append(returnedObj).append('\n'); + + } + + } catch (Throwable e) { + // ignore exceptions and don't print the object + } + + } + + } + + } + + } + + sb.append(""); + + return sb.toString(); + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ResultProcessorList.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ResultProcessorList.java new file mode 100644 index 0000000000..27c192cbee --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ResultProcessorList.java @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.util.HashMap; +import java.util.LinkedList; + +import org.apache.lucene.document.Document; +import org.apache.tuscany.sca.domain.search.Result; +import org.apache.tuscany.sca.domain.search.ResultFactory; +import org.apache.tuscany.sca.domain.search.ResultProcessor; + +/** + * + * @version $Rev$ $Date$ + */ +public class ResultProcessorList extends LinkedList implements ResultProcessor { + + + private static final long serialVersionUID = 7147307292452694895L; + + private HashMap resultRoots = new HashMap(); + + private ResultFactory resultFactory; + + public ResultProcessorList(ResultFactory resultFactory) { + this.resultFactory = resultFactory; + } + + public Result process(Document document, Result result) { + + if (result == null) { + result = this.resultFactory.createResult(document); + + if (result == null) { + return null; + } + + } + + ResultHashMap resultHashMap; + + String parent = document.get(SearchFields.PARENT_FIELD); + + if (parent == null) { + resultHashMap = new ResultHashMap(result); + resultRoots.put(result.getValue(), resultHashMap); + + } else { + + ParentField parentField = new ParentField(parent); + HashMap current = this.resultRoots; + // Result currentResult = null; + int elementsCount = parentField.getElementsCount(); + + for (int i = 0; i < elementsCount; i++) { + String actualName = parentField.getElementName(i); + String type = parentField.getElementType(i); + + if (actualName.length() > 0) { + ResultHashMap actualResultHashMap = current.get(actualName); + + if (actualResultHashMap == null) { + ResultHashMap aux = new ResultHashMap(type, parentField.getElementName(i)); + + current.put(aux.result.getValue(), aux); + // if (current.put(aux.result.getValue(), aux) == null + // && currentResult != null) { + // currentResult.addContent(aux.result); + // } + + current = aux; + // currentResult = aux.result; + + } else { + current = actualResultHashMap; + // currentResult = actualResultHashMap.result; + + } + + } + + } + + resultHashMap = current.get(result.getValue()); + + if (resultHashMap == null) { + resultHashMap = new ResultHashMap(result); + current.put(result.getValue(), resultHashMap); + + // if (currentResult != null) { + // currentResult.addContent(result); + // } + + } + + } + + for (ResultProcessor processor : this) { + result = processor.process(document, result); + } + + resultHashMap.result = result; + + return result; + + } + + private static void addContentsToResult(ResultHashMap resultHashMap) { + + for (ResultHashMap actual : resultHashMap.values()) { + addContentsToResult(actual); + + resultHashMap.result.addContent(actual.result); + + } + + } + + public Result[] createResultRoots() { + int size = this.resultRoots.size(); + + if (size == 0) { + return new Result[0]; + } + + Result[] res = new Result[size]; + + int i = 0; + for (ResultHashMap resultHashMap : this.resultRoots.values()) { + + addContentsToResult(resultHashMap); + res[i++] = resultHashMap.result; + + } + + this.resultRoots.clear(); + + return res; + + } + + private Result createResult(String field, String value) { + Result result = this.resultFactory.createResult(field, value); + + if (result != null) { + return result; + } + + throw new IllegalArgumentException(); + + } + + private class ResultHashMap extends HashMap { + + private static final long serialVersionUID = 7982561264440904411L; + + Result result; + + ResultHashMap(String type, String name) { + this(createResult(type, name)); + } + + ResultHashMap(Result result) { + this.result = result; + } + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/SearchFields.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/SearchFields.java new file mode 100644 index 0000000000..abfaa8c466 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/SearchFields.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +/** + * + * @version $Rev$ $Date$ + */ +public interface SearchFields { + + final public static String ARTIFACT_FIELD = "artifact"; + + final public static String COMPONENT_TYPE_FIELD = "componenttype"; + + final public static String REFERENCE_FIELD = "reference"; + + final public static String COMPOSITE_FIELD = "composite"; + + final public static String SERVICE_FIELD = "service"; + + final public static String BINDING_FIELD = "binding"; + + final public static String CONTRIBUTION_FIELD = "contribution"; + + final public static String COMPONENT_FIELD = "component"; + + final public static String TYPE_FIELD = "type"; + + final public static String PARENT_FIELD = "parent"; + + final public static String IMPLEMENTS_FIELD = "implements"; + + final public static String SERVICE_NAME_FIELD = "servicename"; + + final public static String SERVICE_INTERFACE_FIELD = "serviceinterface"; + + final public static String SERVICE_INTERFACE_CALLBACK_FIELD = "serviceinterfacecallback"; + + final public static String REFERENCE_NAME_FIELD = "referencename"; + + final public static String REFERENCE_INTERFACE_FIELD = "referenceinterface"; + + final public static String REFERENCE_INTERFACE_CALLBACK_FIELD = "referenceinterfacecallback"; + + final public static String IMPORTEDBY_FIELD = "importedby"; + + final public static String EXPORTEDBY_FIELD = "exportedby"; + + final public static String INCLUDEDBY_FIELD = "includedby"; + + final public static String PROPERTY_KEY_FIELD = "propertykey"; + + final public static String VALUE_FIELD = "propertyvalue"; + + final public static String FILE_CONTENT_FIELD = "filecontent"; + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/SystemFileContent.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/SystemFileContent.java new file mode 100644 index 0000000000..3d75c2b86e --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/SystemFileContent.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * + * @version $Rev$ $Date$ + */ +public class SystemFileContent implements FileContent { + + private static final long serialVersionUID = -8337926886777467728L; + + final boolean leaf; + + final private File file; + + public SystemFileContent(File file) { + this.leaf = !file.isDirectory(); + this.file = file; + + } + + public File getFile() { + return this.file; + } + + public InputStream getInputStream() throws IOException { + return new FileInputStream(this.file); + } + + public FileContent[] getChildren() { + File[] files = this.file.listFiles(); + FileContent[] ret = new FileContent[files.length]; + + for (int i = 0; i < files.length; i++) { + ret[i] = new SystemFileContent(files[i]); + } + + return ret; + + } + + public boolean isLeaf() { + return this.leaf; + } + + public String getName() { + return this.file.getName(); + } + + public String getPath() { + return this.file.getPath(); + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/WrappedFileContent.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/WrappedFileContent.java new file mode 100644 index 0000000000..78434d4c0d --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/WrappedFileContent.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.JarURLConnection; +import java.net.URL; + +/** + * @version $Rev$ $Date$ + */ +public class WrappedFileContent implements FileContent { + + final private FileContent fileContent; + + public WrappedFileContent(URL url) throws IOException { + String protocol = url.getProtocol(); + + if (protocol.equals("jar")) { + JarURLConnection jarConn = (JarURLConnection)url.openConnection(); + String file = url.getFile(); + file = file.substring(file.lastIndexOf('!') + 1); + + this.fileContent = ZipFileContent.createZipFileContent(jarConn.getJarFile(), file); + + } else if (protocol.equals("file")) { + this.fileContent = new SystemFileContent(new File(url.getFile())); + + } else { + this.fileContent = new DefaultFileContent(url); + } + + } + + public FileContent[] getChildren() { + return this.fileContent.getChildren(); + } + + public InputStream getInputStream() throws IOException { + return this.fileContent.getInputStream(); + } + + public String getName() { + return this.fileContent.getName(); + } + + public String getPath() { + return this.fileContent.getPath(); + } + + public boolean isLeaf() { + return this.fileContent.isLeaf(); + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ZipDocumentProcessor.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ZipDocumentProcessor.java new file mode 100644 index 0000000000..2337c40fc1 --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ZipDocumentProcessor.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.File; +import java.io.IOException; +import java.util.zip.ZipFile; + +import org.apache.lucene.document.Field; +import org.apache.tuscany.sca.domain.search.DocumentMap; +import org.apache.tuscany.sca.domain.search.DocumentProcessor; + +/** + * + * @version $Rev$ $Date$ + */ +public class ZipDocumentProcessor implements DocumentProcessor { + + public Object getDocumentKey(Object object) { + + if (object instanceof File) { + File file = (File)object; + String path = file.getPath(); + + if (path != null && path.length() == 0) { + return null; + } + + return path; + + } + + throw new IllegalArgumentException(); + + } + + public Document process(DocumentProcessor parentProcessor, + DocumentMap documents, + Object object, + Document document, + String parent) { + + if (object instanceof SystemFileContent) { + SystemFileContent file = (SystemFileContent)object; + + try { + ZipFile zip = new ZipFile(file.getFile()); + + if (document == null) { + document = documents.get(file.getPath()); + } + + parent += + DomainPathAnalyzer.PATH_SEPARATOR + SearchFields.ARTIFACT_FIELD + + DomainPathAnalyzer.TYPE_SEPARATOR + + "jar:file:" + + file.getPath() + + DomainPathAnalyzer.ARCHIVE_SEPARATOR + + '/' + + file.getName() + + DomainPathAnalyzer.URI_SEPARATOR + + file.getName(); + + document.add(new Field(SearchFields.ARTIFACT_FIELD, file.getName(), Field.Store.YES, + Field.Index.ANALYZED)); + + ZipFileContent[] zipFiles = ZipFileContent.createZipFileContent(zip); + + for (ZipFileContent zipFile : zipFiles) { + + parentProcessor.process(parentProcessor, documents, zipFile, document, parent); + + } + + return document; + + } catch (IOException e) { + // ignore file + } + + } + + return null; + + } + +} diff --git a/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ZipFileContent.java b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ZipFileContent.java new file mode 100644 index 0000000000..15f9bb6feb --- /dev/null +++ b/sca-java-1.x/trunk/modules/domain-search/src/main/java/org/apache/tuscany/sca/domain/search/impl/ZipFileContent.java @@ -0,0 +1,321 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tuscany.sca.domain.search.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * + * @version $Rev$ $Date$ + */ +public class ZipFileContent implements FileContent { + + final private ZipFile file; + + final private ZipEntry entry; + + private FileContent[] children; + + private ZipFileContent(ZipFile file, ZipEntry entry) { + this.file = file; + this.entry = entry; + + } + + public InputStream getInputStream() throws IOException { + return this.file.getInputStream(this.entry); + } + + public String getPath() { + return this.file.getName() + DomainPathAnalyzer.ARCHIVE_SEPARATOR + '/' + this.entry.getName(); + } + + public FileContent[] getChildren() { + return this.children; + } + + public String getName() { + return this.entry.getName(); + // int lastSlashIndex = name.lastIndexOf('/'); + // + // if (lastSlashIndex == -1) { + // return name; + // } + // + // if (lastSlashIndex == name.length() - 1 && name.length() > 1) { + // lastSlashIndex = name.lastIndexOf('/', name.length() - 2); + // + // if (lastSlashIndex == -1) { + // return name.substring(0, name.length() - 1); + // } + // + // return name.substring(lastSlashIndex + 1, name.length() - 1); + // + // } + // + // return name.substring(lastSlashIndex + 1); + + } + + public boolean isLeaf() { + return !this.entry.isDirectory(); + } + + public static ZipFileContent[] createZipFileContent(ZipFile file) { + Enumeration entries = file.entries(); + + if (!entries.hasMoreElements()) { + return null; + } + + HashMap roots = new HashMap(); + + do { + ZipEntry entry = entries.nextElement(); + String name = entry.getName(); + + if (name.length() > 0) { + + String[] path = name.split("/"); + + ZipMap current = roots.get(path[0]); + + if (current == null) { + current = new ZipMap(); + roots.put(path[0], current); + + if (path.length == 1) { + current.setEntry(file, entry); + continue; + + } + + } + + for (int i = 1; i < path.length - 1; i++) { + ZipMap actual = current.get(path[i]); + + if (actual == null) { + actual = new ZipMap(); + current.put(path[i], actual); + + } + + current = actual; + + } + + ZipMap entryMap = current.get(path[path.length - 1]); + + if (entryMap == null) { + entryMap = new ZipMap(); + current.put(path[path.length - 1], entryMap); + + } + + entryMap.setEntry(file, entry); + + } + + } while (entries.hasMoreElements()); + + for (ZipMap map : roots.values()) { + createZipFileContentChildren(map); + } + + ZipFileContent[] ret = new ZipFileContent[roots.size()]; + int i = 0; + + for (ZipMap rootMap : roots.values()) { + ret[i++] = rootMap.zipContent; + } + + return ret; + + } + + public static ZipFileContent createZipFileContent(ZipFile file, String filePath) { + + Enumeration entries = file.entries(); + + if (!entries.hasMoreElements()) { + return null; + } + + int beginIndex; + int endIndex; + + if (filePath.charAt(0) == '/') { + beginIndex = 1; + + } else { + beginIndex = 0; + } + + ZipMap root = new ZipMap(); + + if (filePath.length() > 1 && filePath.charAt(filePath.length() - 1) == '/') { + endIndex = filePath.length() - 1; + + } else { + endIndex = filePath.length(); + } + + filePath = filePath.substring(beginIndex, endIndex); + // HashMap roots = new HashMap(); + + do { + ZipEntry entry = entries.nextElement(); + String name = entry.getName(); + + if (name.length() > 0) { + + if (name.charAt(name.length() - 1) == '/') { + endIndex = 1; + + } else { + endIndex = 0; + } + + if (name.length() - endIndex == filePath.length()) { + root.setEntry(file, entry); + + } else if (filePath.length() == 0 || (name.startsWith(filePath) && name.charAt(filePath.length()) == '/')) { + + name = name.substring(filePath.length()); + String[] path = name.split("/"); + + ZipMap current = root; + + // if (current == null) { + // current = new ZipMap(); + // roots.put(path[0], current); + // + // if (path.length == 1) { + // current.setEntry(file, entry); + // continue; + // + // } + // + // } + + if (path.length > 0) { + + int i; + + if (path[0].length() == 0) { + i = 1; + + } else { + i = 0; + } + + for (; i < path.length - 1; i++) { + ZipMap actual = current.get(path[i]); + + if (actual == null) { + actual = new ZipMap(); + current.put(path[i], actual); + + } + + current = actual; + + } + + ZipMap entryMap = current.get(path[path.length - 1]); + + if (entryMap == null) { + entryMap = new ZipMap(); + current.put(path[path.length - 1], entryMap); + + } + + entryMap.setEntry(file, entry); + + } + + } + + } + + } while (entries.hasMoreElements()); + + createZipFileContentChildren(root); + + return root.zipContent; + + } + + private static void createZipFileContentChildren(ZipMap map) { + ZipFileContent[] children = new ZipFileContent[map.size()]; + int i = 0; + + for (ZipMap childMap : map.values()) { + + if (childMap.zipContent == null) { + throw new RuntimeException("could not load zip file hierarchy for file: " + map.zipContent.file); + } + + children[i++] = childMap.zipContent; + + createZipFileContentChildren(childMap); + + } + + map.zipContent.children = children; + + } + + @Override + public String toString() { + return this.file.getName() + '/' + this.entry.getName(); + } + + private static class ZipMap extends HashMap { + + private static final long serialVersionUID = 6514645087432837480L; + + ZipFileContent zipContent; + + void setEntry(ZipFile zipFile, ZipEntry entry) { + this.zipContent = new ZipFileContent(zipFile, entry); + } + + ZipFileContent[] getChildren() { + + ZipFileContent ret[] = new ZipFileContent[this.size()]; + int i = 0; + + for (ZipMap actual : this.values()) { + ret[i++] = actual.zipContent; + } + + return ret; + + } + + } + +} -- cgit v1.2.3