001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to you under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package gudusoft.gsqlparser.sqlenv;
018
019import gudusoft.gsqlparser.EDbVendor;
020import gudusoft.gsqlparser.ext.sqlnamematcher.SqlNameMatcher;
021import gudusoft.gsqlparser.ext.sqlnamematcher.SqlNameMatchers;
022
023import java.util.EnumMap;
024import java.util.Map;
025
026/**
027 * Factory for creating SqlNameMatcher instances per database vendor and object type.
028 *
029 * <p>This class bridges GSP's existing case sensitivity configuration (stored in
030 * TSQLEnv's EnumMaps) to the SqlNameMatcher framework.</p>
031 *
032 * <p>Design rationale: Instead of duplicating vendor-specific case rules, this factory
033 * reads from TSQLEnv's existing static maps and creates appropriate matchers on demand.</p>
034 *
035 * <p><b>Status since the identifier normalization unification (P0d):</b> internal name
036 * equality no longer routes through this factory — {@link NameService} and every other
037 * engine delegate to the canonical relation
038 * ({@link gudusoft.gsqlparser.util.SQLUtil#sameName(EDbVendor, ESQLDataObjectType, String,
039 * String)} / {@link IdentifierService#areEqualStatic(EDbVendor, ESQLDataObjectType, String,
040 * String)}). This class remains only as the public {@code SqlNameMatcher} extension
041 * bridge. New internal code must use the {@code SQLUtil} façade, not a matcher from here.</p>
042 *
043 * @since 3.2.0.3 (Phase 1)
044 */
045public class NamePolicyFactory {
046
047    private final EDbVendor vendor;
048
049    // Cache matchers per type to avoid repeated creation
050    private final Map<ESQLDataObjectType, SqlNameMatcher> matcherCache =
051        new EnumMap<>(ESQLDataObjectType.class);
052
053    /**
054     * Creates a new NamePolicyFactory for the specified database vendor.
055     *
056     * @param vendor the database vendor
057     */
058    public NamePolicyFactory(EDbVendor vendor) {
059        if (vendor == null) {
060            throw new IllegalArgumentException("vendor cannot be null");
061        }
062        this.vendor = vendor;
063    }
064
065    /**
066     * Returns the database vendor associated with this factory.
067     *
068     * @return the database vendor
069     */
070    public EDbVendor getVendor() {
071        return vendor;
072    }
073
074    /**
075     * Gets or creates a SqlNameMatcher for the specified object type.
076     *
077     * <p>The matcher's case sensitivity is determined by querying TSQLEnv's
078     * static maps (columnCollationCaseSensitive, tableCollationCaseSensitive, etc.)</p>
079     *
080     * <p>Results are cached to avoid repeated map lookups.</p>
081     *
082     * @param type the SQL data object type (table, column, function, etc.)
083     * @return a SqlNameMatcher configured for the vendor/type combination
084     */
085    public SqlNameMatcher getMatcherForType(ESQLDataObjectType type) {
086        // Check cache first
087        SqlNameMatcher cached = matcherCache.get(type);
088        if (cached != null) {
089            return cached;
090        }
091
092        // Create new matcher based on TSQLEnv's existing configuration
093        SqlNameMatcher matcher = createMatcher(type);
094        matcherCache.put(type, matcher);
095        return matcher;
096    }
097
098    /**
099     * Creates a SqlNameMatcher by reading TSQLEnv's case sensitivity maps.
100     *
101     * @param type the object type
102     * @return a newly created SqlNameMatcher
103     */
104    private SqlNameMatcher createMatcher(ESQLDataObjectType type) {
105        boolean caseSensitive;
106
107        switch (type) {
108            case dotCatalog:
109            case dotSchema:
110                // Catalog and schema use the catalogCollationCaseSensitive map
111                caseSensitive = TSQLEnv.catalogCollationCaseSensitive.get(vendor);
112                break;
113
114            case dotTable:
115            case dotProcedure:
116            case dotTrigger:
117            case dotOraclePackage:
118                // Tables, procedures, triggers, and Oracle packages use tableCollationCaseSensitive
119                caseSensitive = TSQLEnv.tableCollationCaseSensitive.get(vendor);
120                break;
121
122            case dotFunction:
123                // Functions have their own map
124                caseSensitive = TSQLEnv.functionCollationCaseSensitive.get(vendor);
125                break;
126
127            case dotColumn:
128                // Columns have their own map
129                caseSensitive = TSQLEnv.columnCollationCaseSensitive.get(vendor);
130                break;
131
132            default:
133                // Everything else uses the default map
134                caseSensitive = TSQLEnv.defaultCollationCaseSensitive.get(vendor);
135                break;
136        }
137
138        // Create a matcher with the appropriate case sensitivity
139        return SqlNameMatchers.withCaseSensitive(caseSensitive);
140    }
141
142    /**
143     * Convenience method to check if a specific object type is case-sensitive
144     * for this vendor.
145     *
146     * @param type the object type
147     * @return true if case-sensitive, false otherwise
148     */
149    public boolean isCaseSensitive(ESQLDataObjectType type) {
150        return getMatcherForType(type).isCaseSensitive();
151    }
152}