<commit_before>/*
 * Copyright 2015, Yahoo Inc.
 * Copyrights licensed under the Apache 2.0 License.
 * See the accompanying LICENSE file for terms.
 */
package com.yahoo.squidb.processor.plugins.defaults.properties;

import com.yahoo.aptutils.model.DeclaredTypeName;
import com.yahoo.aptutils.utils.AptUtils;
import com.yahoo.squidb.annotations.PrimaryKey;
import com.yahoo.squidb.processor.TypeConstants;
import com.yahoo.squidb.processor.data.ModelSpec;
import com.yahoo.squidb.processor.data.TableModelSpecWrapper;
import com.yahoo.squidb.processor.plugins.PluginEnvironment;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicBlobPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicBooleanPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicDoublePropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicIntegerPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicLongPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicStringPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.PropertyGenerator;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.lang.model.element.VariableElement;
import javax.tools.Diagnostic;
import javax.tools.Diagnostic.Kind;

/**
 * This plugin controls generating property declarations, getters, and setters for fields in a table model. It can
 * create instances of {@link PropertyGenerator} for each of the basic supported column types (String, int, long, etc.)
 */
public class TableModelSpecFieldPlugin extends BaseFieldPlugin {

    private Map<DeclaredTypeName, Class<? extends BasicPropertyGenerator>> generatorMap = new HashMap<>();

    public TableModelSpecFieldPlugin(ModelSpec<?> modelSpec, PluginEnvironment pluginEnv) {
        super(modelSpec, pluginEnv);
        registerBasicPropertyGenerators();
    }

    @Override
    public boolean hasChangesForModelSpec() {
        return modelSpec instanceof TableModelSpecWrapper;
    }

    @Override
    public boolean processVariableElement(VariableElement field, DeclaredTypeName fieldType) {
        if (TypeConstants.isConstant(field)) {
            // Looks like a constant, ignore
            return false;
        } else {
            if (field.getAnnotation(PrimaryKey.class) != null) {
                if (modelSpec instanceof TableModelSpecWrapper
                        && ((TableModelSpecWrapper) modelSpec).isVirtualTable()) {
                    utils.getMessager().printMessage(Kind.ERROR,
                            "Virtual tables cannot declare a custom primary key", field);
                } else if (modelSpec.hasMetadata(TableModelSpecWrapper.METADATA_KEY_HAS_PRIMARY_KEY)) {
                    utils.getMessager().printMessage(Diagnostic.Kind.ERROR,
                            "Only a single field can be annotated as @PrimaryKey. If you want a multi-column primary "
                                    + "key, specify it using SQL in TableModelSpec#tableConstraint() and set "
                                    + "TableModelSpec#noRowIdAlias() to true in your TableModelSpec annotation.",
                            field);
                } else {
                    modelSpec.putMetadata(TableModelSpecWrapper.METADATA_KEY_HAS_PRIMARY_KEY, true);
                    if (TypeConstants.isIntegerType(fieldType)) {
                        modelSpec.putMetadata(TableModelSpecWrapper.METADATA_KEY_ROWID_ALIAS_PROPERTY_GENERATOR,
                                getPropertyGenerator(field, fieldType));
                        return true;
                    } else {
                        return super.processVariableElement(field, fieldType);
                    }
                }
            } else {
                return super.processVariableElement(field, fieldType);
            }
        }
        return false;
    }

    @Override
    protected boolean hasPropertyGeneratorForField(VariableElement field, DeclaredTypeName fieldType) {
        return generatorMap.containsKey(fieldType);
    }

