/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kie.workbench.common.services.refactoring.backend.server.impact; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.kie.workbench.common.services.refactoring.backend.server.indexing.AbstractFileIndexer; import org.kie.workbench.common.services.refactoring.model.index.ResourceReference; import org.kie.workbench.common.services.refactoring.model.index.Resource; import org.kie.workbench.common.services.refactoring.model.index.SharedPart; import org.kie.workbench.common.services.refactoring.service.PartType; import org.kie.workbench.common.services.refactoring.service.ResourceType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class should be extended by all "Visitor" implementations in different editor backends. These Visitor implementations * are responsible for collecting reference part information about the assets that they modify. * </p> * Subsequently, the Visitor implementation instance (and extended {@link ResourceReferenceCollector} instance) is passed to the * protected {@link AbstractFileIndexer} addReferencedResourcesToIndexBuilder(..) method, so that the collected reference information * can be added to the index, to be used during change impact and refactoring. * * </p> */ public abstract class ResourceReferenceCollector { private static final Logger logger = LoggerFactory.getLogger(ResourceReferenceCollector.class); private Map<String, Resource> resourcesMap; private Map<String, ResourceReference> referencedResourcesMap; private Set<SharedPart> sharedPartReferences; /** * Used by the {@link AbstractFileIndexer} implementation to get the reference information. * @return A {@link Collection} of {@link ResourceReference} instances. */ public Collection<ResourceReference> getResourceReferences() { if( referencedResourcesMap != null ) { return referencedResourcesMap.values(); } return Collections.emptyList(); } /** * Used by the {@link AbstractFileIndexer} implementation to get the shared reference information. * @return A {@link Collection} of {@link ResourceReference} instances. */ public Collection<SharedPart> getSharedReferences() { if( sharedPartReferences != null ) { return sharedPartReferences; } return Collections.emptyList(); } /** * Used by the {@link AbstractFileIndexer} implementation to get the shared reference information. * @return A {@link Collection} of {@link ResourcePartReference} instances. */ public Collection<Resource> getResources() { if( resourcesMap != null ) { return resourcesMap.values(); } return Collections.emptyList(); } private Map<String, ResourceReference> internalGetResourceReferences() { if( referencedResourcesMap == null ) { referencedResourcesMap = new HashMap<>(4); } return referencedResourcesMap; } /** * Used by the Visitor implementation to add the FQN and type of a reference. * @param fullyQualifiedName The FQN of the reference * @param type The type of the reference part. * @return The {@link ResourceReference} being added, so that more part references can be added. */ public ResourceReference addResourceReference(String fullyQualifiedName, ResourceType type) { ResourceReference resRef = internalGetResourceReferences().get(fullyQualifiedName); if( resRef == null ) { resRef = new ResourceReference(fullyQualifiedName, type); referencedResourcesMap.put(fullyQualifiedName, resRef); } else if( type != null && ! type.equals(resRef.getResourceType()) ) { String msg = "Existing resource reference found with type " + resRef.getResourceType().toString() + " (tried to add resrouce reference of type " + type.toString() + ")"; logger.error(msg); } return resRef; } /** * Used by the Visitor implemenation to add multiple {@link ResourceReference} instances at once. * @param collector A {@link ResourceReferenceCollector} containing information about the asset being indexed. */ public void addResourceReferences(ResourceReferenceCollector collector) { if( collector.referencedResourcesMap != null ) { Map<String, ResourceReference> refResMap = internalGetResourceReferences(); for( Entry<String, ResourceReference> resRefEntry : collector.referencedResourcesMap.entrySet() ) { ResourceReference newResRef = resRefEntry.getValue(); ResourceReference existingResRef = refResMap.put(resRefEntry.getKey(), newResRef); if( existingResRef != null ) { newResRef.addPartReference(existingResRef.getPartReferences()); } } } } /** * Used by the Visitor implementation to add the name and type of a shared reference. * @param partName The name of the shared reference * @param partType The type of the shared reference. */ public void addSharedReference(String partName, PartType partType) { if( sharedPartReferences == null ) { sharedPartReferences = new HashSet<>(); } sharedPartReferences.add(new SharedPart(partName, partType)); } public Resource addResource(String resourceFQN, ResourceType type) { if( resourcesMap == null ) { resourcesMap = new HashMap<>(4); } Resource resRef = resourcesMap.get(resourceFQN); if( resRef == null ) { resRef = new Resource(resourceFQN, type); resourcesMap.put(resourceFQN, resRef); } else if( type != null && ! type.equals(resRef.getResourceType()) ) { String msg = "Existing resource found with type " + resRef.getResourceType().toString() + " (tried to add resource reference of type " + type.toString() + ")"; logger.error(msg); } return resRef; } }