blob: 8f119952b4dfc5bb723ffb7a3b25f7d058e65661 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2012 Red Hat and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat - Initial API and implementation
* Roberto Sanchez Herrera - [371907] Do not add duplicate resources
*******************************************************************************/
package org.eclipse.jst.common.internal.modulecore;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jst.common.internal.modulecore.SingleRootUtil.SingleRootCallback;
import org.eclipse.wst.common.componentcore.internal.DependencyType;
import org.eclipse.wst.common.componentcore.internal.flat.AbstractFlattenParticipant;
import org.eclipse.wst.common.componentcore.internal.flat.ChildModuleReference;
import org.eclipse.wst.common.componentcore.internal.flat.FlatFile;
import org.eclipse.wst.common.componentcore.internal.flat.FlatFolder;
import org.eclipse.wst.common.componentcore.internal.flat.FlatResource;
import org.eclipse.wst.common.componentcore.internal.flat.FlatVirtualComponent.FlatComponentTaskModel;
import org.eclipse.wst.common.componentcore.internal.flat.IChildModuleReference;
import org.eclipse.wst.common.componentcore.internal.flat.IFlatFile;
import org.eclipse.wst.common.componentcore.internal.flat.IFlatFolder;
import org.eclipse.wst.common.componentcore.internal.flat.IFlatResource;
import org.eclipse.wst.common.componentcore.internal.flat.IFlattenParticipant;
import org.eclipse.wst.common.componentcore.internal.flat.VirtualComponentFlattenUtility;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;
/**
* Single root optimization.
* @author rob
*/
public class SingleRootExportParticipant extends AbstractFlattenParticipant {
private SingleRootParticipantCallback callbackHandler;
private IVirtualComponent rootComponent;
private FlatComponentTaskModel dataModel;
private IFlattenParticipant[] delegates;
private List<IChildModuleReference> children;
private IVirtualReference[] referencesToAddAsResources = null;
public interface SingleRootParticipantCallback extends SingleRootCallback {
public IFlattenParticipant[] getDelegateParticipants();
}
public SingleRootExportParticipant() {
super();
callbackHandler = null;
}
public SingleRootExportParticipant(SingleRootParticipantCallback handler) {
this();
callbackHandler = handler;
}
@Override
public void initialize(IVirtualComponent component,
FlatComponentTaskModel dataModel, List<IFlatResource> resources) {
this.rootComponent = component;
this.dataModel = dataModel;
}
private void initializeDelegates() {
if (callbackHandler != null) {
delegates = callbackHandler.getDelegateParticipants();
}
else {
delegates = new IFlattenParticipant[] {};
}
}
@Override
public boolean canOptimize(IVirtualComponent component,
FlatComponentTaskModel dataModel) {
return new SingleRootUtil(component, callbackHandler).isSingleRoot();
}
@Override
public void optimize(IVirtualComponent component, FlatComponentTaskModel dataModel,
List<IFlatResource> resources, List<IChildModuleReference> childModules) {
try {
resources.clear(); // We want complete control
childModules.clear();
children = childModules;
initializeDelegates();
IContainer container = new SingleRootUtil(component, callbackHandler).getSingleRoot();
IFlatResource[] mr = getMembers(resources, container, new Path("")); //$NON-NLS-1$
int size = mr.length;
for (int j = 0; j < size; j++) {
resources.add(mr[j]);
}
addChildModules(component);
// addChildModules might have added elements to referencesToAddAsResources while looking for
// child modules. Let's add these references
addReferencesAsResources(resources, referencesToAddAsResources);
// run finalizers
for (int i = 0; i < delegates.length; i++) {
delegates[i].finalize(component, dataModel, resources);
}
} catch( CoreException ce ) {
// TODO
}
}
/*
* This function adds resources based on the list of references.
*/
private void addReferencesAsResources(List<IFlatResource> resources,
IVirtualReference[] references) {
for (IVirtualReference reference:references){
File f = (File)reference.getReferencedComponent().getAdapter(File.class);
FlatFile file = new FlatFile(f, reference.getArchiveName(), reference.getRuntimePath());
FlatResource existingRes = VirtualComponentFlattenUtility.getExistingModuleResource(resources, file.getModuleRelativePath().append(file.getName()));
// If the resource already exist in the list of resources, do not add it
if ( existingRes == null){
// The resource is not in the list if resources, so add it.
IPath path = reference.getRuntimePath(); // Folder to add the ref in
IFlatFolder folder = (IFlatFolder) VirtualComponentFlattenUtility
.getExistingModuleResource(resources, path.makeRelative());
if( folder == null ) {
folder = VirtualComponentFlattenUtility.ensureParentExists(resources, path, null);
}
if( folder == null )
resources.add(file);
else
VirtualComponentFlattenUtility.addMembersToModuleFolder(folder, new IFlatFile[]{file});
}
}
}
protected IFlatResource[] getMembers(List<IFlatResource> members,
IContainer cont, IPath path) throws CoreException {
IResource[] res = cont.members();
int size2 = res.length;
List list = new ArrayList(size2);
for (int j = 0; j < size2; j++) {
if (res[j] instanceof IContainer) {
IContainer cc = (IContainer) res[j];
// Retrieve already existing module folder if applicable
IFlatFolder mf = (FlatFolder) VirtualComponentFlattenUtility.getExistingModuleResource(members,path.append(new Path(cc.getName()).makeRelative()));
if (mf == null) {
mf = new FlatFolder(cc, cc.getName(), path);
IFlatFolder parent = (FlatFolder) VirtualComponentFlattenUtility.getExistingModuleResource(members, path);
if (path.isEmpty() || path.equals(new Path("/"))) //$NON-NLS-1$
members.add(mf);
else {
if (parent == null)
parent = VirtualComponentFlattenUtility.ensureParentExists(members, path, cc);
VirtualComponentFlattenUtility.addMembersToModuleFolder(parent, new IFlatResource[] {mf});
}
}
IFlatResource[] mr = getMembers(members, cc, path.append(cc.getName()));
VirtualComponentFlattenUtility.addMembersToModuleFolder(mf, mr);
} else {
IFile f = (IFile) res[j];
IFlatFile mf = VirtualComponentFlattenUtility.createModuleFile(f, path);
if (shouldAddComponentFile(rootComponent, mf))
list.add(mf);
}
}
FlatResource[] mr = new FlatResource[list.size()];
list.toArray(mr);
return mr;
}
protected void addChildModules(IVirtualComponent vc) throws CoreException {
ArrayList<IVirtualReference> refAsResource = new ArrayList<IVirtualReference>();
Map<String, Object> options = new HashMap<String, Object>();
options.put(IVirtualComponent.REQUESTED_REFERENCE_TYPE, IVirtualComponent.FLATTENABLE_REFERENCES);
IVirtualReference[] allReferences = vc.getReferences(options);
for (int i = 0; i < allReferences.length; i++) {
IVirtualReference reference = allReferences[i];
if (reference.getDependencyType() == DependencyType.USES ) {
if (shouldIgnoreReference(vc, reference))
continue;
if (isChildModule(vc, reference)) {
ChildModuleReference cm = new ChildModuleReference(reference, new Path("")); //$NON-NLS-1$
List<IChildModuleReference> duplicates = new ArrayList();
for (IChildModuleReference tmp : children) {
if (tmp.getRelativeURI().equals(cm.getRelativeURI()))
duplicates.add(tmp);
}
children.removeAll(duplicates);
children.add(cm);
} else {
// It's not a child module, but it is a reference that needs to be added in anyway
refAsResource.add(reference);
}
}
}
referencesToAddAsResources = refAsResource.toArray(new IVirtualReference[refAsResource.size()]);
}
protected boolean isChildModule(IVirtualComponent component, IVirtualReference referencedComponent) {
for (int i = 0; i < delegates.length; i++) {
if (delegates[i].isChildModule(component, referencedComponent, dataModel))
return true;
}
return false;
}
protected boolean shouldIgnoreReference(IVirtualComponent component, IVirtualReference referencedComponent) {
for (int i = 0; i < delegates.length; i++ ) {
if (delegates[i].shouldIgnoreReference(component, referencedComponent, dataModel))
return true;
}
return false;
}
public boolean shouldAddComponentFile(IVirtualComponent component, IFlatFile file) {
for (int i = 0; i < delegates.length; i++) {
if (delegates[i].isChildModule(component, dataModel, file)) {
ChildModuleReference child = new ChildModuleReference(component.getProject(), file);
children.add(child);
return false;
} else if (!delegates[i].shouldAddExportableFile(component, component, dataModel, file))
return false;
}
return true;
}
}