package org.diretto.web.richwebclient.view.sections; import java.io.File; import java.math.BigDecimal; import java.text.NumberFormat; import java.util.List; import java.util.Map; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import org.apache.commons.collections.MultiHashMap; import org.apache.commons.collections.MultiMap; import org.diretto.api.client.base.data.PlatformMediaType; import org.diretto.api.client.base.data.UploadInfo; import org.diretto.api.client.main.core.CoreService; import org.diretto.api.client.main.core.entities.Document; import org.diretto.api.client.main.core.entities.DocumentID; import org.diretto.api.client.main.core.entities.creation.PlatformAttachmentCreationData; import org.diretto.api.client.main.storage.StorageService; import org.diretto.api.client.main.storage.upload.UploadProcess; import org.diretto.api.client.main.storage.upload.UploadReport; import org.diretto.api.client.session.UserSession; import org.diretto.api.client.util.Observable; import org.diretto.web.richwebclient.RichWebClientApplication; import org.diretto.web.richwebclient.view.base.AbstractSection; import org.diretto.web.richwebclient.view.base.Section; import org.diretto.web.richwebclient.view.util.MediaTypeUtils; import org.diretto.web.richwebclient.view.util.ResourceUtils; import org.diretto.web.richwebclient.view.util.StyleUtils; import org.diretto.web.richwebclient.view.widgets.upload.client.base.FileInfo; import org.diretto.web.richwebclient.view.widgets.upload.server.MultipleUpload; import org.diretto.web.richwebclient.view.widgets.upload.server.MultipleUpload.MultipleUploadHandler; import org.diretto.web.richwebclient.view.windows.ConfirmWindow; import org.diretto.web.richwebclient.view.windows.MainWindow; import org.diretto.web.richwebclient.view.windows.UploadSettingsWindow; import org.diretto.web.richwebclient.view.windows.UploadSettingsWindow.UploadSettings; import org.diretto.web.richwebclient.view.windows.event.SectionChangeListener; import com.vaadin.ui.Alignment; import com.vaadin.ui.Embedded; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.ProgressIndicator; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window.CloseEvent; import com.vaadin.ui.Window.CloseListener; import com.vaadin.ui.themes.Reindeer; /** * This class represents an {@code UploadSection}. * * @author Tobias Schlecht */ public final class UploadSection extends AbstractSection { private static final long serialVersionUID = -359519159690651564L; private static final int POLLING_INTERVAL = 15000; private final RichWebClientApplication application; private final CoreService coreService; private final StorageService storageService; private boolean componentsAdded = false; private MainWindow mainWindow; private VerticalLayout mainLayout; private MultipleUpload multipleUpload; private HorizontalLayout captionLayout = null; private final Map<String, FileInfo> files = new ConcurrentHashMap<String, FileInfo>(); private final List<String> fileNames = new CopyOnWriteArrayList<String>(); private final Map<String, UploadSettings> settings = new ConcurrentHashMap<String, UploadSettings>(); private final Map<String, UploadSettings> preSettings = new ConcurrentHashMap<String, UploadSettings>(); private final MultiMap uploadedEmbeddeds = new MultiHashMap(); private final MultiMap publishedEmbeddeds = new MultiHashMap(); private FileInfo currentFile = null; /** * Constructs an {@link UploadSection}. * * @param application The corresponding {@code RichWebClientApplication} */ public UploadSection(RichWebClientApplication application) { super(application.getAuthenticationRegistry(), true, false, "Upload", "Share your media"); this.application = application; coreService = application.getCoreService(); storageService = application.getStorageService(); } @Override public synchronized void addComponents() { if(!componentsAdded) { mainWindow = (MainWindow) getWindow(); loadComponents(); mainWindow.addSectionChangeListener(new SectionChangeListener() { @Override public void onSectionChanged(Section section) { if(componentsAdded && section == UploadSection.this) { if(captionLayout != null && captionLayout.getComponentCount() == 1) { captionLayout.addComponent(getPollingProgressIndicator()); } } else { if(captionLayout != null && captionLayout.getComponentCount() > 1) { captionLayout.removeComponent(captionLayout.getComponent(1)); } } } }); componentsAdded = true; } } /** * Loads the content of this {@link Section}. */ private void loadComponents() { removeAllComponents(); captionLayout = new HorizontalLayout(); captionLayout.addComponent(StyleUtils.getLabelH1(title)); captionLayout.addComponent(getPollingProgressIndicator()); addComponent(captionLayout); mainLayout = new VerticalLayout(); mainLayout.setStyleName(Reindeer.LAYOUT_BLACK); mainLayout.setMargin(true); mainLayout.setSpacing(true); addComponent(mainLayout); mainLayout.addComponent(StyleUtils.getLabelH2("File Upload")); mainLayout.addComponent(StyleUtils.getHorizontalLine()); mainLayout.addComponent(StyleUtils.getLabel("Select the files which you want to upload")); mainLayout.addComponent(StyleUtils.getLabelSmall("(To choose multiple files, just press the CTRL-key while selecting the files)")); mainLayout.addComponent(StyleUtils.getVerticalSpaceSmall()); multipleUpload = new MultipleUpload(application, "Select Files", Reindeer.BUTTON_DEFAULT); multipleUpload.addMultipleUploadHandler(new MultipleUploadHandler() { @Override public void onUploadsSelected(List<FileInfo> fileInfos) { for(FileInfo file : fileInfos) { if(file != null) { files.put(file.getName(), file); if(!fileNames.contains(file.getName())) { fileNames.add(file.getName()); } } } handleNextFile(); } @Override public void onUploadStarted(FileInfo fileInfo) { return; } @SuppressWarnings("unchecked") @Override public void onUploadFinished(final FileInfo fileInfo, final File file) { final UploadSettings uploadSettings = settings.remove(fileInfo.getName()); final UserSession userSession = authenticationRegistry.getActiveUserSession(); Embedded embedded; synchronized(UploadSection.this) { embedded = ((List<Embedded>) uploadedEmbeddeds.get(fileInfo)).get(0); uploadedEmbeddeds.remove(fileInfo, embedded); if(embedded != null) { embedded.setSource(ResourceUtils.RUNO_ICON_32_OK_RESOURCE); requestRepaint(); } } new Thread(new Runnable() { @Override public void run() { if(uploadSettings != null && userSession != null) { PlatformMediaType platformMediaType = coreService.getPlatformMediaType(fileInfo.getType()); PlatformAttachmentCreationData platformAttachmentCreationData = ((PlatformAttachmentCreationData.Builder) new PlatformAttachmentCreationData.Builder().fileSize(fileInfo.getSize()).platformMediaType(platformMediaType).title(uploadSettings.getTitle()).description(uploadSettings.getDescription()).license(uploadSettings.getLicense()).contributors(uploadSettings.getContributors()).creators(uploadSettings.getCreators())).build(); UploadInfo uploadInfo = coreService.createDocument(userSession, platformAttachmentCreationData, uploadSettings.getTopographicPoint(), uploadSettings.getTimeRange()); UploadProcess uploadProcess = storageService.createUploadProcess(userSession, uploadInfo, file); UploadReport uploadReport = storageService.executeUploadProcess(uploadProcess); Embedded embedded; synchronized(UploadSection.this) { embedded = ((List<Embedded>) publishedEmbeddeds.get(fileInfo)).get(0); publishedEmbeddeds.remove(fileInfo, embedded); } if(uploadReport != null) { for(String tag : uploadSettings.getTags()) { Document document = coreService.getDocument((DocumentID) uploadReport.getAttachmentID().getRootID()); document.addTag(userSession, tag); } NumberFormat numberFormat = NumberFormat.getInstance(); numberFormat.setGroupingUsed(false); System.out.println("=================================="); System.out.println("vvvvvvvvvv UploadReport vvvvvvvvvv"); System.out.println("AttachmentID: " + uploadReport.getAttachmentID().getUniqueResourceURL().toExternalForm()); System.out.println("File URL: " + uploadReport.getFileURL().toExternalForm()); System.out.println("Media Type: " + uploadReport.getPlatformMediaType().getID()); System.out.println("File Size: " + uploadReport.getFileSize() + " Bytes"); System.out.println("Upload Time: " + numberFormat.format(uploadReport.getUploadTime()) + " ms"); System.out.println("Upload Rate: " + numberFormat.format(uploadReport.getUploadRate()) + " Bytes/s"); System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); System.out.println("=================================="); synchronized(UploadSection.this) { if(embedded != null) { embedded.setSource(ResourceUtils.RUNO_ICON_32_OK_RESOURCE); requestRepaint(); } } } else { System.err.println("UploadReport: null"); synchronized(UploadSection.this) { if(embedded != null) { embedded.setSource(ResourceUtils.RUNO_ICON_32_CANCEL_RESOURCE); requestRepaint(); } } } } if(file.exists()) { file.delete(); } } }).start(); } @SuppressWarnings("unchecked") @Override public void onUploadFailed(FileInfo fileInfo, Exception exception) { Embedded uploadedEmbedded; synchronized(UploadSection.this) { uploadedEmbedded = ((List<Embedded>) uploadedEmbeddeds.get(fileInfo)).get(0); uploadedEmbeddeds.remove(fileInfo, uploadedEmbedded); if(uploadedEmbedded != null) { uploadedEmbedded.setSource(ResourceUtils.RUNO_ICON_32_CANCEL_RESOURCE); requestRepaint(); } } Embedded publishedEmbedded; synchronized(UploadSection.this) { publishedEmbedded = ((List<Embedded>) publishedEmbeddeds.get(fileInfo)).get(0); publishedEmbeddeds.remove(fileInfo, publishedEmbedded); if(publishedEmbedded != null) { publishedEmbedded.setSource(ResourceUtils.RUNO_ICON_32_CANCEL_RESOURCE); requestRepaint(); } } settings.remove(fileInfo.getName()); } }); mainLayout.addComponent(multipleUpload); mainLayout.addComponent(StyleUtils.getHorizontalLine()); } /** * Returns a new polling {@link ProgressIndicator}. * * @return A new polling {@code ProgressIndicator} */ private ProgressIndicator getPollingProgressIndicator() { ProgressIndicator pollingProgressIndicator = new ProgressIndicator(); pollingProgressIndicator.addStyleName("outside-screen"); pollingProgressIndicator.setIndeterminate(true); pollingProgressIndicator.setImmediate(true); pollingProgressIndicator.setPollingInterval(POLLING_INTERVAL); return pollingProgressIndicator; } /** * Induces the necessary actions for handling the next file. */ private void handleNextFile() { if(files.size() > 0) { currentFile = files.remove(fileNames.get(0)); fileNames.remove(currentFile.getName()); PlatformMediaType platformMediaType = coreService.getPlatformMediaType(currentFile.getType()); if(platformMediaType != null && currentFile.getSize() > 0 && currentFile.getSize() <= platformMediaType.getMaxSize()) { UploadSettings uploadSettings = null; if(preSettings.containsKey(currentFile.getName())) { uploadSettings = preSettings.get(currentFile.getName()); } UploadSettingsWindow uploadSettingsWindow = new UploadSettingsWindow((MainWindow) getWindow(), this, currentFile, MediaTypeUtils.getMediaType(platformMediaType.getMediaMainType()), uploadSettings, fileNames); getWindow().addWindow(uploadSettingsWindow); } else { String message = null; if(currentFile.getType().equals("")) { message = "The file \"" + currentFile.getName() + "\" cannot be uploaded because files without a type are not supported by this platform."; } else if(currentFile.getSize() <= 0) { message = "The file \"" + currentFile.getName() + "\" cannot be uploaded because empty files are not supported by this platform."; } else if(platformMediaType != null && currentFile.getSize() > platformMediaType.getMaxSize()) { message = "The file \"" + currentFile.getName() + "\" cannot be uploaded because the maximum file size for the type \"" + platformMediaType.getID() + "\" is \"" + platformMediaType.getMaxSize() + " Bytes\"."; } else { message = "The file \"" + currentFile.getName() + "\" cannot be uploaded because the type \"" + currentFile.getType() + "\" is not supported by this platform."; } ConfirmWindow confirmWindow = new ConfirmWindow((MainWindow) getWindow(), "Upload Error", StyleUtils.getLabel(message)); confirmWindow.setWidth("400px"); confirmWindow.addListener(new CloseListener() { private static final long serialVersionUID = -5264116947530035902L; @Override public void windowClose(CloseEvent e) { cancelUpload(); } }); getWindow().addWindow(confirmWindow); } } else { finishCurrentUploadBatch(); } } /** * Uploads the currently processed file. * * @param uploadSettings The {@code UploadSettings} of the file * @param filesWithSameSettings A {@code List} with the names of the files * which should get the given {@code UploadSettings} as presetting */ public void upload(final UploadSettings uploadSettings, List<String> filesWithSameSettings) { final FileInfo fileInfo = currentFile; settings.put(fileInfo.getName(), uploadSettings); for(String fileName : filesWithSameSettings) { preSettings.put(fileName, uploadSettings); } new Thread(new Runnable() { @Override public void run() { ProgressIndicator progressIndicator = multipleUpload.upload(fileInfo); synchronized(application) { VerticalLayout uploadBoxLayout = new VerticalLayout(); mainLayout.addComponent(uploadBoxLayout); HorizontalLayout fileInfoLayout = new HorizontalLayout(); uploadBoxLayout.addComponent(fileInfoLayout); Label nameLabel = StyleUtils.getLabelBold(fileInfo.getName()); fileInfoLayout.addComponent(nameLabel); fileInfoLayout.addComponent(StyleUtils.getLabelSmallHTML("   ")); fileInfoLayout.setComponentAlignment(nameLabel, Alignment.MIDDLE_LEFT); BigDecimal fileSize = new BigDecimal((((double) fileInfo.getSize()) / 1000000.0d)); fileSize = fileSize.setScale(2, BigDecimal.ROUND_HALF_UP); Label typeSizeLabel = StyleUtils.getLabelSmallHTML(fileInfo.getType() + "  --  " + fileSize.toPlainString() + " MB"); fileInfoLayout.addComponent(typeSizeLabel); fileInfoLayout.setComponentAlignment(typeSizeLabel, Alignment.MIDDLE_LEFT); uploadBoxLayout.addComponent(StyleUtils.getVerticalSpace("100%", "8px")); uploadBoxLayout.addComponent(progressIndicator); uploadBoxLayout.addComponent(StyleUtils.getVerticalSpace("100%", "8px")); HorizontalLayout resultLayout = new HorizontalLayout(); uploadBoxLayout.addComponent(resultLayout); Label uploadedLabel = StyleUtils.getLabelSmallHTML("Uploaded: "); resultLayout.addComponent(uploadedLabel); resultLayout.setComponentAlignment(uploadedLabel, Alignment.MIDDLE_LEFT); Embedded uploadedEmbedded = new Embedded(null, ResourceUtils.RUNO_ICON_32_GLOBE_RESOURCE); uploadedEmbedded.addStyleName("image-opacity-65"); uploadedEmbedded.setType(Embedded.TYPE_IMAGE); uploadedEmbedded.setImmediate(true); uploadedEmbedded.setWidth("22px"); uploadedEmbedded.setHeight("22px"); resultLayout.addComponent(uploadedEmbedded); uploadedEmbeddeds.put(fileInfo, uploadedEmbedded); resultLayout.addComponent(StyleUtils.getLabelSmallHTML("   ")); Label publishedLabel = StyleUtils.getLabelSmallHTML("Published: "); resultLayout.addComponent(publishedLabel); resultLayout.setComponentAlignment(publishedLabel, Alignment.MIDDLE_LEFT); Embedded publishedEmbedded = new Embedded(null, ResourceUtils.RUNO_ICON_32_GLOBE_RESOURCE); publishedEmbedded.addStyleName("image-opacity-65"); publishedEmbedded.setType(Embedded.TYPE_IMAGE); publishedEmbedded.setImmediate(true); publishedEmbedded.setWidth("22px"); publishedEmbedded.setHeight("22px"); resultLayout.addComponent(publishedEmbedded); publishedEmbeddeds.put(fileInfo, publishedEmbedded); mainLayout.addComponent(StyleUtils.getVerticalSpace("100%", "5px")); requestRepaint(); } } }).start(); handleNextFile(); } /** * Cancels the currently processed upload. */ public void cancelUpload() { if(currentFile != null) { multipleUpload.cancelUpload(currentFile); } handleNextFile(); } /** * Cancels all uploads. */ public void cancelAllUploads() { if(currentFile != null) { multipleUpload.cancelUpload(currentFile); } if(files.size() > 0) { multipleUpload.cancelUploads(new Vector<FileInfo>(files.values())); } finishCurrentUploadBatch(); } /** * Finishes the current upload batch. */ private void finishCurrentUploadBatch() { files.clear(); fileNames.clear(); preSettings.clear(); currentFile = null; multipleUpload.finishCurrentUploadBatch(); } @Override public void update(Observable<UserSession> observable, UserSession userSession) { if(componentsAdded) { if(userSession == null) { multipleUpload.cancelAllUploads(); finishCurrentUploadBatch(); removeAllComponents(); } else { loadComponents(); } } } }