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

software.amazon.ion.impl.LocalSymbolTableImports Maven / Gradle / Ivy

There is a newer version: 1.5.1
Show newest version
/*
 * Copyright 2009-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at:
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file 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 software.amazon.ion.impl;

import java.util.ArrayList;
import static software.amazon.ion.SymbolTable.UNKNOWN_SYMBOL_ID;

import java.util.Arrays;
import java.util.List;
import software.amazon.ion.SymbolTable;
import software.amazon.ion.SymbolToken;

/**
 * This class manages the system symbol table and any shared symbol table(s)
 * imported by a local symbol table. It provides "find" methods to find
 * either symbol Ids or names in the imported tables.
 * 

* This class is immutable, and hence safe for use by multiple threads. */ // TODO amzn/ion-java#37 Create specialized class to handle the common case where // there are zero or one imported non-system shared symtab(s). final class LocalSymbolTableImports { /** * The symtabs imported by a local symtab, never null or empty. The first * symtab must be a system symtab, the rest must be non-system shared * symtabs. */ private final SymbolTable[] myImports; /** * The maxId of all imported tables, i.e., the sum of all maxIds declared * by symtabs in {@link #myImports}. */ private final int myMaxId; /** * The base Sid of each symtab in {@link #myImports} in parallel, i.e., * {@link #myBaseSids}[0] references {@link #myImports}[0]. Must be * the same length as {@link #myImports}. */ private final int[] myBaseSids; //========================================================================== // Constructor(s) and static factory methods //========================================================================== /** * Constructor, takes the passed-in {@code importTables} containing the * imported symtabs. * * @param importTables * the imported symtabs, must contain at least one element; the * first element must be a system symtab, the rest must be * non-system shared symtabs * * @throws IllegalArgumentException * if any import is a local table, or if any but the first is a * system table * @throws NullPointerException * if any import is null */ LocalSymbolTableImports(List importTables) { validateImports(importTables); int importTablesSize = importTables.size(); // detects and adapts local tables so they are importable myImports = new SymbolTable[importTablesSize]; for(int i = 0; i < importTables.size(); i++) { SymbolTable symbolTable = importTables.get(i); if(symbolTable.isLocalTable()) { myImports[i] = LocalSymbolTableImportAdapter.of((LocalSymbolTable) symbolTable); } else { myImports[i] = symbolTable; } } myBaseSids = new int[importTablesSize]; myMaxId = prepBaseSids(myBaseSids, myImports); } /** * Validates the import list to ensure that if there is a {@link LocalSymbolTable} in it then it's a single import * apart from the system table */ private void validateImports(final List importTables) { int sizeWithoutSystemTables = importTables.size(); int numberOfLocalTables = 0; for(SymbolTable table : importTables) { if(table.isLocalTable()) numberOfLocalTables++; if(table.isSystemTable()) sizeWithoutSystemTables--; } if(numberOfLocalTables > 0 && sizeWithoutSystemTables != 1){ throw new IllegalArgumentException("when importing LocalSymbolTables it needs to be the only import"); } } /** * @param defaultSystemSymtab * the default system symtab, which will be used if the first * import in {@code imports} isn't a system symtab, never null * @param imports * the set of shared symbol tables to import; the first (and only * the first) may be a system table, in which case the * {@code defaultSystemSymtab is ignored} * * @throws IllegalArgumentException * if any import is a local table, or if any but the first is a * system table * @throws NullPointerException * if any import is null */ LocalSymbolTableImports(SymbolTable defaultSystemSymtab, SymbolTable... imports) { assert defaultSystemSymtab.isSystemTable() : "defaultSystemSymtab isn't a system symtab"; if (imports != null && imports.length > 0) { final int offset; final SymbolTable systemTable; if (imports[0].isSystemTable()) { offset = 0; systemTable = imports[0]; } else { offset = 1; systemTable = defaultSystemSymtab; } myImports = new SymbolTable[imports.length + offset]; myImports[0] = systemTable; // no need to consider the offset here as it only comes in play when there is a system table validateImports(Arrays.asList(imports)); for(int i = 1 - offset; i < imports.length; i++) { SymbolTable symbolTable = imports[i]; if(symbolTable instanceof LocalSymbolTable) { myImports[i + offset] = LocalSymbolTableImportAdapter.of((LocalSymbolTable) symbolTable); } else { myImports[i + offset] = symbolTable; } } } else { // use defaultSystemSymtab only myImports = new SymbolTable[] { defaultSystemSymtab }; } myBaseSids = new int[myImports.length]; myMaxId = prepBaseSids(myBaseSids, myImports); } /** * Collects the necessary maxId info. from the passed-in {@code imports} * and populates the {@code baseSids} array. * * @return the sum of all imports' maxIds * * @throws IllegalArgumentException * if any symtab beyond the first is a local or system symtab */ private static int prepBaseSids(int[] baseSids, SymbolTable[] imports) { SymbolTable firstImport = imports[0]; assert firstImport.isSystemTable() : "first symtab must be a system symtab"; baseSids[0] = 0; int total = firstImport.getMaxId(); for (int i = 1; i < imports.length; i++) { SymbolTable importedTable = imports[i]; if (importedTable.isSystemTable()) { String message = "only non-system shared tables can be imported"; throw new IllegalArgumentException(message); } baseSids[i] = total; total += imports[i].getMaxId(); } return total; } //========================================================================== String findKnownSymbol(int sid) { String name = null; if (sid <= myMaxId) { int i, previousBaseSid = 0; for (i = 1; i < myImports.length; i++) { int baseSid = myBaseSids[i]; if (sid <= baseSid) { break; } previousBaseSid = baseSid; } // if we run over myImports.length, the sid is in the last symtab int importScopedSid = sid - previousBaseSid; name = myImports[i-1].findKnownSymbol(importScopedSid); } return name; } int findSymbol(String name) { SymbolToken tok = find(name); return (tok == null ? UNKNOWN_SYMBOL_ID : tok.getSid()); } /** * Finds a symbol already interned by an import, returning the lowest * known SID. *

