All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.unibz.inf.ontop.dbschema.QuotedIDFactory Maven / Gradle / Ivy

package it.unibz.inf.ontop.dbschema;

/*
 * #%L
 * ontop-obdalib-core
 * %%
 * Copyright (C) 2009 - 2014 Free University of Bozen-Bolzano
 * %%
 * 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.
 * #L%
 */

import com.google.common.collect.ImmutableMap;
import org.eclipse.jdt.annotation.NonNullByDefault;

import javax.annotation.Nullable;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * Factory for creating attribute and relation identifier from strings.
 * 

* Instances of this class define the rules of transforming unquoted and quoted identifiers, and different * {@code QuotedIDFactory} sub-classes can be defined to address different DBMS backends. *

* Each {@code QuotedIDFactory} implementation class should be associated to a factory type identifier obtainable * via {@link #getIDFactoryType()} and generally deriving from a {@link IDFactoryType} class annotation. This identifier * is a human-readable string that uniquely identifies the factory type (e.g., {@code POSTGRESQL}) in data written by * Ontop (e.g., the DB metadata saved to file) so to allow reading back that data using the proper * {@code QuotedIDFactory} implementation. *

* When implementing {@code QuotedIDFactory}, add a {@link IDFactoryType} annotation to specify the factory type * identifier, and then add a binding for the implementation class in the {@code OntopAbstractModule} sub-class of the * enclosing Ontop project (see the implementation of {@code OntopModelModule} for an example of how * {@code SQLStandardQuotedIDFactory} is bound). *

* * @author Roman Kontchakov (original implementation) */ @NonNullByDefault public interface QuotedIDFactory { /** * Creates a new attribute ID from a string. * * @param attributeId possibly quoted attribute ID (SQL rendering) * @return attribute ID */ QuotedID createAttributeID(String attributeId); /** * Creates a new relation ID from the supplied name. * * @param tableId the name * @return relation ID */ RelationID createRelationID(String tableId); /** * Creates a new relation ID from the component strings. * * @param components list of the possibly quoted components of relation ID, * from the catalog to the table name * @return relation ID */ RelationID createRelationID(@Nullable String... components); /** * Returns the quotation string used in the SQL rendering. * * @return the quotation string */ String getIDQuotationString(); /** * Returns whether notation {@code [identifier]} for schema/table/attribute identifiers is supported. * * @return true if square bracked notation is supported */ @SuppressWarnings("BooleanMethodIsAlwaysInverted") boolean supportsSquareBracketQuotation(); /** * Returns an identifier (such as "POSTGRESQL") useful to denote the type of factory when writing/reading database * metadata. The default implementation retrieves the identifier from a {@link IDFactoryType} annotation placed on * the java class this object is instance of. Consider adding a {@code IDFactoryType} in derived classes or, for * wrappers, overriding and delegating this method to the wrapped {@code QuotedIDFactory}. * * @return a string identifier of this factory type, not null * @throws UnsupportedOperationException if a factory type ID is not available */ default String getIDFactoryType() { return getIDFactoryType(getClass()); } static String getIDFactoryType(Class factoryClass) { //noinspection ConstantConditions return Stream.>iterate(factoryClass, Objects::nonNull, Class::getSuperclass) .flatMap(c -> Stream.ofNullable(c.getAnnotation(IDFactoryType.class)).map(IDFactoryType::value)) .findFirst() .orElseThrow(() -> new UnsupportedOperationException("No @IDFactoryType annotation found")); } /** * Supplies a human-readable string identifier of a {@link QuotedIDFactory} implementation class. *

* This annotation is read by default by {@link QuotedIDFactory#getIDFactoryType()} and its value can be used to * indicate the type of {@code QuotedIDFactory} in read/written data. *

*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface IDFactoryType { /** * The string identifying the ID factory type (such as {@code POSTGRESQL}). * * @return a string identifier of the ID factory type */ String value(); } /** * Supplier of {@link QuotedIDFactory} based on factory type identifier. *

* Instances of this interface can be used / injected wherever it is needed to obtain a {@code QuotedIDFactory} * instance matching a factory type (e.g., {@code POSTGRESQL}) only known at runtime, e.g., because deserialized * from read data. An instance of this interface covering all available {@code QuotedIDFactory} types in Ontop can * be injected using Ontop configuration / injection mechanism. *

*/ interface Supplier { /** * Returns a {@code QuotedIDFactory} with the ID factory type specified. * * @param idFactoryType factory type identifier * @return a corresponding factory instance */ Optional get(String idFactoryType); /** * Utility method producing a {@code Supplier} whose {@code get()} method returns one of the specified * {@code QuotedIDFactory}. * * @param factories the factories to return * @return the created supplier */ static Supplier wrap(QuotedIDFactory... factories) { ImmutableMap> map = Stream.of(factories) .collect(ImmutableMap.toImmutableMap(QuotedIDFactory::getIDFactoryType, Optional::of)); return idFactoryType -> map.getOrDefault(idFactoryType, Optional.empty()); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy