/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.registry.datatype;
import org.eclipse.core.runtime.IConfigurationElement;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataKind;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.app.DBPRegistryDescriptor;
import org.jkiss.dbeaver.model.impl.AbstractDescriptor;
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
import org.jkiss.dbeaver.registry.DataSourceProviderDescriptor;
import org.jkiss.dbeaver.registry.RegistryConstants;
import java.lang.reflect.Field;
import java.util.*;
/**
* DataTypeAbstractDescriptor
*/
public abstract class DataTypeAbstractDescriptor<DESCRIPTOR> extends AbstractDescriptor implements DBPRegistryDescriptor<DESCRIPTOR>
{
private static final Log log = Log.getLog(ValueHandlerDescriptor.class);
public static final String ALL_TYPES_PATTERN = "*";
private final Class<DESCRIPTOR> instanceType;
private final String id;
private ObjectType implType;
private Set<Object> supportedTypes = new HashSet<>();
private List<String> supportedDataSources = new ArrayList<>();
private boolean hasAll, hasTypeIds, hasDataKinds, hasTypeNames;
protected DESCRIPTOR instance;
public DataTypeAbstractDescriptor(IConfigurationElement config, Class<DESCRIPTOR> instanceType)
{
super(config);
this.instanceType = instanceType;
this.id = config.getAttribute(RegistryConstants.ATTR_ID);
this.implType = new ObjectType(config.getAttribute(RegistryConstants.ATTR_CLASS));
IConfigurationElement[] typeElements = config.getChildren(RegistryConstants.TAG_TYPE);
for (IConfigurationElement typeElement : typeElements) {
String typeName = typeElement.getAttribute(RegistryConstants.ATTR_NAME);
if (typeName != null) {
if (typeName.equals(ALL_TYPES_PATTERN)) {
hasAll = true;
} else {
supportedTypes.add(typeName.toLowerCase(Locale.ENGLISH));
hasTypeNames = true;
}
} else {
typeName = typeElement.getAttribute("kind");
if (typeName != null) {
try {
supportedTypes.add(DBPDataKind.valueOf(typeName));
} catch (IllegalArgumentException e) {
log.warn(e);
}
hasDataKinds = true;
} else {
typeName = typeElement.getAttribute(RegistryConstants.ATTR_STANDARD);
if (typeName == null) {
typeName = typeElement.getAttribute(RegistryConstants.ATTR_ID);
if (typeName == null) {
log.warn("Type element without name or standard type reference"); //$NON-NLS-1$
continue;
}
try {
int typeNumber = Integer.parseInt(typeName);
supportedTypes.add(typeNumber);
hasTypeIds = true;
} catch (NumberFormatException e) {
log.warn("Type ID must be an integer while '" + typeName + "' was specified"); //$NON-NLS-1$
}
} else {
try {
Field typeField = java.sql.Types.class.getField(typeName);
int typeNumber = typeField.getInt(null);
supportedTypes.add(typeNumber);
hasTypeIds = true;
} catch (Exception e) {
log.warn("Standard type '" + typeName + "' cannot be accessed", e); //$NON-NLS-1$
}
}
}
}
}
IConfigurationElement[] dsElements = config.getChildren(RegistryConstants.TAG_DATASOURCE);
for (IConfigurationElement dsElement : dsElements) {
String dsId = dsElement.getAttribute(RegistryConstants.ATTR_ID);
String dsClassName = dsElement.getAttribute(RegistryConstants.ATTR_CLASS);
if (dsId == null && dsClassName == null) {
log.warn("Datasource reference with null ID/Class"); //$NON-NLS-1$
continue;
}
supportedDataSources.add(dsId != null ? dsId : dsClassName);
}
}
@Override
public String getId()
{
return id;
}
@Override
public DESCRIPTOR getInstance()
{
if (instance == null && implType != null) {
try {
this.instance = implType.createInstance(instanceType);
}
catch (Exception e) {
throw new IllegalStateException("Can't instantiate data type provider '" + this.id + "'", e); //$NON-NLS-1$
}
}
return instance;
}
public boolean supportsType(@NotNull DBSTypedObject typedObject) {
if (hasAll || (hasTypeIds && supportedTypes.contains(typedObject.getTypeID()))) {
return true;
}
if (hasTypeNames) {
String typeName = typedObject.getTypeName();
if (typeName != null && supportedTypes.contains(typeName.toLowerCase(Locale.ENGLISH))) {
return true;
}
}
return hasDataKinds && supportedTypes.contains(typedObject.getDataKind());
}
public Set<Object> getSupportedTypes()
{
return supportedTypes;
}
public boolean isGlobal()
{
return supportedDataSources.isEmpty();
}
public boolean supportsDataSource(DBPDataSource dataSource, DataSourceProviderDescriptor descriptor)
{
return supportedDataSources.contains(descriptor.getId()) || supportedDataSources.contains(dataSource.getClass().getName());
}
@Override
public String toString() {
return getId();
}
}