blob: 97a0274b29baf39bb4ac4a82ceed167bc7b791ea [file] [log] [blame]
/**
* Copyright (c) 2020 RBEI and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v. 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Adhith Gopal - Initial API and Implementation
*
*/
package org.eclipse.blockchain.model.core;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.eclipse.blockchain.model.ethproject.DeploymentModel;
import org.eclipse.blockchain.model.ethproject.EthereumProject;
import org.eclipse.blockchain.model.ethproject.EthprojectFactory;
import org.eclipse.blockchain.model.ethproject.EthprojectPackage;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
/**
*
* EMF Notification mechanism is not used here, if required then Adapter's have
* to be created and registered in the list of adapters
*/
public class EthereumProjectHandler {
private static EthereumProjectHandler instance = null;
private final Map<String, EthereumProject> projectMap = new HashMap<>();
private EthereumProjectHandler() {
}
/**
* @return This provides an Ethereum Project Handle which can be used to
* manipulate the Ethereum Project
*/
public static EthereumProjectHandler getInstance() {
if (null == instance) {
instance = new EthereumProjectHandler();
/**
* This is just to initialize the EMF model and listeners
*/
EthprojectPackage.eINSTANCE.eClass();
}
return instance;
}
/**
* This returns the Ethereum Project instance that matches the project name. If
* none match then a new Ethereum Project instance is created
*
* @param projectName - The name of the project
* @return - EthereumProject
*/
public EthereumProject getEthProject(final String projectName) {
return this.projectMap.computeIfAbsent(projectName, (v) -> {
EthereumProject ethProj = EthprojectFactory.eINSTANCE.createEthereumProject();
/**
* Initialize all collections so that no NPE gets thrown
*/
ethProj.setProjectBuilders(new ArrayList<>());
ethProj.setProjectNatures(new ArrayList<>());
ethProj.setCompiledSolidityFiles(new HashSet<>());
ethProj.setEnvironmentBasedDeployedModel(new HashMap<>());
return ethProj;
});
}
/**
* Remove the project from the map
*
* @param projectName - The name of project which should be removed.
*/
public void removeEthProject(final String projectName) {
this.projectMap.remove(projectName);
}
/**
* Adds the given nature to the list of project natures of ethereum project
*
* @param ethProject - The Ethereum Project for which nature should be added
* @param natureId - The nature id string
*/
public void addProjectNature(final EthereumProject ethProject, final String natureId) {
ethProject.getProjectNatures().add(natureId);
}
/**
* Adds the given builder to the list of project builders of ethereum project
*
* @param ethProject - The Ethereum Project for which nature should be added
* @param builderId - The builder id string
*/
public void addProjectBuilder(final EthereumProject ethProject, final String builderId) {
ethProject.getProjectBuilders().add(builderId);
}
/**
* @param projectName - The ethereum Project name for which first matching sol
* file should be returned
* @return - The first matching sol file, if none then null
* @throws CoreException -
*/
public IFile getSolFile(final String projectName) throws CoreException {
EthereumProject ethProject = this.projectMap.get(projectName);
IProject project = ethProject.getProject();
if (project != null) {
project.accept(new IResourceVisitor() {
@Override
public boolean visit(final IResource resource) throws CoreException {
if ((resource instanceof IFile) && (resource.getFileExtension() != null)
&& resource.getFileExtension().equals("sol")) {
ethProject.setFirstMatchingSolFile(resource.getProjectRelativePath().toOSString());
return false;
}
return true;
}
});
return (IFile) project.findMember(ethProject.getFirstMatchingSolFile());
}
return null;
}
/**
* This method is used to add the compiled solidity files to the set that is
* maintained in this project
*
* @param solidityFile - The compiled solidity file that belongs to this project
*/
public void addCompiledSolidityFiles(final IResource solidityFile) {
EthereumProject ethProject = this.projectMap.get(solidityFile.getProject().getName());
ethProject.getCompiledSolidityFiles().add(solidityFile.getProjectRelativePath().toOSString());
}
/**
*
* @param scFile - The SC resource
* @param environment - This denotes the environment into which this SC is
* deployed(Embedded/Geth)
* @return - Whether the SC is deployed into the passed in environment
*/
public boolean isSCDeployed(final IResource scFile, final String environment) {
Map<String, DeploymentModel> map = this.projectMap.get(scFile.getProject().getName())
.getEnvironmentBasedDeployedModel().get(environment);
return (map != null) && map.containsKey(scFile.getProjectRelativePath().toOSString());
}
/**
* This creates a deployment model for a smart contract that is deployed into a
* blockchain
*
* @param contractAddress - The contract address of the deployed SC
* @param scFile - The SC resource
* @param lastUsedAccount - The account that was last used for performing a
* transaction
* @param environment - This denotes the environment into which this SC is
* deployed(Embedded/Geth)
*/
public void createDeploymentModel(final String contractAddress, final IResource scFile,
final String lastUsedAccount, final String environment) {
DeploymentModel deploymentModel = EthprojectFactory.eINSTANCE.createDeploymentModel();
deploymentModel.setContractAddress(contractAddress);
deploymentModel.setScFile(scFile.getProjectRelativePath().toOSString());
deploymentModel.setLastUsedAccount(lastUsedAccount);
deploymentModel.setEnvironment(environment);
EthereumProject ethProject = this.projectMap.get(scFile.getProject().getName());
/**
* The below addition will add all the DM's that get created to the ETHProj
* model and will be serialized during modal save.
*/
ethProject.getDeploymentmodel().add(deploymentModel);
Map<String, DeploymentModel> depModelMap = ethProject.getEnvironmentBasedDeployedModel()
.computeIfAbsent(environment, m -> new HashMap<>());
depModelMap.put(scFile.getProjectRelativePath().toOSString(), deploymentModel);
}
/**
*
* @param scFile - The SC resource
* @param environment - This denotes the environment into which this SC is
* deployed(Embedded/Geth)
* @return - The account that was last used for performing a transaction
*/
public String getLastUsedAccount(final IResource scFile, final String environment) {
Map<String, DeploymentModel> map = this.projectMap.get(scFile.getProject().getName())
.getEnvironmentBasedDeployedModel().get(environment);
if ((map != null) && map.containsKey(scFile.getProjectRelativePath().toOSString())) {
return map.get(scFile.getProjectRelativePath().toOSString()).getLastUsedAccount();
}
return "";
}
/**
* This is used to update the last used account(for transacting with blockchain)
*
* @param scFile - The SC resource
* @param accountDetails - The new account that was used for transaction
* @param environment - This denotes the environment into which this SC is
* deployed(Embedded/Geth)
*/
public void updateLastUsedAccount(final IResource scFile, final String accountDetails, final String environment) {
Map<String, DeploymentModel> map = this.projectMap.get(scFile.getProject().getName())
.getEnvironmentBasedDeployedModel().get(environment);
if ((map != null) && map.containsKey(scFile.getProjectRelativePath().toOSString())) {
map.get(scFile.getProjectRelativePath().toOSString()).setLastUsedAccount(accountDetails);
}
}
/**
*
* @param scFile - The SC resource
* @param environment - This denotes the environment into which this SC is
* deployed(Embedded/Geth)
* @return - The contract address of the deployed SC
*/
public String getContractAddress(final IResource scFile, final String environment) {
Map<String, DeploymentModel> map = this.projectMap.get(scFile.getProject().getName())
.getEnvironmentBasedDeployedModel().get(environment);
if ((map != null) && map.containsKey(scFile.getProjectRelativePath().toOSString())) {
return map.get(scFile.getProjectRelativePath().toOSString()).getContractAddress();
}
return "";
}
/**
* This method is used to remove the SC resource from the map which holds
* deployed resources
*
* @param projectName - The ethereum project name from which SC should be
* removed
* @param resource - The SC resource
* @param environment - This denotes the environment into which this SC is
* deployed(Embedded/Geth)
*/
public void removeDeploymentModelForResource(final IResource resource, final String environment) {
EthereumProject ethProject = this.projectMap.get(resource.getProject().getName());
if (null == ethProject) {
return;
}
Map<String, Map<String, DeploymentModel>> envMap = ethProject.getEnvironmentBasedDeployedModel();
if (null == envMap) {
return;
}
Map<String, DeploymentModel> map = envMap.get(environment);
if ((map != null) && map.containsKey(resource.getProjectRelativePath().toOSString())) {
DeploymentModel dm = map.remove(resource.getProjectRelativePath().toOSString());
/**
* Also remove from ethProject
*/
ethProject.getDeploymentmodel().remove(dm);
}
}
}