* This method will not necessarily return the same instance given the * same input. * * @param text the symbol text to find * * @return * the interned symbol (with both text and SID), or {@code null} * if it's not defined by an imported table */ SymbolToken find(String text) { for (int i = 0; i < myImports.length; i++) { SymbolTable importedTable = myImports[i]; SymbolToken tok = importedTable.find(text); if (tok != null) { int sid = tok.getSid() + myBaseSids[i]; text = tok.getText(); // Use interned instance assert text != null; return new SymbolTokenImpl(text, sid); } } return null; } int getMaxId() { return myMaxId; } /** * Gets the sole system symtab. */ SymbolTable getSystemSymbolTable() { assert myImports[0].isSystemTable(); return myImports[0]; } /** * Gets all non-system shared symtabs (if any). * * @return a newly allocated copy of the imported symtabs */ SymbolTable[] getImportedTables() { int count = myImports.length - 1; // we don't include system symtab SymbolTable[] imports = new SymbolTable[count]; if (count > 0) { // defensive copy System.arraycopy(myImports, 1, imports, 0, count); } return imports; } /** * Returns the {@link #myImports} member field without making a copy. *

* Note: Callers must not modify the resulting SymbolTable array! * This will violate the immutability property of this class. * * @return * the backing array of imported symtabs, as-is; the first element * is a system symtab, the rest are non-system shared symtabs * * @see #getImportedTables() */ SymbolTable[] getImportedTablesNoCopy() { return myImports; } @Override public String toString() { return Arrays.toString(myImports); } /** * Determines whether the passed-in instance has the same sequence of * symbol table imports as this instance. Note that equality of these * imports are checked using their reference, instead of their semantic * state. */ boolean equalImports(LocalSymbolTableImports other) { return Arrays.equals(myImports, other.myImports); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy