<commit_before>/*******************************************************************************
 * Copyright (c) 2010-11 Bolton University, UK.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the License
 * which accompanies this distribution in the file LICENSE.txt
 *******************************************************************************/
package uk.ac.bolton.archimate.editor.diagram.policies;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.jface.viewers.IStructuredSelection;

import uk.ac.bolton.archimate.editor.diagram.commands.AddDiagramArchimateConnectionCommand;
import uk.ac.bolton.archimate.editor.diagram.commands.AddDiagramModelReferenceCommand;
import uk.ac.bolton.archimate.editor.diagram.commands.AddDiagramObjectCommand;
import uk.ac.bolton.archimate.editor.diagram.commands.DiagramCommandFactory;
import uk.ac.bolton.archimate.editor.diagram.dnd.AbstractDNDEditPolicy;
import uk.ac.bolton.archimate.editor.diagram.dnd.ArchimateDiagramTransferDropTargetListener;
import uk.ac.bolton.archimate.editor.diagram.dnd.DiagramDropRequest;
import uk.ac.bolton.archimate.editor.model.DiagramModelUtils;
import uk.ac.bolton.archimate.editor.model.commands.NonNotifyingCompoundCommand;
import uk.ac.bolton.archimate.editor.preferences.ConnectionPreferences;
import uk.ac.bolton.archimate.model.IArchimateElement;
import uk.ac.bolton.archimate.model.IArchimateFactory;
import uk.ac.bolton.archimate.model.IArchimateModel;
import uk.ac.bolton.archimate.model.IArchimateModelElement;
import uk.ac.bolton.archimate.model.IDiagramModel;
import uk.ac.bolton.archimate.model.IDiagramModelArchimateObject;
import uk.ac.bolton.archimate.model.IRelationship;
import uk.ac.bolton.archimate.model.util.ArchimateModelUtils;


/**
 * A policy to handle an Archimate Diagram's and Diagram's Container object's Native DND commands
 * Create a Command for dropping and dragging elements from Tree to diagram/container
 * 
 * @author <NAME>
 */
public class ArchimateDNDEditPolicy extends AbstractDNDEditPolicy {

    protected List<IArchimateElement> fElementsToAdd;
    protected List<IRelationship> fRelationsToAdd;
    protected List<IDiagramModel> fDiagramRefsToAdd;
    
