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 * @since 3.2.0.3 (Phase 1)
036 */
037public class NamePolicyFactory {
038
039    private final EDbVendor vendor;
040
041    // Cache matchers per type to avoid repeated creation
042    private final Map<ESQLDataObjectType, SqlNameMatcher> matcherCache =
043        new EnumMap<>(ESQLDataObjectType.class);
044
045    /**
046     * Creates a new NamePolicyFactory for the specified database vendor.
047     *
048     * @param vendor the database vendor
049     */
050    public NamePolicyFactory(EDbVendor vendor) {
051        if (vendor == null) {
052            throw new IllegalArgumentException("vendor cannot be null");
053        }
054        this.vendor = vendor;
055    }
056
057    /**
058     * Returns the database vendor associated with this factory.
059     *
060     * @return the database vendor
061     */
062    public EDbVendor getVendor() {
063        return vendor;
064    }
065
066    /**
067     * Gets or creates a SqlNameMatcher for the specified object type.
068     *
069     * <p>The matcher's case sensitivity is determined by querying TSQLEnv's
070     * static maps (columnCollationCaseSensitive, tableCollationCaseSensitive, etc.)</p>
071     *
072     * <p>Results are cached to avoid repeated map lookups.</p>
073     *
074     * @param type the SQL data object type (table, column, function, etc.)
075     * @return a SqlNameMatcher configured for the vendor/type combination
076     */
077    public SqlNameMatcher getMatcherForType(ESQLDataObjectType type) {
078        // Check cache first
079        SqlNameMatcher cached = matcherCache.get(type);
080        if (cached != null) {
081            return cached;
082        }
083
084        // Create new matcher based on TSQLEnv's existing configuration
085        SqlNameMatcher matcher = createMatcher(type);
086        matcherCache.put(type, matcher);
087        return matcher;
088    }
089
090    /**
091     * Creates a SqlNameMatcher by reading TSQLEnv's case sensitivity maps.
092     *
093     * @param type the object type
094     * @return a newly created SqlNameMatcher
095     */
096    private SqlNameMatcher createMatcher(ESQLDataObjectType type) {
097        boolean caseSensitive;
098
099        switch (type) {
100            case dotCatalog:
101            case dotSchema:
102                // Catalog and schema use the catalogCollationCaseSensitive map
103                caseSensitive = TSQLEnv.catalogCollationCaseSensitive.get(vendor);
104                break;
105
106            case dotTable:
107            case dotProcedure:
108            case dotTrigger:
109            case dotOraclePackage:
110                // Tables, procedures, triggers, and Oracle packages use tableCollationCaseSensitive
111                caseSensitive = TSQLEnv.tableCollationCaseSensitive.get(vendor);
112                break;
113
114            case dotFunction:
115                // Functions have their own map
116                caseSensitive = TSQLEnv.functionCollationCaseSensitive.get(vendor);
117                break;
118
119            case dotColumn:
120                // Columns have their own map
121                caseSensitive = TSQLEnv.columnCollationCaseSensitive.get(vendor);
122                break;
123
124            default:
125                // Everything else uses the default map
126                caseSensitive = TSQLEnv.defaultCollationCaseSensitive.get(vendor);
127                break;
128        }
129
130        // Create a matcher with the appropriate case sensitivity
131        return SqlNameMatchers.withCaseSensitive(caseSensitive);
132    }
133
134    /**
135     * Convenience method to check if a specific object type is case-sensitive
136     * for this vendor.
137     *
138     * @param type the object type
139     * @return true if case-sensitive, false otherwise
140     */
141    public boolean isCaseSensitive(ESQLDataObjectType type) {
142        return getMatcherForType(type).isCaseSensitive();
143    }
144}