/****************************************************************************** * Copyright (c) 2016 Oracle * 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: * Konstantin Komissarchik - initial implementation ******************************************************************************/ package org.eclipse.sapphire.workspace.internal; import static org.eclipse.sapphire.workspace.CreateWorkspaceFileOp.PROBLEM_FILE_EXISTS; import java.util.List; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.sapphire.Event; import org.eclipse.sapphire.FileName; import org.eclipse.sapphire.FilteredListener; import org.eclipse.sapphire.InitialValueService; import org.eclipse.sapphire.Listener; import org.eclipse.sapphire.LocalizableText; import org.eclipse.sapphire.PropertyContentEvent; import org.eclipse.sapphire.ReferenceValue; import org.eclipse.sapphire.Text; import org.eclipse.sapphire.Value; import org.eclipse.sapphire.modeling.Path; import org.eclipse.sapphire.modeling.Status; import org.eclipse.sapphire.platform.PathBridge; import org.eclipse.sapphire.services.FileExtensionsService; import org.eclipse.sapphire.services.ReferenceService; import org.eclipse.sapphire.services.RelativePathService; import org.eclipse.sapphire.services.ValidationService; import org.eclipse.sapphire.util.ListFactory; import org.eclipse.sapphire.workspace.CreateWorkspaceFileOp; /** * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a> */ public final class CreateWorkspaceFileOpServices { @Text( "Folder must be specified" ) private static LocalizableText folderMustBeSpecified; @Text( "Project \"{0}\" does not exist or is not accessible" ) private static LocalizableText projectDoesNotExist; @Text( "File \"{0}\" already exists" ) private static LocalizableText fileExists; @Text( "File extension should be \"{0}\"" ) private static LocalizableText invalidFileExtensionOne; @Text( "File extension should be \"{0}\" or \"{1}\"" ) private static LocalizableText invalidFileExtensionTwo; @Text( "File extension should be one of \"{0}\"" ) private static LocalizableText invalidFileExtensionMultiple; static { LocalizableText.init( CreateWorkspaceFileOpServices.class ); } public CreateWorkspaceFileOpServices() {} public static final class RootReferenceService extends ReferenceService<IContainer> { @Override protected IContainer compute() { final String reference = context( Value.class ).text(); final IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace().getRoot(); if( reference == null ) { return wsroot; } else { final Path root = new Path( reference ); if( root.segmentCount() == 1 ) { return wsroot.getProject( root.segment( 0 ) ); } else { return wsroot.getFolder( PathBridge.create( root ) ); } } } } public static final class FolderReferenceService extends ReferenceService<IContainer> { @Override protected void initReferenceService() { context( CreateWorkspaceFileOp.class ).getRoot().service( ReferenceService.class ).attach ( new Listener() { @Override public void handle( final Event event ) { refresh(); } } ); } @Override protected IContainer compute() { final String reference = context( Value.class ).text(); final CreateWorkspaceFileOp op = context( CreateWorkspaceFileOp.class ); final IContainer root = op.getRoot().target(); if( reference == null ) { return root; } else { final IPath path = new org.eclipse.core.runtime.Path( reference ); if( root instanceof IWorkspaceRoot && path.segmentCount() == 1 ) { return ( (IWorkspaceRoot) root ).getProject( path.segment( 0 ) ); } else { return root.getFolder( path ); } } } } public static final class FolderRelativePathService extends RelativePathService { @Override public List<Path> roots() { final CreateWorkspaceFileOp op = context( CreateWorkspaceFileOp.class ); final IContainer root = op.getRoot().target(); if( root == null ) { return ListFactory.empty(); } else { return ListFactory.singleton( new Path( root.getLocation().toString() ) ); } } @Override public Path convertToRelative( final Path path ) { final CreateWorkspaceFileOp op = context( CreateWorkspaceFileOp.class ); final IContainer root = op.getRoot().target(); if( root instanceof IWorkspaceRoot ) { for( final IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects() ) { final Path location = new Path( project.getLocation().toPortableString() ); if( location.isPrefixOf( path ) ) { return new Path( project.getName() ).append( path.makeRelativeTo( location ) ); } } } else { super.convertToRelative( path ); } return null; } @Override public Path convertToAbsolute( final Path path ) { final CreateWorkspaceFileOp op = context( CreateWorkspaceFileOp.class ); final IContainer root = op.getRoot().target(); if( root instanceof IWorkspaceRoot ) { if( path.segmentCount() > 0 ) { final IProject project = ( (IWorkspaceRoot) root ).getProject( path.segment( 0 ) ); return new Path( project.getLocation().toString() ).append( path.removeFirstSegments( 1 ) ); } } else { super.convertToAbsolute( path ); } return null; } } public static final class FolderValidationService extends ValidationService { @Override protected void initValidationService() { context( Value.class ).service( ReferenceService.class ).attach ( new Listener() { @Override public void handle( final Event event ) { refresh(); } } ); } @Override protected Status compute() { final ReferenceValue<Path,IContainer> value = context( ReferenceValue.of( Path.class, IContainer.class ) ); final CreateWorkspaceFileOp op = value.nearest( CreateWorkspaceFileOp.class ); if( value.empty() && op.getRoot().empty() ) { return Status.createErrorStatus( folderMustBeSpecified.text() ); } final IContainer folder = context( ReferenceValue.of( Path.class, IContainer.class ) ).target(); if( folder != null ) { final IProject project = folder.getProject(); if( project != null && ! project.isAccessible() ) { final String msg = projectDoesNotExist.format( project.getName() ); return Status.createErrorStatus( msg ); } } return Status.createOkStatus(); } } public static final class FolderInitialValueService extends InitialValueService { @Override protected void initInitialValueService() { final Listener listener = new FilteredListener<PropertyContentEvent>() { @Override protected void handleTypedEvent( final PropertyContentEvent event ) { refresh(); } }; context( CreateWorkspaceFileOp.class ).getContext().attach( listener ); } @Override protected String compute() { final CreateWorkspaceFileOp op = context( CreateWorkspaceFileOp.class ); IResource resource = op.getContext().content(); if( resource instanceof IFile ) { resource = resource.getParent(); } return resource == null ? null : resource.getFullPath().makeRelative().toPortableString(); } } public static final class FileReferenceService extends ReferenceService<IFile> { @Override protected void initReferenceService() { context( CreateWorkspaceFileOp.class ).getFolder().service( ReferenceService.class ).attach ( new Listener() { @Override public void handle( final Event event ) { refresh(); } } ); } @Override protected IFile compute() { final String reference = context( Value.class ).text(); final CreateWorkspaceFileOp op = context( CreateWorkspaceFileOp.class ); final IContainer folder = op.getFolder().target(); if( reference == null || folder == null || folder instanceof IWorkspaceRoot ) { return null; } else { return folder.getFile( new org.eclipse.core.runtime.Path( reference ) ); } } } public static final class FileValidationService extends ValidationService { @Override protected void initValidationService() { final Value<?> value = context( Value.class ); final CreateWorkspaceFileOp op = value.nearest( CreateWorkspaceFileOp.class ); op.getOverwriteExistingFile().attach ( new FilteredListener<PropertyContentEvent>() { @Override protected void handleTypedEvent( final PropertyContentEvent event ) { refresh(); } } ); value.service( ReferenceService.class ).attach ( new Listener() { @Override public void handle( final Event event ) { refresh(); } } ); final FileExtensionsService fileExtensionsService = value.service( FileExtensionsService.class ); if( fileExtensionsService != null ) { fileExtensionsService.attach ( new Listener() { @Override public void handle( final Event event ) { refresh(); } } ); } } @Override protected Status compute() { final Value<?> value = context( Value.class ); final CreateWorkspaceFileOp op = value.nearest( CreateWorkspaceFileOp.class ); final FileName fileName = (FileName) value.content(); if( fileName != null ) { final String extension = fileName.extension(); if( extension != null ) { final FileExtensionsService fileExtensionsService = value.service( FileExtensionsService.class ); if( fileExtensionsService != null ) { final List<String> extensions = fileExtensionsService.extensions(); final int count = extensions.size(); if( count > 0 ) { boolean match = false; for( String ext : extensions ) { if( extension.equalsIgnoreCase( ext ) ) { match = true; break; } } if( ! match ) { final String message; if( count == 1 ) { message = invalidFileExtensionOne.format( extensions.get( 0 ) ); } else if( count == 2 ) { message = invalidFileExtensionTwo.format( extensions.get( 0 ), extensions.get( 1 ) ); } else { final StringBuilder buf = new StringBuilder(); for( String ext : extensions ) { if( buf.length() != 0 ) { buf.append( ", " ); } buf.append( ext ); } message = invalidFileExtensionMultiple.format( buf.toString() ); } return Status.createWarningStatus( message ); } } } } final IFile fileHandle = op.getFile().target(); if( fileHandle != null && fileHandle.exists() && op.getOverwriteExistingFile().content() == false ) { final String msg = fileExists.format( fileName ); return Status.factoryForLeaf().severity( Status.Severity.ERROR ).type( PROBLEM_FILE_EXISTS ).message( msg ).create(); } } return Status.createOkStatus(); } } }