/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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.wso2.carbon.registry.indexing.indexer;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.registry.core.Association;
import org.wso2.carbon.registry.core.Collection;
import org.wso2.carbon.registry.core.Comment;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.ActionConstants;
import org.wso2.carbon.registry.core.Tag;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
import org.wso2.carbon.registry.indexing.AsyncIndexer.File2Index;
import org.wso2.carbon.registry.indexing.IndexingConstants;
import org.wso2.carbon.registry.indexing.IndexingManager;
import org.wso2.carbon.registry.indexing.solr.IndexDocument;
import org.wso2.carbon.registry.indexing.solr.SolrClient;
import org.wso2.carbon.registry.indexing.utils.IndexingUtils;
import org.wso2.carbon.user.core.UserRealm;
import org.wso2.carbon.user.core.UserStoreException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* IndexDocumentCreator class is responsible for create the IndexDocument for solr server.
*/
public class IndexDocumentCreator {
// Instance of file2Index
private final File2Index file2Index;
// Instance of indexer
private Indexer indexer;
private boolean isMediaTypeSet = false;
private String resourcePath = null;
private UserRegistry registry;
private Resource resource = null;
private static final Log log = LogFactory.getLog(IndexDocumentCreator.class);
//TODO: Move to IndexingConstants in 5.2.0
private static final String FIELD_ALLOWED_ROLES = "allowedRoles";
// Indexing fields attribute Map
private Map<String, List<String>> attributes = new HashMap<String, List<String>>();
public IndexDocumentCreator(File2Index file2Index, Resource resource) {
this.file2Index = file2Index;
this.resource = resource;
// Get the user registry
this.registry = IndexingManager.getInstance().getRegistry(file2Index.tenantId);
// Set the path of the resource
resourcePath = file2Index.path;
}
/**
* Method to create the IndexDocument with all attributes need in advance search
* 1. Get the IndexDocument defined for the mediaType
* 2. Then update the document with attributes need for the advance search
* 3. If mediaType is null create the IndexDocument with attributes need for advance search
* @throws RegistryException
*/
public void createIndexDocument() throws RegistryException, IndexerException {
file2Index.lcName = resource.getProperty("registry.LC.name");
file2Index.lcState = file2Index.lcName != null ? resource.getProperty("registry.lifecycle." + file2Index.lcName + ".state") : null;
file2Index.mediaType = resource.getMediaType();
// Check for resources that can get the byte content
if (!(resource instanceof Collection)
|| IndexingManager.getInstance().getIndexerForMediaType(file2Index.mediaType) != null) {
file2Index.data = IndexingUtils.getByteContent(resource, file2Index.sourceURL);
}
// Get the indexDocument
IndexDocument indexDocument = getIndexDocument();
// Get the index fields
if (indexDocument.getFields() != null) {
attributes = indexDocument.getFields();
}
// Set the resource name to attribute list
addResourceName();
// Set the author of the resource to the attribute list
addAuthor();
// Set the last updater of the resource to the attribute list
addLastUpdateUser();
// Set the created date of the resource to the attribute list
addCreatedDate();
// Set the last updated date of the resource to the attribute list
addLastUpdatedDate();
// Set the last mediaType of the resource to the attribute list
addMediaType();
if (!(resource instanceof Collection)) {
// Set Comments of the resource to the attribute list
addComments();
// Set Tags of the resource to the attribute list
addTags();
// Set Association types and destinations of the resource to the attribute list
addAssociations();
}
// Set Property names and values of the resource to the attribute list
addPropertyData();
// Add allowed roles of the resource path.
addAllowedRoles();
// Set the attribute fields.
indexDocument.setFields(attributes);
// Set the tenant id.
indexDocument.setTenantId(file2Index.tenantId);
// Add the document to solr server.
SolrClient.getInstance().addDocument(indexDocument);
}
/**
* Method to set the resource Property names and values to IndexDocument attribute list.
*/
private void addPropertyData() {
// Get the property values of the resource
Properties properties = resource.getProperties();
// Get the property key set
Set keySet = properties.keySet();
List<String> propertyList = new ArrayList<String>();
String propertyKey;
if (keySet.size() > 0) {
Object[] propertyKeys = keySet.toArray();
List values;
for (Object key : propertyKeys) {
propertyKey = key.toString();
values = (List) properties.get(key);
String propertyValue = "";
if (values != null) {
for (Object value : values) {
propertyValue += value + ",";
}
} else {
propertyValue = ",";
}
propertyList.add(propertyKey + "," + propertyValue);
}
}
if (propertyList.size() > 0) {
attributes.put(IndexingConstants.FIELD_PROPERTY_VALUES, propertyList);
}
}
/**
* Method to set the resource Association types and destinations to IndexDocument attribute list.
*/
private void addAssociations() throws RegistryException {
// Add resource association types and destinations
Association[] associations;
try {
associations = registry.getAllAssociations(resourcePath);
} catch (RegistryException e) {
String message = "Error at IndexDocumentCreator when getting Registry Associations.";
log.error(message, e);
throw new RegistryException(message, e);
}
List<String> associationTypeList = new ArrayList<>();
List<String> associationDestinationList = new ArrayList<>();
if (associations != null && associations.length > 0) {
for (Association association : associations) {
associationTypeList.add(association.getAssociationType());
associationDestinationList.add(association.getDestinationPath());
}
if (associationTypeList.size() > 0) {
attributes.put(IndexingConstants.FIELD_ASSOCIATION_TYPES, associationTypeList);
}
if (associationDestinationList.size() > 0) {
attributes.put(IndexingConstants.FIELD_ASSOCIATION_DESTINATIONS, associationDestinationList);
}
}
}
/**
* Method to set the resource Tags to IndexDocument attribute list.
*/
private void addTags() throws RegistryException {
// Add resource tags
Tag[] tags;
tags = registry.getTags(resourcePath);
List<String> tagList = new ArrayList<>();
List<String> taxonomyList = new ArrayList<>();
if (tags != null && tags.length > 0) {
for (Tag tag : tags) {
if (tag.getTagName().contains("/")) {
taxonomyList.add(tag.getTagName().toLowerCase());
} else {
tagList.add(tag.getTagName());
}
}
if (tagList.size() > 0) {
attributes.put(IndexingConstants.FIELD_TAGS, tagList);
}
if (taxonomyList.size() > 0) {
attributes.put(IndexingConstants.FIELD_TAXONOMY, taxonomyList);
}
}
}
/**
* Method to set the resource comments to IndexDocument attribute list.
*/
private void addComments() throws RegistryException {
// Add resource comments
Comment[] comments;
try {
comments = registry.getComments(resourcePath);
} catch (RegistryException e) {
String message = "Error at IndexDocumentCreator when getting Registry Comment.";
log.error(message, e);
throw new RegistryException(message, e);
}
List<String> commentList = new ArrayList<>();
if (comments != null && comments.length > 0) {
for (Comment comment : comments) {
commentList.add(comment.getText());
}
if (commentList.size() > 0) {
attributes.put(IndexingConstants.FIELD_COMMENTS, commentList);
}
}
}
/**
* Method to set the resource mediaType to IndexDocument attribute list.
*/
private void addMediaType() {
// Check whether the media type is added by the mediaType Indexer
for (Map.Entry<String, List<String>> mediaTypeList : attributes.entrySet()) {
if (mediaTypeList.getKey().equals(IndexingConstants.FIELD_MEDIA_TYPE)) {
isMediaTypeSet = true;
break;
}
}
// Set the mediaType
if (!isMediaTypeSet) {
attributes.put(IndexingConstants.FIELD_MEDIA_TYPE, Arrays.asList(file2Index.mediaType));
}
}
/**
* Method to set the resource last updated date to IndexDocument attribute list.
*/
private void addLastUpdatedDate() {
// Set the last updated date
Date updatedDate = resource.getLastModified();
if (updatedDate != null) {
attributes.put(IndexingConstants.FIELD_LAST_UPDATED_DATE, Arrays.asList(updatedDate.toString()));
}
}
/**
* Method to set the resource created date to IndexDocument attribute list.
*/
private void addCreatedDate() {
// Set the created date
Date createdDate = resource.getCreatedTime();
if (createdDate != null) {
attributes.put(IndexingConstants.FIELD_CREATED_DATE, Arrays.asList(createdDate.toString()));
}
}
/**
* Method to set the resource last updater to IndexDocument attribute list.
*/
private void addLastUpdateUser() {
// Set the last update user
String lastUpdatedBy = resource.getLastUpdaterUserName();
if (lastUpdatedBy != null && !StringUtils.isEmpty(lastUpdatedBy)) {
attributes.put(IndexingConstants.FIELD_LAST_UPDATED_BY, Arrays.asList(lastUpdatedBy));
}
}
/**
* Method to set the resource author to IndexDocument attribute list.
*/
private void addAuthor() {
// Set the author of the resource
String createdBy = resource.getAuthorUserName();
if (createdBy != null && !StringUtils.isEmpty(createdBy)) {
attributes.put(IndexingConstants.FIELD_CREATED_BY, Arrays.asList(createdBy));
}
}
/**
* Method to set the resource name to IndexDocument attribute list.
*/
private void addResourceName() {
// Set the resource name
String resourceName = RegistryUtils.getResourceName(resourcePath);
if (StringUtils.isNotEmpty(resourceName)) {
attributes.put(IndexingConstants.FIELD_RESOURCE_NAME, Arrays.asList(resourceName));
}
}
/**
* Method to get the IndexDocument written for the media type.
* @return IndexDocument
* @throws RegistryException
*/
private IndexDocument getIndexDocument() throws RegistryException {
IndexDocument indexDocument;
// Get the Indexer if available
if (file2Index.mediaType != null) {
// Get the indexer define for the media type
indexer = IndexingManager.getInstance().getIndexerForMediaType(file2Index.mediaType);
}
if (indexer != null) {
try {
// Get the index document from pre-defined Indexer.
indexDocument = indexer.getIndexedDocument(file2Index);
} catch (RegistryException e) {
String message = "Error at IndexDocumentCreator when getting IndexDocument for mediaType.";
log.error(message, e);
throw new RegistryException(message, e);
}
} else {
indexDocument = new IndexDocument();
}
// Set path in index document
indexDocument.setPath(file2Index.path);
return indexDocument;
}
/**
* method to get allowed roles for the resource and to indexed list.
* @throws RegistryException
*/
private void addAllowedRoles() throws RegistryException {
try {
UserRealm userRealm = registry.getUserRealm();
String[] allowedRoles = userRealm.getAuthorizationManager().getAllowedRolesForResource(resourcePath, ActionConstants.GET);
if (log.isDebugEnabled()) {
log.debug("Allowed Roles for the resource: " + resourcePath + " : " + Arrays.toString(allowedRoles));
}
List<String> allowedRolesLowerCase = new ArrayList<>();
for (String role: allowedRoles) {
if (role != null) {
allowedRolesLowerCase.add(role.toLowerCase());
}
}
attributes.put(FIELD_ALLOWED_ROLES, allowedRolesLowerCase);
if (log.isDebugEnabled()) {
log.debug("Indexed allowed roles for the resource: " + resourcePath + " : " + allowedRolesLowerCase);
}
} catch (UserStoreException e) {
throw new RegistryException("Unable to retrieve allowed roles for resource", e);
}
}
}