    @Override
    protected Command getDropCommand(DiagramDropRequest request) {
        if(!(request.getData() instanceof IStructuredSelection)) {
            return null;
        }
        
        // XY drop point
        Point pt = getDropLocation(request);

        int origin = pt.x;
        int x = pt.x;
        int y = pt.y;

        fElementsToAdd = new ArrayList<IArchimateElement>();
        fRelationsToAdd = new ArrayList<IRelationship>();
        fDiagramRefsToAdd = new ArrayList<IDiagramModel>();
        
        // Gather an actual list of elements dragged onto the container, omitting duplicates and anything already on the diagram
        Object[] objects = ((IStructuredSelection)request.getData()).toArray();
        getElementsToAdd(objects);
        
        // Store the Diagram Model Components that will be added
        List<IDiagramModelArchimateObject> diagramObjects = new ArrayList<IDiagramModelArchimateObject>();

        // Compound Command - it has to be Non-Notifying or it's way too slow (tested with Bill's UoB model!)
        CompoundCommand result = new NonNotifyingCompoundCommand("Add Elements");

        // Add the Commands adding the Elements first
        for(IArchimateElement element : fElementsToAdd) {
            // Add Diagram object
            IDiagramModelArchimateObject object = IArchimateFactory.eINSTANCE.createDiagramModelArchimateObject();
            object.setArchimateElement(element);
            object.setBounds(x, y, -1, -1);
            
            // Store it
            diagramObjects.add(object);
            
            // Add Command
            result.add(new AddDiagramObjectCommand(getTargetContainer(), object));

            // Increase x,y
            x += 150;
            if(x > origin + 400) {
                x = origin;
                y += 100;
            }
        }

        // Then any Diagram Model Ref Commands
        for(IDiagramModel diagramModel : fDiagramRefsToAdd) {
            result.add(new AddDiagramModelReferenceCommand(getTargetContainer(), diagramModel, x, y));
            
            x += 150;
            if(x > origin + 400) {
                x = origin;
                y += 100;
            }
        }

        // Add selected Relations to create connections for those elements on the diagram that don't already have them
        for(IRelationship relation : fRelationsToAdd) {
            // Existing
            List<IDiagramModelArchimateObject> sources = DiagramModelUtils.findDiagramModelObjectsForElement(getTargetDiagramModel(), relation.getSource());
            List<IDiagramModelArchimateObject> targets = DiagramModelUtils.findDiagramModelObjectsForElement(getTargetDiagramModel(), relation.getTarget());

            for(IDiagramModelArchimateObject dcSource : sources) {
                for(IDiagramModelArchimateObject dcTarget : targets) {
                    if(dcTarget != dcSource && !DiagramModelUtils.hasDiagramModelArchimateConnection(dcSource, dcTarget, relation)) {
                        result.add(new AddDiagramArchimateConnectionCommand(dcSource, dcTarget, relation));
                    }
                }
            }
        }
        
        // Whether to add connections to elements
        Boolean addConnectionsToElements = (Boolean)request.getExtendedData().get(ArchimateDiagramTransferDropTargetListener.ADD_ELEMENT_CONNECTIONS);
        
        // Newly added objects will need new connections to existing elements and newly added elements
        for(IDiagramModelArchimateObject dmo : diagramObjects) {
            IArchimateElement element = dmo.getArchimateElement();

            for(IRelationship relation : ArchimateModelUtils.getRelationships(element)) {
                /*
                 * If the user holds down the Copy key (Ctrl on win/lnx, Alt on Mac) then linked connections
                 * are not added on drag and drop. However, any selected relations' linked objects are added.
                 */
                if(!addConnectionsToElements && !fRelationsToAdd.contains(relation)) {
                    continue;
                }

                // Find existing objects
                List<IDiagramModelArchimateObject> sources = DiagramModelUtils.findDiagramModelObjectsForElement(getTargetDiagramModel(), relation.getSource());
                List<IDiagramModelArchimateObject> targets = DiagramModelUtils.findDiagramModelObjectsForElement(getTargetDiagramModel(), relation.getTarget());

                // Add new ones too
                for(IDiagramModelArchimateObject dmo2 : diagramObjects) {
                    if(dmo != dmo2) {<commit_msg>Check for null value<commit_after>/*******************************************************************************
 * Copyright (c) 2010-11 Bolton University, UK.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the License
 * which accompanies this distribution in the file LICENSE.txt
 *******************************************************************************/
package uk.ac.bolton.archimate.editor.diagram.policies;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.jface.viewers.IStructuredSelection;

import uk.ac.bolton.archimate.editor.diagram.commands.AddDiagramArchimateConnectionCommand;
import uk.ac.bolton.archimate.editor.diagram.commands.AddDiagramModelReferenceCommand;
import uk.ac.bolton.archimate.editor.diagram.commands.AddDiagramObjectCommand;
import uk.ac.bolton.archimate.editor.diagram.commands.DiagramCommandFactory;
import uk.ac.bolton.archimate.editor.diagram.dnd.AbstractDNDEditPolicy;
import uk.ac.bolton.archimate.editor.diagram.dnd.ArchimateDiagramTransferDropTargetListener;
import uk.ac.bolton.archimate.editor.diagram.dnd.DiagramDropRequest;
import uk.ac.bolton.archimate.editor.model.DiagramModelUtils;
import uk.ac.bolton.archimate.editor.model.commands.NonNotifyingCompoundCommand;
import uk.ac.bolton.archimate.editor.preferences.ConnectionPreferences;
import uk.ac.bolton.archimate.model.IArchimateElement;
import uk.ac.bolton.archimate.model.IArchimateFactory;
import uk.ac.bolton.archimate.model.IArchimateModel;
import uk.ac.bolton.archimate.model.IArchimateModelElement;
import uk.ac.bolton.archimate.model.IDiagramModel;
import uk.ac.bolton.archimate.model.IDiagramModelArchimateObject;
import uk.ac.bolton.archimate.model.IRelationship;
import uk.ac.bolton.archimate.model.util.ArchimateModelUtils;


/**
 * A policy to handle an Archimate Diagram's and Diagram's Container object's Native DND commands
 * Create a Command for dropping and dragging elements from Tree to diagram/container
 * 
 * @author <NAME>
 */
public class ArchimateDNDEditPolicy extends AbstractDNDEditPolicy {

    protected List<IArchimateElement> fElementsToAdd;
    protected List<IRelationship> fRelationsToAdd;
    protected List<IDiagramModel> fDiagramRefsToAdd;
    
    @Override
    protected Command getDropCommand(DiagramDropRequest request) {
        if(!(request.getData() instanceof IStructuredSelection)) {
            return null;
        }
        
        // XY drop point
        Point pt = getDropLocation(request);

        int origin = pt.x;
        int x = pt.x;
        int y = pt.y;

        fElementsToAdd = new ArrayList<IArchimateElement>();
        fRelationsToAdd = new ArrayList<IRelationship>();
        fDiagramRefsToAdd = new ArrayList<IDiagramModel>();
        
        // Gather an actual list of elements dragged onto the container, omitting duplicates and anything already on the diagram
        Object[] objects = ((IStructuredSelection)request.getData()).toArray();
        getElementsToAdd(objects);
        
        // Store the Diagram Model Components that will be added
        List<IDiagramModelArchimateObject> diagramObjects = new ArrayList<IDiagramModelArchimateObject>();

        // Compound Command - it has to be Non-Notifying or it's way too slow (tested with Bill's UoB model!)
        CompoundCommand result = new NonNotifyingCompoundCommand("Add Elements");

        // Add the Commands adding the Elements first
        for(IArchimateElement element : fElementsToAdd) {
            // Add Diagram object
            IDiagramModelArchimateObject object = IArchimateFactory.eINSTANCE.createDiagramModelArchimateObject();
            object.setArchimateElement(element);
            object.setBounds(x, y, -1, -1);
            
            // Store it
            diagramObjects.add(object);
            
            // Add Command
            result.add(new AddDiagramObjectCommand(getTargetContainer(), object));

            // Increase x,y
            x += 150;
            if(x > origin + 400) {
                x = origin;
                y += 100;
            }
        }

        // Then any Diagram Model Ref Commands
        for(IDiagramModel diagramModel : fDiagramRefsToAdd) {
            result.add(new AddDiagramModelReferenceCommand(getTargetContainer(), diagramModel, x, y));
            
            x += 150;
            if(x > origin + 400) {
                x = origin;
                y += 100;
            }
        }

        // Add selected Relations to create connections for those elements on the diagram that don't already have them
        for(IRelationship relation : fRelationsToAdd) {
            // Existing
            List<IDiagramModelArchimateObject> sources = DiagramModelUtils.findDiagramModelObjectsForElement(getTargetDiagramModel(), relation.getSource());
            List<IDiagramModelArchimateObject> targets = DiagramModelUtils.findDiagramModelObjectsForElement(getTargetDiagramModel(), relation.getTarget());

            for(IDiagramModelArchimateObject dcSource : sources) {
                for(IDiagramModelArchimateObject dcTarget : targets) {
                    if(dcTarget != dcSource && !DiagramModelUtils.hasDiagramModelArchimateConnection(dcSource, dcTarget, relation)) {
                        result.add(new AddDiagramArchimateConnectionCommand(dcSource, dcTarget, relation));
                    }
                }
            }
        }
        
        // Whether to add connections to elements
        Boolean value = (Boolean)request.getExtendedData().get(ArchimateDiagramTransferDropTargetListener.ADD_ELEMENT_CONNECTIONS);
        boolean addConnectionsToElements = value != null && value.booleanValue();
        
        // Newly added objects will need new connections to existing elements and newly added elements
        for(IDiagramModelArchimateObject dmo : diagramObjects) {
            IArchimateElement element = dmo.getArchimateElement();

            for(IRelationship relation : ArchimateModelUtils.getRelationships(element)) {
                /*
                 * If the user holds down the Copy key (Ctrl on win/lnx, Alt on Mac) then linked connections
                 * are not added on drag and drop. However, any selected relations' linked objects are added.
                 */
                if(!addConnectionsToElements && !fRelationsToAdd.contains(relation)) {
                    continue;
                }

                // Find existing objects
                List<IDiagramModelArchimateObject> sources = DiagramModelUtils.findDiagramModelObjectsForElement(getTargetDiagramModel(), relation.getSource());
                List<IDiagramModelArchimateObject> targets = DiagramModelUtils.findDiagramModelObjectsForElement(getTargetDiagramModel(), relation.getTarget());

                // Add new ones too
                for(IDiagramModelArchimateObject dmo2 : diagramObjects) {
                    if(dmo != dmo2) {
{'fraction_non_alphanumeric': 0.10121657943131984, 'fraction_numerical': 0.004102419012590183, 'mean_word_length': 2.9839391377852915, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 33, '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': '265483', 'n_tokens_mistral': 3750, 'n_tokens_neox': 3587, 'n_words': 828}