class TableFormatFactoryBase implements TableFormatFactory<T> {

	public static TableSchema deriveSchema(Map<String, String> properties) {
		final DescriptorProperties descriptorProperties = new DescriptorProperties();
		descriptorProperties.putProperties(properties);

		final TableSchema.Builder builder = TableSchema.builder();

		final TableSchema baseSchema = descriptorProperties.getTableSchema(SCHEMA);
		for (int i = 0; i < baseSchema.getFieldCount(); i++) {
			final String fieldName = baseSchema.getFieldNames()[i];
			final TypeInformation<?> fieldType = baseSchema.getFieldTypes()[i];

			final boolean isProctime = descriptorProperties
				.getOptionalBoolean(SCHEMA + '.' + i + '.' + SCHEMA_PROCTIME)
				.orElse(false);
			final String timestampKey = SCHEMA + '.' + i + '.' + ROWTIME_TIMESTAMPS_TYPE;
			final boolean isRowtime = descriptorProperties.containsKey(timestampKey);
			if (!isProctime && !isRowtime) {
				// check for aliasing
				final String aliasName = descriptorProperties
					.getOptionalString(SCHEMA + '.' + i + '.' + SCHEMA_FROM)
					.orElse(fieldName);
				builder.field(aliasName, fieldType);
			}
			// only use the rowtime attribute if it references a field
			else if (isRowtime &&
					descriptorProperties.isValue(timestampKey, ROWTIME_TIMESTAMPS_TYPE_VALUE_FROM_FIELD)) {
				final String aliasName = descriptorProperties
					.getString(SCHEMA + '.' + i + '.' + ROWTIME_TIMESTAMPS_FROM);
				builder.field(aliasName, fieldType);
			}
		}

		return builder.build();
	}

	public  TableFormatFactoryBase(String type, int version, boolean supportsSchemaDerivation);

}