private Pair<TableSchema, Function<MappingMetaData, Optional<TypeToken<?>>>> estimateSchema( final TableSchema providedSchema) { final Map<String, MappingMetaData> providedData = providedSchema .getEntries() .stream() .distinct() .collect(Collectors.toMap(MappingMetaData::getName, metaData -> metaData)); final List<MappingMetaData> metaDataList = new ArrayList<>(providedSchema.getEntries().size()); final Map<MappingMetaData, TypeToken<?>> types = new HashMap<>(); try (final ResultSet result = database.get().execute("SHOW COLUMNS FROM " + tableName)) { while (result.next()) { final String name = result.getString("Field"); final boolean isPrimaryKey = result.getString("Key").equals("PRI"); final String defaultValue; { final String cache = result.getString("Default"); if (cache == null || "null".equals(cache)) defaultValue = ""; else defaultValue = cache; } final TypeToken<?> type = getJavaTypeOf(result.getString("Type"), isPrimaryKey); final MappingMetaData finalMetaData; final MappingMetaData data = providedData.get(name); if (Objects.nonNull(data)) { // Complete info finalMetaData = new AbstractMappingMetaData() { @Override public String getName() { return data.getName(); } @Override public String getTarget() { return data.getTarget(); } @Override public String getDescription() { return data.getDescription(); } @Override public String getCategory() { return data.getCategory(); }; @Override public String getDefaultValue() { return data.getDefaultValue().isEmpty() ? defaultValue : data.getDefaultValue(); }; @Override public int getIndex() { return data.getIndex(); } @Override public boolean isKey() { return data.isKey() ? true : isPrimaryKey; } @Override public String getAlias() { return data.getAlias(); } }; } else if (providedSchema.getPolicy().hasPermissionToAddColumns()) { // Add column finalMetaData = new AbstractMappingMetaData() { @Override public String getName() { return name; } @Override public String getDescription() { return "Auto completed"; } @Override public String getDefaultValue() { return defaultValue; }; @Override public boolean isKey() { return isPrimaryKey; } }; } else continue; metaDataList.add(finalMetaData); types.put(finalMetaData, type); } } catch (final Throwable t) { throw new DatabaseConnectionException(t); } // Get Fields of the table return new Pair<>( new TableSchema() { private final List<MappingMetaData> entries = Collections.unmodifiableList(metaDataList); @Override public SchemaPolicy getPolicy() { return providedSchema.getPolicy(); } @Override public String getStructure() { return providedSchema.getStructure(); } @Override public String getName() { return providedSchema.getName(); } @Override public ClientStorageFormat getFormat() { return providedSchema.getFormat(); } @Override public List<MappingMetaData> getEntries() { return entries; } }, m -> Optional.ofNullable(types.get(m))); }
public ServerStorageImpl( final String databaseId, final String tableName, final ChangeTrackerImpl changeTracker) throws ServerStorageException { this.databaseId = databaseId; this.tableName = tableName; this.changeTracker = changeTracker; this.database.bind(FrameworkServiceImpl.getDatabasePoolService().requestConnection(databaseId)); final Optional<TableSchema> trySchema = FrameworkServiceImpl.getConfigService() .getActiveEnvironment() .getDatabaseConfig(databaseId) .schema() .get() .getSchemaOf(tableName); // Estimate tables without provided schema // Create empty schema final TableSchema providedSchema = trySchema.orElseGet( () -> { return new TableSchema() { private final List<MappingMetaData> entries = Collections.emptyList(); @Override public SchemaPolicy getPolicy() { return SchemaPolicy.LAZY; } @Override public String getStructure() { return UnknownServerStorageStructure.class.getCanonicalName(); } @Override public String getName() { return tableName; } @Override public ClientStorageFormat getFormat() { throw new UnsupportedOperationException(); } @Override public List<MappingMetaData> getEntries() { return entries; } }; }); final TableSchema schema; final Function<MappingMetaData, Optional<TypeToken<?>>> typeReceiver; if (!providedSchema.getPolicy().hasPermissionToComplete()) { schema = providedSchema; typeReceiver = metaData -> Optional.empty(); } else { final Pair<TableSchema, Function<MappingMetaData, Optional<TypeToken<?>>>> result = estimateSchema(providedSchema); schema = result.first(); typeReceiver = result.second(); } this.structureName = schema.getStructure(); mapper = new JsonMapper<>( schema, SQLToPropertyMappingAdapterHolder.<T>get(), Arrays.asList(ServerStorageStructurePrivateBase.class), ServerStorageStructureBaseImplementation.class, typeReceiver); statementObject = tableName + PreparedStatements.STATEMENT_SELECT_ROW.toString() + (/*FIXME*/ INCREMENT++); selectLowPart = createSelectFormat(); statementFormat = createStatementFormat(); this.database.addListener( new ChangeListener<Database>() { @Override public void changed( final ObservableValue<? extends Database> observable, final Database oldValue, final Database newValue) { alive.unbind(); if (Objects.nonNull(newValue)) { alive.bind(newValue.alive()); registerStatements(); } else alive.set(false); } }); registerStatements(); }