// ============================================================================
//
// Copyright (C) 2006-2012 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.core.repository;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.talend.commons.ui.runtime.exception.ExceptionHandler;
import org.talend.core.GlobalServiceRegister;
import org.talend.core.database.EDatabaseTypeName;
import org.talend.core.model.components.IComponent;
import org.talend.core.model.components.IComponentsService;
import org.talend.core.model.metadata.builder.connection.DatabaseConnection;
import org.talend.core.model.properties.DatabaseConnectionItem;
import org.talend.core.model.properties.Item;
import org.talend.core.model.repository.ERepositoryObjectType;
import org.talend.repository.model.RepositoryNode;
/**
* ggu class global comment. Detailled comment
*/
public final class RepositoryComponentManager {
private static final String EMPTY = ""; //$NON-NLS-1$
public static final String OUTPUT = "Output"; //$NON-NLS-1$
public static final String INPUT = "Input"; //$NON-NLS-1$
private static final List<RepositoryComponentSetting> repComponentSettings;
private static final List<RepositoryComponentDndFilterSetting> repComponentDndFilterSettings;
private static final List<SortedComponentSetting> sortedComponentSetting;
private static final List<SortedComponentSetting> specialSortedComponentSetting;
static {
repComponentSettings = new ArrayList<RepositoryComponentSetting>();
repComponentDndFilterSettings = new ArrayList<RepositoryComponentDndFilterSetting>();
sortedComponentSetting = new ArrayList<SortedComponentSetting>();
specialSortedComponentSetting = new ArrayList<SortedComponentSetting>();
init();
// sort by level
Collections.sort(repComponentDndFilterSettings, new Comparator<RepositoryComponentDndFilterSetting>() {
public int compare(RepositoryComponentDndFilterSetting o1, RepositoryComponentDndFilterSetting o2) {
return o1.getLevel() - o2.getLevel();
}
});
Collections.sort(sortedComponentSetting, new Comparator<SortedComponentSetting>() {
public int compare(SortedComponentSetting o1, SortedComponentSetting o2) {
return o1.getLevel() - o2.getLevel();
}
});
Collections.sort(specialSortedComponentSetting, new Comparator<SortedComponentSetting>() {
public int compare(SortedComponentSetting o1, SortedComponentSetting o2) {
return o1.getLevel() - o2.getLevel();
}
});
}
private static void init() {
IExtensionRegistry registry = Platform.getExtensionRegistry();
IConfigurationElement[] configurationElements = registry
.getConfigurationElementsFor("org.talend.core.runtime.repositoryComponent_provider"); //$NON-NLS-1$
List<String> repositoryComponentNames = new ArrayList<String>();
List<String> dndFilterIds = new ArrayList<String>();
List<String> componentIds = new ArrayList<String>();
for (int i = 0; i < configurationElements.length; i++) {
IConfigurationElement element = configurationElements[i];
if (element.getName().equals("ExtensionFilter")) { //$NON-NLS-1$
//
List<String> filterAttrs = getFilterAttrs(element, "RepositoryComponentFilter", //$NON-NLS-1$
"repositoryComponentName"); //$NON-NLS-1$
repositoryComponentNames.addAll(filterAttrs);
//
filterAttrs = getFilterAttrs(element, "DragAndDropFilterFilter", //$NON-NLS-1$
"dndFilterId"); //$NON-NLS-1$
dndFilterIds.addAll(filterAttrs);
//
filterAttrs = getFilterAttrs(element, "SortedComponentFilter", //$NON-NLS-1$
"componentId"); //$NON-NLS-1$
componentIds.addAll(filterAttrs);
}
}
for (int i = 0; i < configurationElements.length; i++) {
IConfigurationElement element = configurationElements[i];
if (element.getName().equals("RepositoryComponent")) { //$NON-NLS-1$
String name = element.getAttribute("name"); //$NON-NLS-1$
if (repositoryComponentNames.contains(name)) {
continue; // filter
}
String type = element.getAttribute("type"); //$NON-NLS-1$
boolean withSchema = Boolean.parseBoolean(element.getAttribute("withSchema")); //$NON-NLS-1$
String input = element.getAttribute("input"); //$NON-NLS-1$
String output = element.getAttribute("output"); //$NON-NLS-1$
String def = element.getAttribute("default"); //$NON-NLS-1$
IRepositoryComponentAgent agent = null;
if (element.getAttribute("agent") != null) { //$NON-NLS-1$
try {
Object object = element.createExecutableExtension("agent"); //$NON-NLS-1$
if (object != null && (object instanceof IRepositoryComponentAgent)) {
agent = (IRepositoryComponentAgent) object;
}
} catch (Exception e) {
//
}
}
RepositoryComponentSetting setting = new RepositoryComponentSetting();
setting.setName(name);
setting.setRepositoryType(type);
setting.setWithSchema(withSchema);
setting.setInputComponent(input);
setting.setOutputComponent(output);
setting.setDefaultComponent(def);
setting.setClasses(retrieveClasses(element));
setting.setDbTypes(retrieveDBTypes(element));
setting.setAgent(agent);
repComponentSettings.add(setting);
} else if (element.getName().equals("DragAndDropFilter")) { //$NON-NLS-1$
String id = element.getAttribute("id"); //$NON-NLS-1$
if (dndFilterIds.contains(id)) {
continue; // filter
}
String name = element.getAttribute("name"); //$NON-NLS-1$
int level = parserLevel(element.getAttribute("level")); //$NON-NLS-1$
IRepositoryComponentDndFilter filter = null;
try {
Object object = element.createExecutableExtension("clazz"); //$NON-NLS-1$
if (object == null || !(object instanceof IRepositoryComponentDndFilter)) {
throw new IllegalArgumentException("the argument of clazz is wrong");//$NON-NLS-1$
}
filter = (IRepositoryComponentDndFilter) object;
} catch (Exception e) {
ExceptionHandler.process(e);
}
RepositoryComponentDndFilterSetting dndSetting = new RepositoryComponentDndFilterSetting();
dndSetting.setId(id);
dndSetting.setName(name);
dndSetting.setLevel(level);
dndSetting.setFilter(filter);
repComponentDndFilterSettings.add(dndSetting);
} else if (element.getName().equals("SortedComponents")) { //$NON-NLS-1$
retrieveSortedComponent(componentIds, sortedComponentSetting, element, "Component"); //$NON-NLS-1$
retrieveSortedComponent(componentIds, specialSortedComponentSetting, element, "SpecialComponent"); //$NON-NLS-1$
}
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private static Class<Item>[] retrieveClasses(IConfigurationElement parent) {
IConfigurationElement[] children = parent.getChildren("Item"); //$NON-NLS-1$
List<Class<Item>> list = new ArrayList<Class<Item>>();
for (IConfigurationElement ce : children) {
String className = ce.getAttribute("clazz"); //$NON-NLS-1$
try {
Class clazz = Class.forName(className);
list.add(clazz);
} catch (ClassNotFoundException e) {
ExceptionHandler.process(e);
}
}
return list.toArray(new Class[0]);
}
private static EDatabaseTypeName[] retrieveDBTypes(IConfigurationElement parent) {
IConfigurationElement[] children = parent.getChildren("DBType"); //$NON-NLS-1$
List<EDatabaseTypeName> list = new ArrayList<EDatabaseTypeName>();
for (IConfigurationElement ce : children) {
String type = ce.getAttribute("type"); //$NON-NLS-1$
EDatabaseTypeName dbType = EDatabaseTypeName.getTypeFromDbType(type, false);
if (dbType == null) { // process some the types
for (EDatabaseTypeName dtn : EDatabaseTypeName.values()) {
if (dtn.name().equals(type)) {
dbType = dtn;
break;
}
}
}
if (dbType != null) {
list.add(dbType);
}
}
return list.toArray(new EDatabaseTypeName[0]);
}
private static void retrieveSortedComponent(List<String> componentIds, List<SortedComponentSetting> componentSetting,
IConfigurationElement parent, String extension) {
IConfigurationElement[] children = parent.getChildren(extension);
for (IConfigurationElement element : children) {
String id = element.getAttribute("id"); //$NON-NLS-1$
if (componentIds.contains(id)) {
continue; // filter
}
String name = element.getAttribute("name"); //$NON-NLS-1$
String pattern = element.getAttribute("pattern"); //$NON-NLS-1$
String description = element.getAttribute("description"); //$NON-NLS-1$
int level = parserLevel(element.getAttribute("level")); //$NON-NLS-1$
SortedComponentSetting setting = new SortedComponentSetting();
setting.setId(id);
setting.setName(name);
setting.setPattern(pattern);
setting.setLevel(level);
setting.setDescription(description);
componentSetting.add(setting);
}
}
private static int parserLevel(String levelStr, int... defaultValue) {
int level = 0;
if (defaultValue != null && defaultValue.length > 0) {
level = defaultValue[0];
}
if (levelStr != null && !EMPTY.equals(levelStr.trim())) {
try {
level = Integer.parseInt(levelStr);
} catch (NumberFormatException e) {
// keep zero by default
}
}
return level;
}
private static List<String> getFilterAttrs(IConfigurationElement parent, String extension, String attr) {
List<String> filterAttrValues = new ArrayList<String>();
IConfigurationElement[] children = parent.getChildren(extension);
for (IConfigurationElement ce : children) {
String filterAttr = ce.getAttribute(attr);
if (filterAttr != null && EMPTY.equals(filterAttr.trim())) {
filterAttrValues.add(filterAttr);
}
}
return filterAttrValues;
}
static RepositoryComponentSetting[] getSettings() {
return repComponentSettings.toArray(new RepositoryComponentSetting[0]);
}
static RepositoryComponentDndFilterSetting[] getDndFilterSettings() {
return repComponentDndFilterSettings.toArray(new RepositoryComponentDndFilterSetting[0]);
}
static SortedComponentSetting[] getSortedComponentSetting() {
return sortedComponentSetting.toArray(new SortedComponentSetting[0]);
}
static SortedComponentSetting[] getSpecialSortedComponentSetting() {
return specialSortedComponentSetting.toArray(new SortedComponentSetting[0]);
}
public static RepositoryComponentSetting getSetting(Item item, ERepositoryObjectType type) {
if (item == null) {
return null;
}
boolean subItem = (type == ERepositoryObjectType.METADATA_CON_TABLE);
for (RepositoryComponentSetting setting : getSettings()) {
Class<Item>[] classes = setting.getClasses();
if (classes != null) {
for (Class<Item> clazz : classes) {
if (clazz.isAssignableFrom(item.getClass())) {
if (clazz.isAssignableFrom(DatabaseConnectionItem.class)) { // for db
EDatabaseTypeName[] dbTypes = setting.getDbTypes();
if (dbTypes != null) {
for (EDatabaseTypeName dbType : dbTypes) {
DatabaseConnectionItem dbItem = (DatabaseConnectionItem) item;
DatabaseConnection dbConnection = (DatabaseConnection) dbItem.getConnection();
// use the display name as the database type
if (dbType.getDisplayName().equals(dbConnection.getDatabaseType())) {
if (!subItem) {
return setting;
}
if (subItem && setting.withSchema()) {
return setting;
}
}
}
}
} else {
return setting;
}
}
}
}
}
return null;
}
public static List<IComponent> filterNeededComponents(Item item, RepositoryNode seletetedNode, ERepositoryObjectType type) {
if (!GlobalServiceRegister.getDefault().isServiceRegistered(IComponentsService.class)) {
return Collections.emptyList();
}
IComponentsService service = (IComponentsService) GlobalServiceRegister.getDefault().getService(IComponentsService.class);
Set<IComponent> components = service.getComponentsFactory().getComponents();
List<IComponent> neededComponents = new ArrayList<IComponent>();
List<IComponent> exceptedComponents = new ArrayList<IComponent>();
for (IComponent component : components) {
//
for (RepositoryComponentDndFilterSetting dndFilter : getDndFilterSettings()) {
IRepositoryComponentDndFilter filter = dndFilter.getFilter();
if (filter == null) {
continue;
}
String repositoryType = filter.getRepositoryType(item, type);
if (repositoryType == null) {
continue;
}
if (!exceptedComponents.contains(component)
&& filter.except(item, type, seletetedNode, component, repositoryType)) {
exceptedComponents.add(component);
}
// if have been excepted, so no need add it to needed component
if (!exceptedComponents.contains(component) && !neededComponents.contains(component)
&& filter.valid(item, type, seletetedNode, component, repositoryType)) {
neededComponents.add(component);
}
}
}
// remove all excepted components
neededComponents.removeAll(exceptedComponents);
return sortFilteredComponnents(item, seletetedNode, type, neededComponents);
}
private static List<IComponent> sortFilteredComponnents(Item item, RepositoryNode seletetedNode, ERepositoryObjectType type,
List<IComponent> neededComponents) {
List<IComponent> normalTopComponents = new ArrayList<IComponent>();
List<IComponent> specialTopComponents = new ArrayList<IComponent>();
for (IComponent component : neededComponents) {
if (filterNeededComponent(getSpecialSortedComponentSetting(), component)) {
specialTopComponents.add(component);
} else if (filterNeededComponent(getSortedComponentSetting(), component)) {
normalTopComponents.add(component);
}
}
List<IComponent> sortedComponents = new ArrayList<IComponent>();
sortedComponents.addAll(specialTopComponents);
sortedComponents.addAll(normalTopComponents);
// add the left components
neededComponents.removeAll(specialTopComponents);
neededComponents.removeAll(normalTopComponents);
sortedComponents.addAll(neededComponents);
return sortedComponents;
}
private static boolean filterNeededComponent(SortedComponentSetting[] settings, IComponent component) {
if (settings != null && settings.length > 0 && component != null) {
Pattern p = null;
Matcher matcher = null;
for (SortedComponentSetting setting : settings) {
String pattern = setting.getPattern();
if (pattern != null && !EMPTY.equals(pattern)) {
p = Pattern.compile(pattern);
matcher = p.matcher(component.getName());
if (matcher.find()) {
return true;
}
}
}
}
return false;
}
public static boolean validComponent(String componentName) {
if (componentName != null) {
for (RepositoryComponentSetting setting : getSettings()) {
final String inputComponent = setting.getInputComponent();
final String outputComponent = setting.getOutputComponent();
final String defaultComponent = setting.getDefaultComponent();
if (componentName.equals(inputComponent) || componentName.equals(outputComponent)
|| componentName.equals(defaultComponent)) {
return true;
}
}
}
return false;
}
}