content: /*******************************************************************************
   * Copyright (C) 2021, 1C-Soft LLC and others.
   *
   * This program and the accompanying materials are made
   * available under the terms of the Eclipse Public License 2.0
   * which is available at https://www.eclipse.org/legal/epl-2.0/
   *
   * SPDX-License-Identifier: EPL-2.0
   *
   * Contributors:
   *     Aleksandr Kapralov - initial API and implementation
   *******************************************************************************/
  package com.e1c.v8codestyle.internal.right.itests;
  
  import static org.junit.Assert.assertNotNull;
  import static org.junit.Assert.assertNull;
  import static org.junit.Assert.assertTrue;
  
  import java.text.MessageFormat;
  import java.util.Collection;
  
  import org.eclipse.core.resources.IProject;
  import org.eclipse.core.runtime.IProgressMonitor;
  import org.eclipse.emf.common.util.ECollections;
  import org.eclipse.emf.ecore.EObject;
  import org.eclipse.xtext.resource.IEObjectDescription;
  
  import com._1c.g5.v8.bm.core.IBmObject;
  import com._1c.g5.v8.bm.core.IBmTransaction;
  import com._1c.g5.v8.bm.integration.AbstractBmTask;
  import com._1c.g5.v8.bm.integration.IBmModel;
  import com._1c.g5.v8.dt.core.platform.IDtProject;
  import com._1c.g5.v8.dt.md.refactoring.core.IMdRefactoringService;
  import com._1c.g5.v8.dt.metadata.mdclass.Role;
  import com._1c.g5.v8.dt.platform.IEObjectProvider;
  import com._1c.g5.v8.dt.platform.version.IRuntimeVersionSupport;
  import com._1c.g5.v8.dt.platform.version.Version;
  import com._1c.g5.v8.dt.refactoring.core.IRefactoring;
  import com._1c.g5.v8.dt.rights.model.ObjectRight;
  import com._1c.g5.v8.dt.rights.model.ObjectRights;
  import com._1c.g5.v8.dt.rights.model.Right;
  import com._1c.g5.v8.dt.rights.model.RightValue;
  import com._1c.g5.v8.dt.rights.model.RightsPackage;
  import com._1c.g5.v8.dt.rights.model.RoleDescription;
  import com._1c.g5.v8.dt.rights.model.util.RightName;
  import com._1c.g5.v8.dt.rights.model.util.RightsModelUtil;
  import com._1c.g5.v8.dt.testing.GuiceModules;
  import com._1c.g5.v8.dt.validation.marker.Marker;
  import com._1c.g5.wiring.ServiceAccess;
  import com.e1c.g5.v8.dt.testing.check.CheckTestBase;
  import com.google.inject.Inject;
  
  /**
   * Basic class for role tests
   *
   * @author Aleksandr Kapralov
   *
   */
  @GuiceModules(modules = { CheckExternalDependenciesModule.class })
  public abstract class CheckRights
      extends CheckTestBase
  {
  
      @Inject
      IMdRefactoringService refactoringService;
  
      protected void checkRoleCorrect(String checkId, String projectName, String workspaceRightsFqn, String mdObjectFqn,
          RightName rightName, String newRoleName) throws Exception
      {
          IDtProject dtProject = openProjectAndWaitForValidationFinish(projectName);
          assertNotNull(dtProject);
  
          ObjectRights objectRights = checkRole(dtProject, workspaceRightsFqn, mdObjectFqn, rightName, newRoleName);
  
          checkMarkerCorrect(objectRights, checkId, dtProject);
      }
  
      protected void checkRoleIncorrect(String checkId, String projectName, String workspaceRightsFqn, String mdObjectFqn,
          RightName rightName, String newRoleName) throws Exception
      {
          IDtProject dtProject = openProjectAndWaitForValidationFinish(projectName);
          assertNotNull(dtProject);
  
          ObjectRights objectRights = checkRole(dtProject, workspaceRightsFqn, mdObjectFqn, rightName, newRoleName);
  
          checkMarkerIncorrect(objectRights, checkId, dtProject);
      }
  
      private ObjectRights checkRole(IDtProject dtProject, String workspaceRightsFqn, String mdObjectFqn,
          RightName rightName, String newRoleName) throws Exception
      {
          updateRole(dtProject, workspaceRightsFqn, mdObjectFqn, rightName, newRoleName);
  
          String roleRightsFqn = workspaceRightsFqn;
          if (newRoleName != null)
          {
              roleRightsFqn = String.join(".", "Role", newRoleName, "Rights");
          }
          IBmObject top = getTopObjectByFqn(roleRightsFqn, dtProject);
          assertTrue(top instanceof RoleDescription);
  
          RoleDescription description = (RoleDescription)top;
          EObject mdObject = getTopObjectByFqn(mdObjectFqn, dtProject);
          return RightsModelUtil.getOrCreateObjectRights(mdObject, description);
      }
  
      private void checkMarkerCorrect(ObjectRights objectRights, String checkId, IDtProject dtProject)
      {
          for (ObjectRight objectRight : objectRights.getRights())
          {
              Marker marker = getFirstMarker(checkId, objectRight, dtProject);
              assertNull(marker);
          }
      }
  
      private void checkMarkerIncorrect(ObjectRights objectRights, String checkId, IDtProject dtProject)
      {
          for (ObjectRight objectRight : objectRights.getRights())
          {
              Marker marker = getFirstMarker(checkId, objectRight, dtProject);
              assertNotNull(marker);
          }
      }
  
      private void updateRole(IDtProject dtProject, String roleRightsFqn, String objectFqn, RightName rightName,
          String newRoleName) throws ClassCastException, NullPointerException
      {
          IBmModel model = bmModelManager.getModel(dtProject);
          Role role = model.execute(new AbstractBmTask<Role>("change type")
          {
              @Override
              public Role execute(IBmTransaction transaction, IProgressMonitor monitor)
              {
                  IBmObject object = transaction.getTopObjectByFqn(roleRightsFqn);
                  if (!(object instanceof RoleDescription))
                  {
                      throw new ClassCastException(
                          MessageFormat.format("Failed to get {0} by Fqn {1}", RoleDescription.class, roleRightsFqn));
                  }
  
                  RoleDescription description = (RoleDescription)object;
                  Role role = RightsModelUtil.getOwner(description, model);
                  if (role == null)
                  {
                      throw new NullPointerException(
                          MessageFormat.format("Failed to get {0} from {1}", Role.class, RoleDescription.class));
                  }
  
                  EObject mdObject = transaction.getTopObjectByFqn(objectFqn);
                  if (mdObject == null)
                  {
                      throw new NullPointerException(
                          MessageFormat.format("Failed to get {0} by Fqn {1}", EObject.class, objectFqn));
                  }
  
                  RightValue defaultRightValue = RightsModelUtil.getDefaultRightValue(mdObject, role);
  
                  ObjectRights objectRights = RightsModelUtil.getOrCreateObjectRights(mdObject, description);
  
                  for (ObjectRight objectRight : ECollections.newBasicEList(objectRights.getRights()))
                  {
                      RightsModelUtil.changeObjectRight(defaultRightValue, defaultRightValue, objectRights,
                          objectRight.getRight());
                  }
  
                  Right right = addRight(rightName, dtProject.getWorkspaceProject());
                  if (right == null)
                  {
                      throw new NullPointerException(
                          MessageFormat.format("Failed to get {0} by name {1}", Right.class, rightName));
                  }
  
                  RightsModelUtil.changeObjectRight(RightsModelUtil.getRightValue(true), defaultRightValue, objectRights,
                      right);
  
                  RightsModelUtil.removeEmptyObjectRights(description, objectRights);
  
                  return role;
              }
          });
  
          if (newRoleName != null)
          {
              Collection<IRefactoring> refactoring =
                  refactoringService.createMdObjectRenameRefactoring(role, newRoleName);
              IRefactoring renameRefactoring = refactoring.iterator().next();
              renameRefactoring.perform();
          }
  
          waitForDD(dtProject);
      }
  
      private Right addRight(RightName rightName, IProject project)
      {
          IRuntimeVersionSupport runtimeVersionSupport = ServiceAccess.get(IRuntimeVersionSupport.class);
          Version version = runtimeVersionSupport.getRuntimeVersion(project);
          IEObjectProvider rightsProvider = IEObjectProvider.Registry.INSTANCE.get(RightsPackage.Literals.RIGHT, version);
          Iterable<IEObjectDescription> descrs = rightsProvider.getEObjectDescriptions(input -> true);
          for (IEObjectDescription descr : descrs)
          {
              String name = descr.getName().toString();
              if (rightName.getName().equals(name))
              {
                  return (Right)descr.getEObjectOrProxy();
              }
          }
          return null;
      }
  
  }
  