    @Override
    protected PropertyGenerator getPropertyGenerator(VariableElement field, DeclaredTypeName fieldType) {
        Class<? extends BasicPropertyGenerator> generatorClass = generatorMap.get(fieldType);
        try {
            BasicPropertyGenerator propertyGenerator = generatorClass.getConstructor(ModelSpec.class,
                    VariableElement.class, AptUtils.class).newInstance(modelSpec, field, utils);
            if ("rowid".equalsIgnoreCase(propertyGenerator.getColumnName())) {
                utils.getMessager().printMessage(Kind.ERROR, "Columns in a table model spec cannot be named rowid, as "<commit_msg>Coerce all integer primary key properties to LongProperty<commit_after>/*
 * Copyright 2015, Yahoo Inc.
 * Copyrights licensed under the Apache 2.0 License.
 * See the accompanying LICENSE file for terms.
 */
package com.yahoo.squidb.processor.plugins.defaults.properties;

import com.yahoo.aptutils.model.DeclaredTypeName;
import com.yahoo.aptutils.utils.AptUtils;
import com.yahoo.squidb.annotations.PrimaryKey;
import com.yahoo.squidb.processor.TypeConstants;
import com.yahoo.squidb.processor.data.ModelSpec;
import com.yahoo.squidb.processor.data.TableModelSpecWrapper;
import com.yahoo.squidb.processor.plugins.PluginEnvironment;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicBlobPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicBooleanPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicDoublePropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicIntegerPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicLongPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.BasicStringPropertyGenerator;
import com.yahoo.squidb.processor.plugins.defaults.properties.generators.PropertyGenerator;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.lang.model.element.VariableElement;
import javax.tools.Diagnostic;
import javax.tools.Diagnostic.Kind;

/**
 * This plugin controls generating property declarations, getters, and setters for fields in a table model. It can
 * create instances of {@link PropertyGenerator} for each of the basic supported column types (String, int, long, etc.)
 */
public class TableModelSpecFieldPlugin extends BaseFieldPlugin {

    private Map<DeclaredTypeName, Class<? extends BasicPropertyGenerator>> generatorMap = new HashMap<>();

    public TableModelSpecFieldPlugin(ModelSpec<?> modelSpec, PluginEnvironment pluginEnv) {
        super(modelSpec, pluginEnv);
        registerBasicPropertyGenerators();
    }

    @Override
    public boolean hasChangesForModelSpec() {
        return modelSpec instanceof TableModelSpecWrapper;
    }

    @Override
    public boolean processVariableElement(VariableElement field, DeclaredTypeName fieldType) {
        if (TypeConstants.isConstant(field)) {
            // Looks like a constant, ignore
            return false;
        } else {
            if (field.getAnnotation(PrimaryKey.class) != null) {
                if (modelSpec instanceof TableModelSpecWrapper
                        && ((TableModelSpecWrapper) modelSpec).isVirtualTable()) {
                    utils.getMessager().printMessage(Kind.ERROR,
                            "Virtual tables cannot declare a custom primary key", field);
                } else if (modelSpec.hasMetadata(TableModelSpecWrapper.METADATA_KEY_HAS_PRIMARY_KEY)) {
                    utils.getMessager().printMessage(Diagnostic.Kind.ERROR,
                            "Only a single field can be annotated as @PrimaryKey. If you want a multi-column primary "
                                    + "key, specify it using SQL in TableModelSpec#tableConstraint() and set "
                                    + "TableModelSpec#noRowIdAlias() to true in your TableModelSpec annotation.",
                            field);
                } else {
                    modelSpec.putMetadata(TableModelSpecWrapper.METADATA_KEY_HAS_PRIMARY_KEY, true);
                    if (TypeConstants.isIntegerType(fieldType)) {
                        modelSpec.putMetadata(TableModelSpecWrapper.METADATA_KEY_ROWID_ALIAS_PROPERTY_GENERATOR,
                                getPropertyGenerator(field, fieldType));
                        return true;
                    } else {
                        return super.processVariableElement(field, fieldType);
                    }
                }
            } else {
                return super.processVariableElement(field, fieldType);
            }
        }
        return false;
    }

    @Override
    protected boolean hasPropertyGeneratorForField(VariableElement field, DeclaredTypeName fieldType) {
        return generatorMap.containsKey(fieldType);
    }

    @Override
    protected PropertyGenerator getPropertyGenerator(VariableElement field, DeclaredTypeName fieldType) {
        Class<? extends BasicPropertyGenerator> generatorClass;
        if (isIntegerPrimaryKey(field, fieldType)) {
            // Force INTEGER PRIMARY KEY properties to be LongProperty, even if declared as e.g. int
            generatorClass = getLongPropertyGenerator();
        } else {
            generatorClass = generatorMap.get(fieldType);
        }
        try {
            BasicPropertyGenerator propertyGenerator = generatorClass.getConstructor(ModelSpec.class,
                    VariableElement.class, AptUtils.class).newInstance(modelSpec, field, utils);
            if ("rowid".equalsIgnoreCase(propertyGenerator.getColumnName())) {
                utils.getMessager().printMessage(Kind.ERROR, "Columns in a table model spec cannot be named rowid, as "
{'fraction_non_alphanumeric': 0.0792185069984448, 'fraction_numerical': 0.0011664074650077762, 'mean_word_length': 3.0238560813453264, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3408994', 'n_tokens_mistral': 2612, 'n_tokens_neox': 2463, 'n_words': 554}