/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.vdb.ui.editor;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.designer.core.ModelEditorImpl;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.container.ContainerImpl;
import org.teiid.designer.core.workspace.ModelUtil;
import org.teiid.designer.metamodels.core.ModelAnnotation;
import org.teiid.designer.metamodels.relational.RelationalPackage;
import org.teiid.designer.metamodels.xml.XmlDocumentPackage;
import org.teiid.designer.roles.DataRole;
import org.teiid.designer.roles.Permission;
import org.teiid.designer.roles.ui.wizard.DataRoleResolver;
import org.teiid.designer.vdb.Vdb;
import org.teiid.designer.vdb.VdbEntry;
import org.teiid.designer.vdb.VdbModelEntry;
/**
* This class provides the VDB Editor a mechanism to clean-up/validate the data roles defined for the VDB based
* on any changes in VDB contents.
*
* Models removed from VDB, for instance, may require Permissions and/or Data Roles becoming obsolete.
*
* Models that have been synchronized from workspace may have changed to the point of making Permissions obsolete.
*
*
*
* @since 8.0
*/
public class VdbDataRoleResolver {
static final String WEB_SERVICES_VIEW_MODEL_URI = "http://www.metamatrix.com/metamodels/WebService"; //$NON-NLS-1$
private static final char DELIM = CoreStringUtil.Constants.DOT_CHAR;
private static final char B_SLASH = '/';
private static final String SYSADMIN = "sysadmin"; //$NON-NLS-1$
private Vdb vdb;
/**
*
* @param vdb
*/
public VdbDataRoleResolver(Vdb vdb) {
super();
this.vdb = vdb;
}
/**
* Assumed that the input list of VdbEntry's are being removed from the VDB.
*
* Makes a call to clean-up/remove any data role permissions associated with any of these removed models.
*
* @param entries
*/
public void modelEntriesRemoved( Set<VdbEntry> entries ) {
Set<String> modelNames = new HashSet<String>(entries.size());
for( VdbEntry entry : entries ) {
modelNames.add(entry.getName());
}
removePermissionsForModels(modelNames);
}
/*
* Remove any permissions who's target name begins with one of the provided model names
*/
private void removePermissionsForModels(Set<String> modelNames) {
Collection<DataRole> roles = vdb.getDataRoles();
Collection<DataRole> removeList = new ArrayList<DataRole>();
Collection<DataRole> addList = new ArrayList<DataRole>();
for( DataRole role : roles ) {
boolean changedPerms = false;
Collection<Permission> keepPermList = new ArrayList<Permission>();
Collection<Permission> permissions = role.getPermissions();
for( Permission perm : permissions ) {
boolean shouldRemovePermission = targetIsInStringList(modelNames, perm.getTargetName());
if( shouldRemovePermission ) {
changedPerms = true;
} else {
keepPermList.add(perm);
}
}
if( keepPermList.size() == 1 ) {
if( ((Permission)keepPermList.toArray()[0]).getTargetName().equals(SYSADMIN) ) {
keepPermList.clear();
}
}
if( changedPerms ) {
if( ! keepPermList.isEmpty() ) {
// Remove the old data policy
removeList.add(role);
// Create a data role
DataRole dr = new DataRole(role.getName());
dr.setDescription(role.getDescription());
if( !role.getRoleNames().isEmpty() ) {
dr.setRoleNames(role.getRoleNames());
}
dr.setPermissions(keepPermList);
dr.setAnyAuthenticated(role.isAnyAuthenticated());
addList.add(dr);
} else {
removeList.add(role);
}
}
}
for( DataRole role : removeList ) {
vdb.removeDataRole(role.getName());
}
for( DataRole role : addList ) {
vdb.addDataRole(role);
}
}
private boolean targetIsInStringList(Set<String> modelNames, String targetName) {
IPath targetModelPath = new Path(getTargetNamePath(targetName));
String targetModelName = targetModelPath.segment(0); // SHOULD BE MODEL NAME
for( String modelName : modelNames ) {
if( modelName.equalsIgnoreCase(targetModelName) ) {
return true;
}
}
return false;
}
private String getTargetNamePath(String dotPath) {
return dotPath.replace(DELIM, B_SLASH);
}
private DataRole getDataRole(DataRole DataRole) {
// Create a data role
DataRole dr = new DataRole(DataRole.getName());
dr.setDescription(DataRole.getDescription());
if( !DataRole.getRoleNames().isEmpty() ) {
dr.setRoleNames(DataRole.getRoleNames());
}
List<Permission> perms = new ArrayList<Permission>(DataRole.getPermissions());
dr.setPermissions(perms);
return dr;
}
/**
* Synchronize Model action in VdbEditor will replace a model in the VDB with the current same-name model in the workspace.
*
* This method will load this current model (after synchronization) into a temporary EMF container and remove any
* permission in any data role that has an unresolved target. This is accomplished by searching the container for
* an EObject with the corresponding "target name" or path.
* @param element the VdbEntry
*/
public void modelSynchronized(VdbEntry element) {
if( element instanceof VdbModelEntry ) {
ContainerImpl tempContainer = null;
VdbModelEntry entry = (VdbModelEntry)element;
try {
File modelFile = null;
for( File file : vdb.getModelFiles() ) {
String entryFileName = entry.getPathName();
if( file.getName().equals(entryFileName)) {
modelFile = file;
break;
}
}
if( modelFile != null ) {
tempContainer = (ContainerImpl)ModelerCore.createContainer("tempVdbModelContainer"); //$NON-NLS-1$
ModelEditorImpl.setContainer(tempContainer);
boolean isVisible = true;
Resource r = tempContainer.getResource(URI.createFileURI(modelFile.getPath()), true);
if (isVisible && ModelUtil.isModelFile(r) && !ModelUtil.isXsdFile(r)) {
EObject firstEObj = r.getContents().get(0);
ModelAnnotation ma = ModelerCore.getModelEditor().getModelAnnotation(firstEObj);
String mmURI = ma.getPrimaryMetamodelUri();
if (RelationalPackage.eNS_URI.equalsIgnoreCase(mmURI) ||
XmlDocumentPackage.eNS_URI.equalsIgnoreCase(mmURI) ||
WEB_SERVICES_VIEW_MODEL_URI.equalsIgnoreCase(mmURI)) {
// DO NOTHING. This leaves the resource in the temp container
} else {
tempContainer.getResources().remove(r);
}
} else {
tempContainer.getResources().remove(r);
}
}
} catch (CoreException e) {
e.printStackTrace();
} finally {
ModelEditorImpl.setContainer(null);
}
if( tempContainer != null ) {
DataRoleResolver resolver = new DataRoleResolver(tempContainer);
for( DataRole existingRole : vdb.getDataRoles() ) {
DataRole existingDataRole = getDataRole(existingRole);
DataRole changedDataRole = resolver.resolveDataRole(existingDataRole);
if( changedDataRole != null ) {
// Remove the old data policy
vdb.removeDataRole(existingRole.getName());
vdb.addDataRole(changedDataRole);
}
}
}
}
}
/**
* Synchronize All action in VdbEditor will replace any model in the VDB that has been changed in the user's
* workspace with that current same-name model.
*
* This method will load each vdb model (after synchronization) into a temporary EMF container and remove any
* permission in any data role that has an unresolved target. This is accomplished by searching the container for
* an EObject with the corresponding "target name" or path.
*/
public void allSynchronized() {
ContainerImpl tempContainer = null;
try {
Collection<File> modelFiles = vdb.getModelFiles();
tempContainer = (ContainerImpl)ModelerCore.createContainer("tempVdbModelContainer"); //$NON-NLS-1$
ModelEditorImpl.setContainer(tempContainer);
for (File modelFile : modelFiles) {
boolean isVisible = true;
Resource r = tempContainer.getResource(URI.createFileURI(modelFile.getPath()), true);
if (isVisible && ModelUtil.isModelFile(r) && !ModelUtil.isXsdFile(r)) {
EObject firstEObj = r.getContents().get(0);
ModelAnnotation ma = ModelerCore.getModelEditor().getModelAnnotation(firstEObj);
String mmURI = ma.getPrimaryMetamodelUri();
if (RelationalPackage.eNS_URI.equalsIgnoreCase(mmURI) ||
XmlDocumentPackage.eNS_URI.equalsIgnoreCase(mmURI) ||
WEB_SERVICES_VIEW_MODEL_URI.equalsIgnoreCase(mmURI)) {
// DO NOTHING. This leaves the resource in the temp container
} else {
tempContainer.getResources().remove(r);
}
} else {
tempContainer.getResources().remove(r);
}
}
} catch (CoreException e) {
e.printStackTrace();
} finally {
ModelEditorImpl.setContainer(null);
}
if( tempContainer != null ) {
DataRoleResolver resolver = new DataRoleResolver(tempContainer);
for( DataRole existingRole : vdb.getDataRoles() ) {
DataRole existingDataRole = getDataRole(existingRole);
DataRole changedDataRole = resolver.resolveDataRole(existingDataRole);
if( changedDataRole != null ) {
// Remove the old data policy
vdb.removeDataRole(existingRole.getName());
vdb.addDataRole(changedDataRole);
}
}
}
}
}