/*
* Copyright (c) 2017 wetransform GmbH
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* wetransform GmbH <http://www.wetransform.to>
*/
package eu.esdihumboldt.hale.io.haleconnect.project;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.text.MessageFormat;
import de.fhg.igd.slf4jplus.ALogger;
import de.fhg.igd.slf4jplus.ALoggerFactory;
import eu.esdihumboldt.hale.common.core.HalePlatform;
import eu.esdihumboldt.hale.common.core.io.IOProviderConfigurationException;
import eu.esdihumboldt.hale.common.core.io.ProgressIndicator;
import eu.esdihumboldt.hale.common.core.io.project.impl.ArchiveProjectWriter;
import eu.esdihumboldt.hale.common.core.io.project.model.Project;
import eu.esdihumboldt.hale.common.core.io.report.IOReport;
import eu.esdihumboldt.hale.common.core.io.report.IOReporter;
import eu.esdihumboldt.hale.io.haleconnect.HaleConnectException;
import eu.esdihumboldt.hale.io.haleconnect.HaleConnectService;
import eu.esdihumboldt.hale.io.haleconnect.HaleConnectServices;
import eu.esdihumboldt.hale.io.haleconnect.HaleConnectUrnBuilder;
import eu.esdihumboldt.hale.io.haleconnect.Owner;
import eu.esdihumboldt.hale.io.haleconnect.OwnerType;
/**
* Saves a project (optonally including all related resources) as a ZIP archive
* and uploads it to hale connect.
*
* @author Florian Esser
*/
public class HaleConnectProjectWriter extends ArchiveProjectWriter {
private static final ALogger log = ALoggerFactory.getLogger(HaleConnectProjectWriter.class);
/**
* Owner of the uploaded project
*/
public static final String OWNER_TYPE = "ownerType";
/**
* Share uploaded project publicly
*/
public static final String SHARING_PUBLIC = "sharingOptions.public";
/**
* Enable versioning for uploaded project
*/
public static final String ENABLE_VERSIONING = "enableVersioning";
private final HaleConnectService haleConnect;
private URI projectUri;
private URI clientAccessUrl;
/**
* Creates a hale connect project writer
*/
public HaleConnectProjectWriter() {
super();
this.haleConnect = HalePlatform.getService(HaleConnectService.class);
}
@Override
protected IOReport execute(ProgressIndicator progress, IOReporter reporter)
throws IOProviderConfigurationException, IOException {
if (!haleConnect.isLoggedIn()) {
throw new IOProviderConfigurationException("Must be logged in to hale connect");
}
boolean enableVersioning = getParameter(ENABLE_VERSIONING).as(Boolean.class);
boolean publicAccess = getParameter(SHARING_PUBLIC).as(Boolean.class);
String ownerTypeParameter = getParameter(OWNER_TYPE).as(String.class);
OwnerType ownerType;
try {
ownerType = OwnerType.fromJsonValue(ownerTypeParameter);
} catch (IllegalArgumentException e) {
throw new IOProviderConfigurationException(
MessageFormat.format("Invalid owner type: {0}", ownerTypeParameter), e);
}
// redirect project archive to temporary local file
File projectArchive = Files.createTempFile("hc-arc", ".zip").toFile();
IOReport report;
try (final FileOutputStream archiveStream = new FileOutputStream(projectArchive)) {
report = createProjectArchive(archiveStream, reporter, progress);
}
URI location = getTarget().getLocation();
Project project = getProject();
String projectId;
Owner owner;
if (location == null) {
// was not shared before
String ownerId;
switch (ownerType) {
case USER:
ownerId = haleConnect.getSession().getUserId();
break;
case ORGANISATION:
if (haleConnect.getSession().getOrganisationIds().isEmpty()) {
throw new IOProviderConfigurationException(MessageFormat.format(
"Owner type is set to ORGANISATION but user \"{0}\" is not associated with any organisation",
haleConnect.getSession().getUsername()));
}
ownerId = haleConnect.getSession().getOrganisationIds().iterator().next();
break;
default:
throw new IOProviderConfigurationException(
MessageFormat.format("Unknown owner type: {0}", ownerType));
}
owner = new Owner(ownerType, ownerId);
try {
projectId = haleConnect.createProject(project.getName(), project.getAuthor(), owner,
enableVersioning);
haleConnect.setProjectSharingOptions(projectId, owner,
new SharingOptions(publicAccess));
} catch (HaleConnectException e) {
throw new IOException(e.getMessage(), e);
}
}
else if (!HaleConnectUrnBuilder.isValidProjectUrn(location)) {
throw new IOProviderConfigurationException(
MessageFormat.format("Cannot write to location: {0}", location.toString()));
}
else {
projectId = HaleConnectUrnBuilder.extractProjectId(location);
owner = HaleConnectUrnBuilder.extractProjectOwner(location);
}
boolean result;
try {
result = haleConnect.uploadProjectFile(projectId, owner, projectArchive, progress);
} catch (HaleConnectException e) {
throw new IOException(e.getMessage(), e);
}
// Make sure the bucket name corresponds to possibly updated project
// name
try {
haleConnect.setProjectName(projectId, owner, project.getName());
} catch (HaleConnectException e) {
// This is non-fatal
log.warn(MessageFormat.format(
"Unable to update project bucket name for project {0}: {1}",
HaleConnectUrnBuilder.buildProjectUrn(owner, projectId).toString(),
e.getMessage()), e);
}
this.clientAccessUrl = HaleConnectUrnBuilder.buildClientAccessUrl(
haleConnect.getBasePathManager().getBasePath(HaleConnectServices.WEB_CLIENT), owner,
projectId);
this.projectUri = HaleConnectUrnBuilder.buildProjectUrn(owner, projectId);
reporter.setSuccess(result);
return reporter;
}
/**
* @return the URI of the created project
*/
public URI getProjectUri() {
return this.projectUri;
}
/**
* @return the URL required to access the transformation project via the
* hale connect web client
*/
public URI getClientAccessUrl() {
return this.clientAccessUrl;
}
}