Skip to content

Commit

Permalink
IJMP-1475: added all necessary reworks. Also bug IJMP-1325 is fixed.
Browse files Browse the repository at this point in the history
  • Loading branch information
VKrus committed Jan 17, 2024
1 parent 835aa28 commit 90b9ce1
Show file tree
Hide file tree
Showing 14 changed files with 359 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import eu.ibagroup.formainframe.dataops.fetch.FileFetchProvider
import eu.ibagroup.formainframe.dataops.log.LogFetcher
import eu.ibagroup.formainframe.dataops.log.MFLogger
import eu.ibagroup.formainframe.dataops.log.MFProcessInfo
import eu.ibagroup.formainframe.dataops.operations.mover.names.CopyPasteNameResolver

interface DataOpsManager : Disposable {

Expand Down Expand Up @@ -65,6 +66,8 @@ interface DataOpsManager : Disposable {

fun getMFContentAdapter(file: VirtualFile): MFContentAdapter

fun getNameResolver(source: VirtualFile, destination: VirtualFile): CopyPasteNameResolver

fun isOperationSupported(operation: Operation<*>): Boolean

@Throws(Throwable::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import eu.ibagroup.formainframe.dataops.log.LogFetcher
import eu.ibagroup.formainframe.dataops.log.MFLogger
import eu.ibagroup.formainframe.dataops.log.MFProcessInfo
import eu.ibagroup.formainframe.dataops.operations.OperationRunner
import eu.ibagroup.formainframe.dataops.operations.mover.names.CopyPasteNameResolver
import eu.ibagroup.formainframe.dataops.operations.mover.names.DefaultNameResolver
import eu.ibagroup.formainframe.utils.associateListedBy
import eu.ibagroup.formainframe.utils.findAnyNullable
import eu.ibagroup.formainframe.utils.log
Expand Down Expand Up @@ -137,6 +139,15 @@ class DataOpsManagerImpl : DataOpsManager {
}
private val mfContentAdapters by mfContentAdaptersDelegate

private val nameResolversDelegate = lazy {
CopyPasteNameResolver.EP.extensionList.buildComponents()
}
private val nameResolvers by nameResolversDelegate

override fun getNameResolver(source: VirtualFile, destination: VirtualFile): CopyPasteNameResolver {
return nameResolvers.firstOrNull { it.accepts(source, destination) } ?: DefaultNameResolver()
}

/**
* Checks if sync with mainframe is supported for provided object
* @param file object on mainframe that should be checked on availability of synchronization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,19 @@ abstract class RemoteAttributedContentSynchronizer<FAttributes : FileAttributes>
return fetchedAtLeastOnce.firstOrNull { syncProvider == it } != null
}

/**
* It is only necessary to remove old file from cache while force overwriting.
* TODO: Not the best solution. Think on how to rework.
* @param file - file to remove.
*/
fun removeFromCacheAfterForceOverwriting(file: VirtualFile) {
fetchedAtLeastOnce.removeIf { it.file == file }
// if you will not delete the file than "Local cache conflict" dialog appear.
runWriteActionInEdtAndWait {
file.delete(this@RemoteAttributedContentSynchronizer)
}
}

/**
* Base implementation of [ContentSynchronizer.synchronizeWithRemote] method for each synchronizer.
* Doesn't need to be overridden in most cases
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class UssFileToPdsMover(private val dataOpsManager: DataOpsManager) : AbstractFi
val from = sourceAttributes.path
val to = destinationAttributes.name
val api = api<DataAPI>(connectionConfig)
var memberName = sourceAttributes.name.filter { it.isLetterOrDigit() }.take(8)
var memberName = operation.newName ?: sourceAttributes.name.filter { it.isLetterOrDigit() }.take(8)
if (memberName.isEmpty()) {
memberName = "empty"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright IBA Group 2020
*/
package eu.ibagroup.formainframe.dataops.operations.mover.names

import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.vfs.VirtualFile
import eu.ibagroup.formainframe.dataops.DataOpsComponentFactory

interface CopyPasteNameResolverFactory: DataOpsComponentFactory<CopyPasteNameResolver>

/**
* Class to represent a name resolution for conflicting situation.
* @author Valiantsin Krus
*/
interface CopyPasteNameResolver {
companion object {
@JvmField
val EP = ExtensionPointName.create<CopyPasteNameResolverFactory>("eu.ibagroup.formainframe.nameResolver")
}

/**
* Determines whether this name resolver could resolve conflict for passed files or not.
* @param source source file to copy in destination folder (or folder-like entity).
* @param destination folder-like entity to copy file to.
* @return true if this name resolver could dot it or false otherwise.
*/
fun accepts(source: VirtualFile, destination: VirtualFile): Boolean

/**
* Finds child in destination folder that conflicts with source file.
* @param source source file to copy in destination folder (or folder-like entity).
* @param destination folder-like entity to copy file to.
* @return instance of conflicting child file or null if it was not found.
*/
fun getConflictingChild(source: VirtualFile, destination: VirtualFile): VirtualFile?

/**
* Creates new name for source file to make it possible to be copied in destination folder.
* @param source source file to copy in destination folder (or folder-like entity).
* @param destination folder-like entity to copy file to.
* @return string with new file name.
*/
fun resolve(source: VirtualFile, destination: VirtualFile): String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright IBA Group 2020
*/
package eu.ibagroup.formainframe.dataops.operations.mover.names

import com.intellij.openapi.vfs.VirtualFile
import eu.ibagroup.formainframe.dataops.DataOpsManager
import eu.ibagroup.formainframe.dataops.attributes.RemoteDatasetAttributes

class DatasetOrDirResolverFactory : CopyPasteNameResolverFactory {
override fun buildComponent(dataOpsManager: DataOpsManager): CopyPasteNameResolver {
return DatasetOrDirResolver(dataOpsManager)
}
}

/**
* Implementation of [CopyPasteNameResolver] for copying dataset or directory to uss or local system.
* @author Valiantsin Krus
*/
class DatasetOrDirResolver(val dataOpsManager: DataOpsManager): IndexedNameResolver() {
override fun accepts(source: VirtualFile, destination: VirtualFile): Boolean {
val sourceAttributes = dataOpsManager.tryToGetAttributes(source)
val destinationAttributes = dataOpsManager.tryToGetAttributes(destination)
return (source.isDirectory || sourceAttributes is RemoteDatasetAttributes) && destinationAttributes !is RemoteDatasetAttributes
}


override fun resolveNameWithIndex(source: VirtualFile, destination: VirtualFile, index: Int?): String {
return if (index == null) source.name else "${source.name}_(${index})"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright IBA Group 2020
*/
package eu.ibagroup.formainframe.dataops.operations.mover.names

import com.intellij.openapi.vfs.VirtualFile

/**
* Implementation of [IndexedNameResolver] that is used by default (if no one other name resolver was found)
* It just adds _(<index>) to the end of the file name before extension.
* @author Valiantsin Krus
*/
class DefaultNameResolver: IndexedNameResolver() {
override fun accepts(source: VirtualFile, destination: VirtualFile): Boolean {
return true
}

override fun resolveNameWithIndex(source: VirtualFile, destination: VirtualFile, index: Int?): String {
val sourceName = source.name
return if (index == null) {
sourceName
} else {
val extension = if (sourceName.contains(".")) sourceName.substringAfterLast(".") else null
val newNameWithoutExtension = "${sourceName.substringBeforeLast(".")}_(${index})"
if (extension != null) "$newNameWithoutExtension.$extension" else newNameWithoutExtension
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright IBA Group 2020
*/
package eu.ibagroup.formainframe.dataops.operations.mover.names

import com.intellij.openapi.vfs.VirtualFile

/**
* Name resolver that generates new name based on the index (e.g. file_(1), file_(2) and etc.)
* This is an abstract class, it only finds the necessary index but doesn't create a new name.
* It could be, for example file1, file2, file3. It all depends on implementation needs.
* @author Valiantsin Krus
*/
abstract class IndexedNameResolver: CopyPasteNameResolver {

override fun getConflictingChild(source: VirtualFile, destination: VirtualFile): VirtualFile? {
val rowNameToCopy = resolveNameWithIndex(source, destination, null)
return destination.children.firstOrNull { it.name == rowNameToCopy }
}

/**
* Creates new name for a source file based on passed index.
* @param source source file to copy in destination folder (or folder-like entity).
* @param destination folder-like entity to copy file to.
* @param index generated index to add to the source name. If it is null, then no index is needed to add.
* @return new name with joined index.
*/
abstract fun resolveNameWithIndex(source: VirtualFile, destination: VirtualFile, index: Int?): String

override fun resolve(source: VirtualFile, destination: VirtualFile): String {
var newName = resolveNameWithIndex(source, destination, null)
var index = 1
while (destination.children.any { it.name == newName }) {
newName = resolveNameWithIndex(source, destination, index++)
}
return newName
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright IBA Group 2020
*/
package eu.ibagroup.formainframe.dataops.operations.mover.names

import com.intellij.openapi.vfs.VirtualFile
import eu.ibagroup.formainframe.dataops.DataOpsManager
import eu.ibagroup.formainframe.dataops.attributes.RemoteDatasetAttributes

class NotSeqToPDSResolverFactory : CopyPasteNameResolverFactory {
override fun buildComponent(dataOpsManager: DataOpsManager): CopyPasteNameResolver {
return NotSeqToPDSResolver(dataOpsManager)
}
}

/**
* Implementation of [CopyPasteNameResolver] for copying anything except of Sequential Dataset to PDS.
* @author Valiantsin Krus
*/
class NotSeqToPDSResolver(val dataOpsManager: DataOpsManager) : IndexedNameResolver() {
override fun accepts(source: VirtualFile, destination: VirtualFile): Boolean {
val sourceAttributes = dataOpsManager.tryToGetAttributes(source)
val destinationAttributes = dataOpsManager.tryToGetAttributes(destination)
return destinationAttributes is RemoteDatasetAttributes &&
sourceAttributes !is RemoteDatasetAttributes
}

override fun resolveNameWithIndex(source: VirtualFile, destination: VirtualFile, index: Int?): String {
val memberName = source.name.filter { it.isLetterOrDigit() }.uppercase().ifEmpty { "EMPTY" }
return if (index == null) memberName.take(8) else "${memberName.take(7)}$index"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright IBA Group 2020
*/
package eu.ibagroup.formainframe.dataops.operations.mover.names

import com.intellij.openapi.vfs.VirtualFile
import eu.ibagroup.formainframe.dataops.DataOpsManager
import eu.ibagroup.formainframe.dataops.attributes.RemoteDatasetAttributes

class SeqToPDSResolverFactory : CopyPasteNameResolverFactory {
override fun buildComponent(dataOpsManager: DataOpsManager): CopyPasteNameResolver {
return SeqToPDSResolver(dataOpsManager)
}
}

/**
* Implementation of [CopyPasteNameResolver] for copying Sequential Dataset to PDS.
* @author Valiantsin Krus
*/
class SeqToPDSResolver(val dataOpsManager: DataOpsManager) : IndexedNameResolver() {
override fun accepts(source: VirtualFile, destination: VirtualFile): Boolean {
val sourceAttributes = dataOpsManager.tryToGetAttributes(source)
val destinationAttributes = dataOpsManager.tryToGetAttributes(destination)
return sourceAttributes is RemoteDatasetAttributes &&
!source.isDirectory &&
destinationAttributes is RemoteDatasetAttributes
}

override fun resolveNameWithIndex(source: VirtualFile, destination: VirtualFile, index: Int?): String {
val lastQualifier = source.name.split(".").last()
return if (index == null) lastQualifier else "${lastQualifier.take(7)}${index}"
}
}

0 comments on commit 90b9ce1

Please sign in to comment.