/* * ToroDB * Copyright © 2014 8Kdata Technology (www.8kdata.com) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.torodb.backend; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.torodb.backend.meta.TorodbSchema; import com.torodb.backend.tables.MetaDocPartTable.DocPartTableFields; import com.torodb.core.backend.IdentifierConstraints; import com.torodb.core.exceptions.SystemException; import com.torodb.core.transaction.metainf.FieldType; import java.util.HashSet; import java.util.Set; import javax.annotation.Nonnull; import javax.inject.Singleton; @Singleton public abstract class AbstractIdentifierConstraints implements IdentifierConstraints { private static final char SEPARATOR = '_'; private static final char ARRAY_DIMENSION_SEPARATOR = '$'; private final ImmutableMap<FieldType, Character> fieldTypeIdentifiers; private final ImmutableMap<FieldType, String> scalarFieldTypeIdentifiers; private final ImmutableSet<String> restrictedSchemaNames; private final ImmutableSet<String> restrictedColumnNames; protected AbstractIdentifierConstraints(ImmutableSet<String> restrictedSchemaNames, ImmutableSet<String> restrictedColumnNames) { this.fieldTypeIdentifiers = Maps.immutableEnumMap(ImmutableMap.<FieldType, Character>builder() .put(FieldType.BINARY, 'r') // [r]aw bytes .put(FieldType.BOOLEAN, 'b') // [b]oolean .put(FieldType.DOUBLE, 'd') // [d]ouble .put(FieldType.INSTANT, 't') // [t]imestamp .put(FieldType.INTEGER, 'i') // [i]nteger .put(FieldType.LONG, 'l') // [l]ong .put(FieldType.NULL, 'n') // [n]ull .put(FieldType.STRING, 's') // [s]tring .put(FieldType.CHILD, 'e') // child [e]lement // Mongo types .put(FieldType.MONGO_OBJECT_ID, 'x') .put(FieldType.MONGO_TIME_STAMP, 'y') // No-Mongo types .put(FieldType.DATE, 'c') // [c]alendar .put(FieldType.TIME, 'm') // ti[m]e .build()); ImmutableMap.Builder<FieldType, String> scalarFieldTypeIdentifiersBuilder = ImmutableMap.<FieldType, String>builder(); Set<Character> fieldTypeIdentifierSet = new HashSet<>(); for (FieldType fieldType : FieldType.values()) { if (!this.fieldTypeIdentifiers.containsKey(fieldType)) { throw new SystemException("FieldType " + fieldType + " has not been mapped to an identifier."); } char identifier = this.fieldTypeIdentifiers.get(fieldType); if ((identifier < 'a' || identifier > 'z') && (identifier < '0' || identifier > '9')) { throw new SystemException("FieldType " + fieldType + " has an unallowed identifier " + identifier); } if (fieldTypeIdentifierSet.contains(identifier)) { throw new SystemException("FieldType " + fieldType + " identifier " + identifier + " was used by another FieldType."); } fieldTypeIdentifierSet.add(identifier); scalarFieldTypeIdentifiersBuilder.put(fieldType, DocPartTableFields.SCALAR.fieldName + SEPARATOR + identifier); } this.scalarFieldTypeIdentifiers = Maps.immutableEnumMap(scalarFieldTypeIdentifiersBuilder .build()); this.restrictedSchemaNames = ImmutableSet.<String>builder() .add(TorodbSchema.IDENTIFIER) .addAll(restrictedSchemaNames) .build(); this.restrictedColumnNames = ImmutableSet.<String>builder() .add(DocPartTableFields.DID.fieldName) .add(DocPartTableFields.RID.fieldName) .add(DocPartTableFields.PID.fieldName) .add(DocPartTableFields.SEQ.fieldName) .addAll(scalarFieldTypeIdentifiers.values()) .addAll(restrictedColumnNames) .build(); } @Override public char getSeparator() { return SEPARATOR; } @Override public char getArrayDimensionSeparator() { return ARRAY_DIMENSION_SEPARATOR; } @Override public boolean isAllowedSchemaIdentifier(@Nonnull String schemaName) { return !restrictedSchemaNames.contains(schemaName); } @Override public boolean isAllowedTableIdentifier(@Nonnull String columnName) { return true; } @Override public boolean isAllowedColumnIdentifier(@Nonnull String columnName) { return !restrictedColumnNames.contains(columnName); } @Override public boolean isAllowedIndexIdentifier(@Nonnull String indexName) { return true; } @Override public boolean isSameIdentifier(@Nonnull String leftIdentifier, @Nonnull String rightIdentifier) { return leftIdentifier.equals(rightIdentifier); //leftIdentifier.toLowerCase(Locale.US).equals(rightIdentifier.toLowerCase(Locale.US)); } @Override public char getFieldTypeIdentifier(FieldType fieldType) { return fieldTypeIdentifiers.get(fieldType); } @Override public String getScalarIdentifier(FieldType fieldType) { return scalarFieldTypeIdentifiers.get(fieldType); } }