KYLIN-216 update draft design
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/58a63073 Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/58a63073 Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/58a63073 Branch: refs/heads/master Commit: 58a63073620d16c4bc1aeb0a44db6caadccd3d17 Parents: 944d3aa Author: Luwei-Chen <chenlu...@apache.org> Authored: Fri Jun 2 21:10:45 2017 +0800 Committer: liyang-gmt8 <liy...@apache.org> Committed: Fri Jun 2 21:25:23 2017 +0800 ---------------------------------------------------------------------- .../org/apache/kylin/cube/CubeDescManager.java | 20 ++++++--- .../java/org/apache/kylin/cube/CubeManager.java | 4 +- .../kylin/metadata/project/ProjectManager.java | 36 ++++++++++----- .../kylin/rest/controller/CubeController.java | 3 -- .../rest/controller2/CubeControllerV2.java | 47 ++++++++++++-------- .../rest/controller2/ModelControllerV2.java | 46 ++++++++++--------- .../rest/response/CubeInstanceResponse.java | 18 -------- .../rest/response/DataModelDescResponse.java | 18 -------- .../apache/kylin/rest/service/CubeService.java | 21 +++++---- 9 files changed, 107 insertions(+), 106 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/58a63073/core-cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java ---------------------------------------------------------------------- diff --git a/core-cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java b/core-cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java index 85ca929..4c3c85d 100644 --- a/core-cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java +++ b/core-cube/src/main/java/org/apache/kylin/cube/CubeDescManager.java @@ -129,10 +129,11 @@ public class CubeDescManager { } @Override - public void onEntityChange(Broadcaster broadcaster, String entity, Event event, String cacheKey) throws IOException { + public void onEntityChange(Broadcaster broadcaster, String entity, Event event, String cacheKey) + throws IOException { String cubeDescName = cacheKey; CubeDesc cubeDesc = getCubeDesc(cubeDescName); - String modelName = cubeDesc == null ? null : cubeDesc.getModel().getName(); + String modelName = cubeDesc == null ? null : cubeDesc.getModelName(); if (event == Event.DROP) removeLocalCubeDesc(cubeDescName); @@ -265,7 +266,8 @@ public class CubeDescManager { int keyLength = 0; while (parameter != null) { String encoding = configuration.get(TopNMeasureType.CONFIG_ENCODING_PREFIX + parameter.getValue()); - String encodingVersionStr = configuration.get(TopNMeasureType.CONFIG_ENCODING_VERSION_PREFIX + parameter.getValue()); + String encodingVersionStr = configuration + .get(TopNMeasureType.CONFIG_ENCODING_VERSION_PREFIX + parameter.getValue()); if (StringUtils.isEmpty(encoding) || DictionaryDimEnc.ENCODING_NAME.equals(encoding)) { keyLength += DictionaryDimEnc.MAX_ENCODING_LENGTH; // estimation for dict encoding } else { @@ -279,7 +281,8 @@ public class CubeDescManager { } } Object[] encodingConf = DimensionEncoding.parseEncodingConf(encoding); - DimensionEncoding dimensionEncoding = DimensionEncodingFactory.create((String) encodingConf[0], (String[]) encodingConf[1], encodingVersion); + DimensionEncoding dimensionEncoding = DimensionEncodingFactory.create((String) encodingConf[0], + (String[]) encodingConf[1], encodingVersion); keyLength += dimensionEncoding.getLengthOfEncoding(); } @@ -309,16 +312,19 @@ public class CubeDescManager { private void reloadAllCubeDesc() throws IOException { ResourceStore store = getStore(); - logger.info("Reloading Cube Metadata from folder " + store.getReadableResourcePath(ResourceStore.CUBE_DESC_RESOURCE_ROOT)); + logger.info("Reloading Cube Metadata from folder " + + store.getReadableResourcePath(ResourceStore.CUBE_DESC_RESOURCE_ROOT)); cubeDescMap.clear(); - List<String> paths = store.collectResourceRecursively(ResourceStore.CUBE_DESC_RESOURCE_ROOT, MetadataConstants.FILE_SURFIX); + List<String> paths = store.collectResourceRecursively(ResourceStore.CUBE_DESC_RESOURCE_ROOT, + MetadataConstants.FILE_SURFIX); for (String path : paths) { CubeDesc desc = loadCubeDesc(path, true); if (!path.equals(desc.getResourcePath())) { - logger.error("Skip suspicious desc at " + path + ", " + desc + " should be at " + desc.getResourcePath()); + logger.error( + "Skip suspicious desc at " + path + ", " + desc + " should be at " + desc.getResourcePath()); continue; } if (cubeDescMap.containsKey(desc.getName())) { http://git-wip-us.apache.org/repos/asf/kylin/blob/58a63073/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java ---------------------------------------------------------------------- diff --git a/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java b/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java index e6cd761..8546f76 100644 --- a/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java +++ b/core-cube/src/main/java/org/apache/kylin/cube/CubeManager.java @@ -326,7 +326,9 @@ public class CubeManager implements IRealizationProvider { cube.setOwner(owner); updateCubeWithRetry(new CubeUpdate(cube), 0); - ProjectManager.getInstance(config).moveRealizationToProject(RealizationType.CUBE, cubeName, projectName, owner); + if (!desc.isDraft()) { + ProjectManager.getInstance(config).moveRealizationToProject(RealizationType.CUBE, cubeName, projectName, owner); + } if (listener != null) listener.afterCubeCreate(cube); http://git-wip-us.apache.org/repos/asf/kylin/blob/58a63073/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java ---------------------------------------------------------------------- diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java index a172db8..71d0e6c 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java @@ -28,6 +28,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.apache.commons.lang.StringUtils; import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.persistence.JsonSerializer; import org.apache.kylin.common.persistence.ResourceStore; @@ -52,7 +53,8 @@ import com.google.common.collect.Sets; public class ProjectManager { private static final Logger logger = LoggerFactory.getLogger(ProjectManager.class); private static final ConcurrentMap<KylinConfig, ProjectManager> CACHE = new ConcurrentHashMap<KylinConfig, ProjectManager>(); - public static final Serializer<ProjectInstance> PROJECT_SERIALIZER = new JsonSerializer<ProjectInstance>(ProjectInstance.class); + public static final Serializer<ProjectInstance> PROJECT_SERIALIZER = new JsonSerializer<ProjectInstance>( + ProjectInstance.class); public static ProjectManager getInstance(KylinConfig config) { ProjectManager r = CACHE.get(config); @@ -108,7 +110,8 @@ public class ProjectManager { } @Override - public void onEntityChange(Broadcaster broadcaster, String entity, Event event, String cacheKey) throws IOException { + public void onEntityChange(Broadcaster broadcaster, String entity, Event event, String cacheKey) + throws IOException { String project = cacheKey; if (event == Event.DROP) @@ -129,7 +132,8 @@ public class ProjectManager { ResourceStore store = getStore(); List<String> paths = store.collectResourceRecursively(ResourceStore.PROJECT_RESOURCE_ROOT, ".json"); - logger.debug("Loading Project from folder " + store.getReadableResourcePath(ResourceStore.PROJECT_RESOURCE_ROOT)); + logger.debug( + "Loading Project from folder " + store.getReadableResourcePath(ResourceStore.PROJECT_RESOURCE_ROOT)); for (String path : paths) { reloadProjectLocalAt(path); @@ -165,7 +169,8 @@ public class ProjectManager { return projectMap.get(projectName); } - public ProjectInstance createProject(String projectName, String owner, String description, LinkedHashMap<String, String> overrideProps) throws IOException { + public ProjectInstance createProject(String projectName, String owner, String description, + LinkedHashMap<String, String> overrideProps) throws IOException { logger.info("Creating project " + projectName); ProjectInstance currentProject = getProject(projectName); @@ -191,7 +196,8 @@ public class ProjectManager { } if (projectInstance.getRealizationCount(null) != 0) { - throw new IllegalStateException("The project named " + projectName + " can not be deleted because there's still realizations in it. Delete them first."); + throw new IllegalStateException("The project named " + projectName + + " can not be deleted because there's still realizations in it. Delete them first."); } logger.info("Dropping project '" + projectInstance.getName() + "'"); @@ -210,7 +216,8 @@ public class ProjectManager { } //update project itself - public ProjectInstance updateProject(ProjectInstance project, String newName, String newDesc, LinkedHashMap<String, String> overrideProps) throws IOException { + public ProjectInstance updateProject(ProjectInstance project, String newName, String newDesc, + LinkedHashMap<String, String> overrideProps) throws IOException { if (!project.getName().equals(newName)) { ProjectInstance newProject = this.createProject(newName, project.getOwner(), newDesc, overrideProps); @@ -286,16 +293,24 @@ public class ProjectManager { return newProject; } - public ProjectInstance moveRealizationToProject(RealizationType type, String realizationName, String newProjectName, String owner) throws IOException { + public ProjectInstance moveRealizationToProject(RealizationType type, String realizationName, String newProjectName, + String owner) throws IOException { removeRealizationsFromProjects(type, realizationName); return addRealizationToProject(type, realizationName, newProjectName, owner); } - private ProjectInstance addRealizationToProject(RealizationType type, String realizationName, String project, String user) throws IOException { + private ProjectInstance addRealizationToProject(RealizationType type, String realizationName, String project, + String user) throws IOException { String newProjectName = norm(project); + if (StringUtils.isEmpty(newProjectName)) { + throw new IllegalArgumentException("Project name should not be empty."); + } ProjectInstance newProject = getProject(newProjectName); if (newProject == null) { - newProject = this.createProject(newProjectName, user, "This is a project automatically added when adding realization " + realizationName + "(" + type + ")", null); + newProject = this.createProject(newProjectName, user, + "This is a project automatically added when adding realization " + realizationName + "(" + type + + ")", + null); } newProject.addRealizationEntry(type, realizationName); updateProject(newProject); @@ -436,7 +451,8 @@ public class ProjectManager { public boolean isExposedColumn(String project, String table, String col) { return config.isAdhocEnabled() ? // - l2Cache.isDefinedColumn(norm(project), table, col) || l2Cache.isExposedColumn(norm(project), table, col) : // + l2Cache.isDefinedColumn(norm(project), table, col) || l2Cache.isExposedColumn(norm(project), table, col) + : // l2Cache.isExposedColumn(norm(project), table, col); } http://git-wip-us.apache.org/repos/asf/kylin/blob/58a63073/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java index f932509..bfa5603 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java +++ b/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java @@ -299,9 +299,6 @@ public class CubeController extends BasicController { if (cube == null) { throw new InternalErrorException("Cannot find cube " + cubeName); } - if (cube.getStatus() != null && cube.getStatus().equals("DRAFT")) { - throw new BadRequestException("Cannot build draft cube"); - } return jobService.submitJob(cube, startTime, endTime, startOffset, endOffset, // sourcePartitionOffsetStart, sourcePartitionOffsetEnd, CubeBuildTypeEnum.valueOf(buildType), force, submitter); } catch (Throwable e) { http://git-wip-us.apache.org/repos/asf/kylin/blob/58a63073/server-base/src/main/java/org/apache/kylin/rest/controller2/CubeControllerV2.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller2/CubeControllerV2.java b/server-base/src/main/java/org/apache/kylin/rest/controller2/CubeControllerV2.java index 8179bc8..2edfe7d 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/controller2/CubeControllerV2.java +++ b/server-base/src/main/java/org/apache/kylin/rest/controller2/CubeControllerV2.java @@ -21,7 +21,6 @@ package org.apache.kylin.rest.controller2; import java.io.IOException; import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -51,7 +50,6 @@ import org.apache.kylin.rest.request.CubeRequest; import org.apache.kylin.rest.request.JobBuildRequest; import org.apache.kylin.rest.request.JobBuildRequest2; import org.apache.kylin.rest.response.CubeInstanceResponse; -import org.apache.kylin.rest.response.CubeInstanceResponse.CubeComparator; import org.apache.kylin.rest.response.EnvelopeResponse; import org.apache.kylin.rest.response.GeneralResponse; import org.apache.kylin.rest.response.HBaseResponse; @@ -117,20 +115,19 @@ public class CubeControllerV2 extends BasicController { List<CubeInstanceResponse> cubeInstanceResponses = new ArrayList<CubeInstanceResponse>(); List<CubeInstance> cubes = cubeService.listAllCubes(cubeName, projectName, modelName); - int offset = pageOffset * pageSize; - int limit = pageSize; - - if (cubes.size() <= offset) { - offset = cubes.size(); - limit = 0; - } + for (CubeInstance cube : cubes) { + CubeInstanceResponse cubeInstanceResponse = new CubeInstanceResponse(cube); - if ((cubes.size() - offset) < limit) { - limit = cubes.size() - offset; - } + if (cube.getDescriptor().isDraft()) { + String parentName = cube.getName().substring(0, cube.getName().lastIndexOf("_draft")); + CubeInstance official = cubeService.getCubeManager().getCube(parentName); + if (official == null) { + cubeInstanceResponse.setName(parentName); + } else { + continue; + } + } - for (CubeInstance cube : cubes.subList(offset, offset + limit)) { - CubeInstanceResponse cubeInstanceResponse = new CubeInstanceResponse(cube); cubeInstanceResponse.setPartitionDateStart(cube.getDescriptor().getPartitionDateStart()); String getModelName = modelName == null ? cube.getDescriptor().getModelName() : modelName; @@ -154,10 +151,22 @@ public class CubeControllerV2 extends BasicController { cubeInstanceResponses.add(cubeInstanceResponse); } - CubeComparator cubeComparator = new CubeComparator(); - Collections.sort(cubeInstanceResponses, cubeComparator); - data.put("cubes", cubeInstanceResponses); - data.put("size", cubes.size()); + + int offset = pageOffset * pageSize; + int limit = pageSize; + int size = cubeInstanceResponses.size(); + + if (size <= offset) { + offset = size; + limit = 0; + } + + if ((size - offset) < limit) { + limit = size - offset; + } + + data.put("cubes", cubeInstanceResponses.subList(offset, offset + limit)); + data.put("size", size); return new EnvelopeResponse(ResponseCode.CODE_SUCCESS, data, ""); } @@ -391,7 +400,7 @@ public class CubeControllerV2 extends BasicController { if (cube == null) { throw new BadRequestException(String.format(msg.getCUBE_NOT_FOUND(), cubeName)); } - if (cube.getStatus() != null && cube.getStatus().equals("DRAFT")) { + if (cube.getDescriptor().isDraft()) { throw new BadRequestException(msg.getBUILD_DRAFT_CUBE()); } return jobService.submitJob(cube, startTime, endTime, startOffset, endOffset, // http://git-wip-us.apache.org/repos/asf/kylin/blob/58a63073/server-base/src/main/java/org/apache/kylin/rest/controller2/ModelControllerV2.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller2/ModelControllerV2.java b/server-base/src/main/java/org/apache/kylin/rest/controller2/ModelControllerV2.java index 9e47790..57debf0 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/controller2/ModelControllerV2.java +++ b/server-base/src/main/java/org/apache/kylin/rest/controller2/ModelControllerV2.java @@ -20,7 +20,6 @@ package org.apache.kylin.rest.controller2; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -42,7 +41,6 @@ import org.apache.kylin.rest.msg.Message; import org.apache.kylin.rest.msg.MsgPicker; import org.apache.kylin.rest.request.ModelRequest; import org.apache.kylin.rest.response.DataModelDescResponse; -import org.apache.kylin.rest.response.DataModelDescResponse.ModelComparator; import org.apache.kylin.rest.response.EnvelopeResponse; import org.apache.kylin.rest.response.GeneralResponse; import org.apache.kylin.rest.response.ResponseCode; @@ -100,33 +98,39 @@ public class ModelControllerV2 extends BasicController { HashMap<String, Object> data = new HashMap<String, Object>(); List<DataModelDesc> models = modelService.listAllModels(modelName, projectName); - int offset = pageOffset * pageSize; - int limit = pageSize; - - if (models.size() <= offset) { - offset = models.size(); - limit = 0; - } - - if ((models.size() - offset) < limit) { - limit = models.size() - offset; - } - List<DataModelDescResponse> dataModelDescResponses = new ArrayList<DataModelDescResponse>(); - for (DataModelDesc model : modelService.getModels(modelName, projectName, limit, offset)) { + for (DataModelDesc model : models) { DataModelDescResponse dataModelDescResponse = new DataModelDescResponse(model); - + if (model.isDraft()) { + String parentName = model.getName().substring(0, model.getName().lastIndexOf("_draft")); + DataModelDesc official = modelService.getMetadataManager().getDataModelDesc(parentName); + if (official == null) { + dataModelDescResponse.setName(parentName); + } else { + continue; + } + } if (projectName != null) dataModelDescResponse.setProject(projectName); else dataModelDescResponse.setProject(projectService.getProjectOfModel(model.getName())); - dataModelDescResponses.add(dataModelDescResponse); } - ModelComparator modelComparator = new ModelComparator(); - Collections.sort(dataModelDescResponses, modelComparator); - data.put("models", dataModelDescResponses); - data.put("size", models.size()); + + int offset = pageOffset * pageSize; + int limit = pageSize; + int size = dataModelDescResponses.size(); + + if (size <= offset) { + offset = size; + limit = 0; + } + + if ((size - offset) < limit) { + limit = size - offset; + } + data.put("models", dataModelDescResponses.subList(offset, offset + limit)); + data.put("size", size); return new EnvelopeResponse(ResponseCode.CODE_SUCCESS, data, ""); } http://git-wip-us.apache.org/repos/asf/kylin/blob/58a63073/server-base/src/main/java/org/apache/kylin/rest/response/CubeInstanceResponse.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/response/CubeInstanceResponse.java b/server-base/src/main/java/org/apache/kylin/rest/response/CubeInstanceResponse.java index ab59165..f05de22 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/response/CubeInstanceResponse.java +++ b/server-base/src/main/java/org/apache/kylin/rest/response/CubeInstanceResponse.java @@ -18,8 +18,6 @@ package org.apache.kylin.rest.response; -import java.util.Comparator; - import org.apache.kylin.cube.CubeInstance; import com.fasterxml.jackson.annotation.JsonProperty; @@ -72,20 +70,4 @@ public class CubeInstanceResponse extends CubeInstance { setSegments(cubeInstance.getSegments()); setCreateTimeUTC(cubeInstance.getCreateTimeUTC()); } - - public static class CubeComparator implements Comparator<CubeInstanceResponse> { - @Override - public int compare(CubeInstanceResponse o1, CubeInstanceResponse o2) { - String name1 = o1.getName(), name2 = o2.getName(); - if (name1.endsWith("_draft")) { - name1 = name1.substring(0, name1.lastIndexOf("_draft")); - } - if (name2.endsWith("_draft")) { - name2 = name2.substring(0, name2.lastIndexOf("_draft")); - } - if (name1.equals(name2)) - return o1.getName().compareTo(o2.getName()); - return name1.compareTo(name2); - } - } } http://git-wip-us.apache.org/repos/asf/kylin/blob/58a63073/server-base/src/main/java/org/apache/kylin/rest/response/DataModelDescResponse.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/response/DataModelDescResponse.java b/server-base/src/main/java/org/apache/kylin/rest/response/DataModelDescResponse.java index 7ff30d3..59c9090 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/response/DataModelDescResponse.java +++ b/server-base/src/main/java/org/apache/kylin/rest/response/DataModelDescResponse.java @@ -18,8 +18,6 @@ package org.apache.kylin.rest.response; -import java.util.Comparator; - import org.apache.kylin.metadata.model.DataModelDesc; import org.apache.kylin.metadata.model.PartitionDesc; @@ -62,20 +60,4 @@ public class DataModelDescResponse extends DataModelDesc { setCapacity(dataModelDesc.getCapacity()); setComputedColumnDescs(dataModelDesc.getComputedColumnDescs()); } - - public static class ModelComparator implements Comparator<DataModelDescResponse> { - @Override - public int compare(DataModelDescResponse o1, DataModelDescResponse o2) { - String name1 = o1.getName(), name2 = o2.getName(); - if (name1.endsWith("_draft")) { - name1 = name1.substring(0, name1.lastIndexOf("_draft")); - } - if (name2.endsWith("_draft")) { - name2 = name2.substring(0, name2.lastIndexOf("_draft")); - } - if (name1.equals(name2)) - return o1.getName().compareTo(o2.getName()); - return name1.compareTo(name2); - } - } } http://git-wip-us.apache.org/repos/asf/kylin/blob/58a63073/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java ---------------------------------------------------------------------- diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java index 1eaa31c..3c0bbc6 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java +++ b/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java @@ -182,10 +182,13 @@ public class CubeService extends BasicService { } createdCube = getCubeManager().createCube(cubeName, projectName, createdDesc, owner); - accessService.init(createdCube, AclPermission.ADMINISTRATION); - ProjectInstance project = getProjectManager().getProject(projectName); - accessService.inherit(createdCube, project); + if (!desc.isDraft()) { + accessService.init(createdCube, AclPermission.ADMINISTRATION); + + ProjectInstance project = getProjectManager().getProject(projectName); + accessService.inherit(createdCube, project); + } return createdCube; } @@ -248,13 +251,13 @@ public class CubeService extends BasicService { if (!desc.isDraft()) { int cuboidCount = CuboidCLI.simulateCuboidGeneration(updatedCubeDesc, false); logger.info("Updated cube " + cube.getName() + " has " + cuboidCount + " cuboids"); - } - ProjectManager projectManager = getProjectManager(); - if (!isCubeInProject(newProjectName, cube)) { - String owner = SecurityContextHolder.getContext().getAuthentication().getName(); - ProjectInstance newProject = projectManager.moveRealizationToProject(RealizationType.CUBE, cube.getName(), newProjectName, owner); - accessService.inherit(cube, newProject); + ProjectManager projectManager = getProjectManager(); + if (!isCubeInProject(newProjectName, cube)) { + String owner = SecurityContextHolder.getContext().getAuthentication().getName(); + ProjectInstance newProject = projectManager.moveRealizationToProject(RealizationType.CUBE, cube.getName(), newProjectName, owner); + accessService.inherit(cube, newProject); + } } return updatedCubeDesc;