Skip to content

Commit

Permalink
[WIP] Display semantic data in the workbench
Browse files Browse the repository at this point in the history
Signed-off-by: Stéphane Bégaudeau <[email protected]>
  • Loading branch information
sbegaudeau committed Oct 16, 2023
1 parent 43a0d3b commit 60357ab
Show file tree
Hide file tree
Showing 15 changed files with 520 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2023 Stéphane Bégaudeau.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package com.svalyn.studio.application.controllers.business;

import com.svalyn.studio.application.controllers.business.dto.ObjectDTO;
import com.svalyn.studio.application.controllers.history.dto.ChangeDTO;
import com.svalyn.studio.application.services.business.api.IObjectService;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.stereotype.Controller;

import java.util.List;
import java.util.Objects;

/**
* Controller used to manipulate objects.
*
* @author sbegaudeau
*/
@Controller
public class ObjectController {

private final IObjectService objectService;

public ObjectController(IObjectService objectService) {
this.objectService = Objects.requireNonNull(objectService);
}

@SchemaMapping(typeName = "Change")
public List<ObjectDTO> objects(ChangeDTO change) {
return this.objectService.findAllByChangeId(change.id());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2023 Stéphane Bégaudeau.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package com.svalyn.studio.application.controllers.business.dto;

public record ObjectDTO(String id, String label) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2023 Stéphane Bégaudeau.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package com.svalyn.studio.application.services.business;

import com.svalyn.studio.application.controllers.business.dto.ObjectDTO;
import com.svalyn.studio.application.services.business.api.IObjectService;
import com.svalyn.studio.domain.business.services.api.IObjectDataProvider;
import com.svalyn.studio.domain.business.services.api.IObjectProvider;
import com.svalyn.studio.domain.history.Change;
import com.svalyn.studio.domain.history.ChangeResource;
import com.svalyn.studio.domain.history.repositories.IChangeRepository;
import com.svalyn.studio.domain.resource.Resource;
import com.svalyn.studio.domain.resource.repositories.IResourceRepository;
import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
* Used to manipulate objects.
*
* @author sbegaudeau
*/
@Service
public class ObjectService implements IObjectService {

private final IChangeRepository changeRepository;

private final IResourceRepository resourceRepository;

private final IObjectProvider objectProvider;

private final IObjectDataProvider objectDataProvider;

public ObjectService(IChangeRepository changeRepository, IResourceRepository resourceRepository, IObjectProvider objectProvider, IObjectDataProvider objectDataProvider) {
this.changeRepository = Objects.requireNonNull(changeRepository);
this.resourceRepository = Objects.requireNonNull(resourceRepository);
this.objectProvider = Objects.requireNonNull(objectProvider);
this.objectDataProvider = Objects.requireNonNull(objectDataProvider);
}

@Override
@Transactional(readOnly = true)
public List<ObjectDTO> findAllByChangeId(UUID changeId) {
return this.changeRepository.findById(changeId)
.map(this::toResource)
.map(this::toObjects)
.orElse(List.of());
}

private List<Resource> toResource(Change change) {
var resourceIds = change.getChangeResources().stream()
.map(ChangeResource::getResource)
.map(AggregateReference::getId)
.toList();
return this.resourceRepository.findAllById(resourceIds);
}

private List<ObjectDTO> toObjects(List<Resource> resources) {
return this.objectProvider.toObjects(resources).stream().map(object -> {
var id = this.objectDataProvider.id(object);
var label = this.objectDataProvider.label(object);
return new ObjectDTO(id, label);
}).toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 Stéphane Bégaudeau.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package com.svalyn.studio.application.services.business.api;

import com.svalyn.studio.application.controllers.business.dto.ObjectDTO;

import java.util.List;
import java.util.UUID;

/**
* Used to manipulate objects.
*
* @author sbegaudeau
*/
public interface IObjectService {
List<ObjectDTO> findAllByChangeId(UUID changeId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ type Change {
name: String!
resources: ChangeResourcesConnection!
resource(path: String!, name: String!): ChangeResource
objects: [Object!]!
createdOn: Instant!
createdBy: Profile!
lastModifiedOn: Instant!
Expand All @@ -344,6 +345,11 @@ enum ContentType {
TEXT_PLAIN
}

type Object {
id: ID!
label: String!
}

type ChangeResource {
contentType: ContentType!
content: String!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2023 Stéphane Bégaudeau.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package com.svalyn.studio.domain.business.services;

import com.svalyn.studio.domain.business.services.api.IObjectDataProvider;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
* Used to retrieve some details of a given object.
*
* @author sbegaudeau
*/
@Service
public class ObjectDataProvider implements IObjectDataProvider {
@Override
public String id(Object object) {
return Optional.of(object)
.filter(EObject.class::isInstance)
.map(EObject.class::cast)
.map(eObject -> {
var id = EcoreUtil.getID(eObject);
if (id != null) {
return id;
}
return EcoreUtil.getURI(eObject).toString();
})
.orElse("unknown id");
}

@Override
public String label(Object object) {
return Optional.of(object)
.filter(EObject.class::isInstance)
.map(EObject.class::cast)
.map(eObject -> {
var adapterFactories = eObject.eResource().getResourceSet().getAdapterFactories();
var adapterFactory = new ComposedAdapterFactory(adapterFactories);
var adapter = adapterFactory.adapt(eObject, IItemLabelProvider.class);
if (adapter instanceof IItemLabelProvider labelProvider) {
return labelProvider.getText(eObject);
}
return eObject.eClass().getName() + " unknown";
}).orElse("unknown");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2023 Stéphane Bégaudeau.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package com.svalyn.studio.domain.business.services;

import com.svalyn.studio.domain.business.services.api.IObjectProvider;
import com.svalyn.studio.domain.resource.Resource;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.provider.EcoreItemProviderAdapterFactory;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.StreamSupport;

/**
* Used to retrieve objects.
*
* @author sbegaudeau
*/
@Service
public class ObjectProvider implements IObjectProvider {

private final Logger logger = LoggerFactory.getLogger(ObjectProvider.class);

@Override
public List<Object> toObjects(List<Resource> resources) {
var resourceSet = new ResourceSetImpl();

resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new EcoreResourceFactoryImpl());
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("genmodel", new EcoreResourceFactoryImpl());

resourceSet.getAdapterFactories().add(new EcoreItemProviderAdapterFactory());

resources.forEach(resource -> {
var originalUri = URI.createURI(resource.getPath() + resource.getName());
var convertedUri = URI.createURI("svalyn://resource/" + resource.getPath() + resource.getName());
resourceSet.getURIConverter().getURIMap().put(originalUri, convertedUri);
});

var options = new HashMap<String, Object>();

for (var resource: resources) {
var uri = URI.createURI("svalyn://resource/" + resource.getPath() + resource.getName());
var resourceFactory = resourceSet.getResourceFactoryRegistry().getFactory(uri);
if (resourceFactory != null) {
var domainResource = resourceFactory.createResource(uri);
resourceSet.getResources().add(domainResource);
try {
domainResource.load(new ByteArrayInputStream(resource.getContent()), options);
} catch (IOException exception) {
this.logger.warn(exception.getMessage(), exception);
}
}
}

var spliterator = Spliterators.spliteratorUnknownSize(resourceSet.getAllContents(), Spliterator.ORDERED);
return StreamSupport.stream(spliterator, false)
.filter(EObject.class::isInstance)
.map(EObject.class::cast)
.filter(eObject -> !eObject.eIsProxy() && !(eObject instanceof AnyType))
.map(Object.class::cast)
.toList();
}
}
Loading

0 comments on commit 60357ab

Please sign in to comment.