/*******************************************************************************
* Copyright (c) 2006-2012
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Berlin, Germany
* - initial API and implementation
******************************************************************************/
package org.reuseware.sokan.ui.model.sokanui.util;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
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.util.EcoreUtil;
import org.reuseware.sokan.Constraint;
import org.reuseware.sokan.FacetedRequest;
import org.reuseware.sokan.ID;
import org.reuseware.sokan.IndexRow;
import org.reuseware.sokan.index.emodeler.EModelerManager;
import org.reuseware.sokan.index.solr.SolrConst;
import org.reuseware.sokan.index.util.FacetUtil;
import org.reuseware.sokan.index.util.IndexUtil;
import org.reuseware.sokan.index.util.ResourceUtil;
import org.reuseware.sokan.index.util.SokanConst;
import org.reuseware.sokan.ui.model.sokanui.Artifact;
import org.reuseware.sokan.ui.model.sokanui.Container;
import org.reuseware.sokan.ui.model.sokanui.Package;
import org.reuseware.sokan.ui.model.sokanui.Root;
import org.reuseware.sokan.ui.model.sokanui.RootPackage;
import org.reuseware.sokan.ui.model.sokanui.SokanuiFactory;
public class SokanuiUtil {
public static final List<String> DEFAULT_CONTAINER =
Arrays.asList("(default package)");
public static void init(Root root) {
if (root == null) return;
if (root instanceof RootPackage) {
RootPackage rootPackage = (RootPackage) root;
rootPackage.getPackages().clear();
fillRootPackage(rootPackage, IndexUtil.INSTANCE.getIndex());
}
else {
// TODO #1449: implement folder structure
}
}
private static void fillRootPackage(RootPackage rootPackage, List<IndexRow> rows) {
if (rows == null || rows.isEmpty())
return;
for (IndexRow row : rows) {
List<String> packageID = toPackageID(rootPackage, row.getArtifactID());
if (packageID != null) {
getPackage(rootPackage, packageID);
}
}
}
private static List<String> toPackageID(RootPackage rootPackage, ID id) {
if (id == null) return null;
boolean isVisible = true;
if (!rootPackage.getVisibleTypes().isEmpty()) {
isVisible = false;
IndexRow row = IndexUtil.INSTANCE.getIndex(id);
if (row == null) {
//the element is removed and could have been in a package
//from which it will be removed
isVisible = true;
}
else {
for(EClass eClass : rootPackage.getVisibleTypes()) {
if (EModelerManager.canModel(eClass, row)) {
isVisible = true;
break;
}
}
}
}
if (isVisible) {
List<String> idSegments = id.getSegments();
if (idSegments.size() < 2)
return DEFAULT_CONTAINER;
return idSegments.subList(0, idSegments.size() - 1);
}
return null;
}
public static Package getPackage(RootPackage rootPackage, List<String> packageID) {
if (packageID == null) return null;
if (rootPackage == null) return null;
for(Package p : rootPackage.getPackages()) {
if(p.getId().equals(packageID)) {
return p;
}
}
Package p = SokanuiFactory.eINSTANCE.createPackage();
p.getId().addAll(packageID);
rootPackage.getPackages().add(p);
return p;
}
public static boolean deletePackage(RootPackage rootPackage, List<String> packageID) {
if (packageID == null) return false;
if (rootPackage == null) return false;
for(Package p : rootPackage.getPackages()) {
if(p.getId().equals(packageID)) {
rootPackage.getPackages().remove(p);
return true;
}
}
return false;
}
public static void fillContainer(Container container, ResourceSet resourceSet) {
if (container == null) return;
container.getElements().clear();
String packageName = ResourceUtil.idString(container.getId());
// TODO #1261: use of complex query
String queryString;
if (packageName.equals(ResourceUtil
.idString(DEFAULT_CONTAINER))) {
queryString = SokanConst.SEPERATOR + "* NOT "
+ SokanConst.SEPERATOR + "*" + SokanConst.SEPERATOR
+ "*";
} else {
queryString = packageName + SokanConst.SEPERATOR + "* NOT " + packageName
+ SokanConst.SEPERATOR + "*" + SokanConst.SEPERATOR
+ "*";
}
List<Constraint> constraints = FacetUtil.buildConstraints(
SolrConst.SYS_FIELD_ID, queryString);
FacetedRequest request = FacetUtil.buildFacetedRequest(constraints);
List<IndexRow> response = IndexUtil.INSTANCE.getIndex(request);
for (IndexRow row : response) {
updateArtifact(container, row.getArtifactID(), true, resourceSet);
}
}
private static void updateArtifact(Container container, ID id, boolean recreate, ResourceSet resourceSet) {
if (id == null) return;
// unload resources that might have been loaded on demand
URI uri = ResourceUtil.uriFrom(id);
if (uri != null) {
Resource resource = resourceSet.getResource(uri, false);
if (resource != null) {
resource.unload();
}
}
if (container == null) return;
if (!container.areElementsLoaded()) return;
//removes existing if any
Iterator<EObject> i = container.getElements().iterator();
while (i.hasNext()) {
EObject elem = i.next();
if (elem instanceof Artifact) {
Artifact art = (Artifact) elem;
if (art.getId().equals(id.getSegments())) {
if (art.areContentsLoaded()) {
for(EObject content : art.getContents()) {
Resource resource = content.eResource();
if (resource != null) {
resource.unload();
}
}
}
i.remove();
}
}
else if (EModelerManager.wasModelled(elem, id)) {
// EModeler is responsible for unloading if needed
i.remove();
}
}
if (!recreate) return;
Root root = (Root) EcoreUtil.getRootContainer(container);
IndexRow row = IndexUtil.INSTANCE.getIndex(id);
if (root.getVisibleTypes().isEmpty()) {
Artifact artifact = SokanuiFactory.eINSTANCE.createArtifact();
artifact.getId().addAll(id.getSegments());
artifact.setIndexRow(row);
artifact.setResourceSet(resourceSet);
container.getElements().add(artifact);
} else {
for (EClass visibleEClass : root.getVisibleTypes()) {
container.getElements().addAll(
EModelerManager.createModel(visibleEClass, row, resourceSet));
}
}
}
public static void update(Root root, Set<ID> delta) {
if (delta == null) return;
if (root == null) return;
if (root instanceof RootPackage) {
RootPackage rootPackage = (RootPackage) root;
for (ID id : delta) {
Container container = getPackage(
rootPackage, toPackageID(rootPackage, id));
IndexRow row = IndexUtil.INSTANCE.getIndex(id);
if (row == null) { //handle removed artifacts
updateArtifact(
container, id, false, root.getResourceSet());
// TODO #1449: performance here could be improved: getElements() will load an unloaded package - instead we could check the index
if (container != null && container.getElements().isEmpty()) {
rootPackage.getPackages().remove(container);
}
}
else {
updateArtifact(
container, id, true, root.getResourceSet());
}
}
}
else {
// TODO #1449: implement folder structure
}
}
}