<commit_before>package tools.vitruv.framework.vsum.views

import java.util.Collection
import java.util.function.Consumer
import org.eclipse.emf.common.notify.Notification
import org.eclipse.emf.common.notify.Notifier
import org.eclipse.emf.common.notify.impl.AdapterImpl
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl
import org.eclipse.emf.ecore.util.EcoreUtil
import tools.vitruv.framework.change.recording.ChangeRecorder
import tools.vitruv.framework.vsum.VirtualModel

/**
 *
 * A basic view that passes by default the entirety of its underlying model as it is.
 * IMPORTANT: This is a prototypical implementation for concept exploration and therefore subject to change.
 */
class BasicModelView implements View, AutoCloseable {
    protected ResourceSet viewResourceSet
    val Collection<Resource> modelResources
    protected boolean modelChanged
    val ChangeRecorder changeRecorder
    val VirtualModel virtualModel

    new(Collection<Resource> modelResources, VirtualModel virtualModel) {
        this.modelResources = modelResources
        this.virtualModel = virtualModel
        modelResources.registerModelChangeListener
        update
        changeRecorder = new ChangeRecorder(viewResourceSet)
    }

    override rootObjects() {
        viewResourceSet.resources.map[contents].flatten.toList
    }

    override isModified() { // TODO TS: Alternatively this could be done via a model change listener, what is better?
        return viewResourceSet.resources.stream.anyMatch[isModified]
    }

    override hasVSUMChanged() {
        return modelChanged
    }

    override update() { // TODO TS: should this be delegated to the viewtype, so a view has no access on model resources?
        modelChanged = false
        viewResourceSet = new ResourceSetImpl()
        for (resource : modelResources) {
            val uri = resource.URI
            val newResource = viewResourceSet.resourceFactoryRegistry.getFactory(uri).createResource(uri)
            newResource.contents.addAll(EcoreUtil.copyAll(resource.contents.filter))
            viewResourceSet.resources += newResource
        }
    }

    override <T extends Notifier> commitChanges(T notifier, Consumer<T> consumer) {
        /*
         * TODO TS: It seems there is two ways how to control recording:
         * 1. Always record but add or remove notifiers from the recorder to control when to record
         * 2. Only start/stop recording when actually required
         * What is the correct way here?
         */
        changeRecorder.addToRecording(notifier)
        changeRecorder.beginRecording

        val toSave = determineResource(notifier)
        consumer.accept(notifier)
        (toSave ?: determineResource(notifier))?.saveOrDelete()

        changeRecorder.endRecording
        changeRecorder.removeFromRecording(notifier)

        val propagatedChanges = virtualModel.propagateChange(changeRecorder.change)<commit_msg>Fix resource creation issue that persists in the CI build.<commit_after>package tools.vitruv.framework.vsum.views

import java.util.Collection
import java.util.function.Consumer
import org.eclipse.emf.common.notify.Notification
import org.eclipse.emf.common.notify.Notifier
import org.eclipse.emf.common.notify.impl.AdapterImpl
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl
import org.eclipse.emf.ecore.util.EcoreUtil
import tools.vitruv.framework.change.recording.ChangeRecorder
import tools.vitruv.framework.vsum.VirtualModel

import static com.google.common.base.Preconditions.checkNotNull

import static extension edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceSetUtil.withGlobalFactories

/**
 *
 * A basic view that passes by default the entirety of its underlying model as it is.
 * IMPORTANT: This is a prototypical implementation for concept exploration and therefore subject to change.
 */
class BasicModelView implements View, AutoCloseable {
    protected ResourceSet viewResourceSet
    val Collection<Resource> modelResources
    protected boolean modelChanged
    val ChangeRecorder changeRecorder
    val VirtualModel virtualModel

    new(Collection<Resource> modelResources, VirtualModel virtualModel) {
        this.modelResources = modelResources
        this.virtualModel = virtualModel
        modelResources.registerModelChangeListener
        update
        changeRecorder = new ChangeRecorder(viewResourceSet)
    }

    override rootObjects() {
        viewResourceSet.resources.map[contents].flatten.toList
    }

    override isModified() { // TODO TS: Alternatively this could be done via a model change listener, what is better?
        return viewResourceSet.resources.stream.anyMatch[isModified]
    }

    override hasVSUMChanged() {
        return modelChanged
    }

    override update() { // TODO TS: should this be delegated to the viewtype, so a view has no access on model resources?
        modelChanged = false
        viewResourceSet = checkNotNull(new ResourceSetImpl().withGlobalFactories, "Could not create view resource set!")
        for (resource : modelResources) {
            val uri = resource.URI
            val newResource = viewResourceSet.resourceFactoryRegistry.getFactory(uri).createResource(uri)
            newResource.contents.addAll(EcoreUtil.copyAll(resource.contents.filter))
            viewResourceSet.resources += newResource
        }
    }

    override <T extends Notifier> commitChanges(T notifier, Consumer<T> consumer) {
        /*
         * TODO TS: It seems there is two ways how to control recording:
         * 1. Always record but add or remove notifiers from the recorder to control when to record
         * 2. Only start/stop recording when actually required
         * What is the correct way here?
         */
        changeRecorder.addToRecording(notifier)
        changeRecorder.beginRecording

        val toSave = determineResource(notifier)
        consumer.accept(notifier)
        (toSave ?: determineResource(notifier))?.saveOrDelete()

        changeRecorder.endRecording
        changeRecorder.removeFromRecording(notifier)

        val propagatedChanges = virtualModel.propagateChange(changeRecorder.change)
{'fraction_non_alphanumeric': 0.06940993788819876, 'fraction_numerical': 0.0006211180124223603, 'mean_word_length': 3.5105042016806722, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1122172', 'n_tokens_mistral': 1682, 'n_tokens_neox': 1628, 'n_words': 449}