es.juntadeandalucia.panelGestion.presentacion.controlador.impl.GeosearchController.java Source code

Java tutorial

Introduction

Here is the source code for es.juntadeandalucia.panelGestion.presentacion.controlador.impl.GeosearchController.java

Source

/**
 * Empresa desarrolladora: GUADALTEL S.A.
 *
 * Autor: Junta de Andaluca
 *
 * Derechos de explotacin propiedad de la Junta de Andaluca.
 *
 * Este programa es software libre: usted tiene derecho a redistribuirlo y/o modificarlo bajo los trminos de la
 *
 * Licencia EUPL European Public License publicada por el organismo IDABC de la Comisin Europea, en su versin 1.0.
 * o posteriores.
 *
 * Este programa se distribuye de buena fe, pero SIN NINGUNA GARANT?A, incluso sin las presuntas garantas implcitas
 * de USABILIDAD o ADECUACIN A PROPSITO CONCRETO. Para mas informacin consulte la Licencia EUPL European Public
 * License.
 *
 * Usted recibe una copia de la Licencia EUPL European Public License junto con este programa, si por algn motivo no
 * le es posible visualizarla, puede consultarla en la siguiente URL: http://ec.europa.eu/idabc/servlets/Doc?id=31099
 *
 * You should have received a copy of the EUPL European Public License along with this program. If not, see
 * http://ec.europa.eu/idabc/servlets/Doc?id=31096
 *
 * Vous devez avoir reu une copie de la EUPL European Public License avec ce programme. Si non, voir
 * http://ec.europa.eu/idabc/servlets/Doc?id=30194
 *
 * Sie sollten eine Kopie der EUPL European Public License zusammen mit diesem Programm. Wenn nicht, finden Sie da
 * http://ec.europa.eu/idabc/servlets/Doc?id=29919
 */
/**
 * 
 */
package es.juntadeandalucia.panelGestion.presentacion.controlador.impl;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathExpressionException;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.international.StatusMessage.Severity;
import org.jboss.seam.international.StatusMessages;

import es.juntadeandalucia.panelGestion.exception.GeosearchException;
import es.juntadeandalucia.panelGestion.exception.PanelException;
import es.juntadeandalucia.panelGestion.negocio.servicios.ServiceService;
import es.juntadeandalucia.panelGestion.negocio.utiles.PanelSettings;
import es.juntadeandalucia.panelGestion.negocio.utiles.Utils;
import es.juntadeandalucia.panelGestion.negocio.utiles.geosearch.Geosearch;
import es.juntadeandalucia.panelGestion.negocio.utiles.geosearch.GeosearchConfigWriter;
import es.juntadeandalucia.panelGestion.negocio.utiles.geosearch.GeosearchDataImportWriter;
import es.juntadeandalucia.panelGestion.negocio.utiles.geosearch.GeosearchSchemaWriter;
import es.juntadeandalucia.panelGestion.negocio.utiles.geosearch.GeosearchUtils;
import es.juntadeandalucia.panelGestion.negocio.vo.GeosearchFieldVO;
import es.juntadeandalucia.panelGestion.negocio.vo.GeosearchTableVO;
import es.juntadeandalucia.panelGestion.negocio.vo.XMLFileVO;
import es.juntadeandalucia.panelGestion.persistencia.entidades.Service;
import es.juntadeandalucia.panelGestion.persistencia.entidades.ServiceType;
import es.juntadeandalucia.panelGestion.persistencia.entidades.Table;

@AutoCreate
@Scope(ScopeType.CONVERSATION)
@Name("geosearchController")
public class GeosearchController implements Serializable {

    /**
     * Generated serial version UID
     */
    private static final long serialVersionUID = -3097437847618823807L;

    private static Logger log = Logger.getLogger(GeosearchController.class);

    private static final String CONTENT_TYPE = "application/zip";

    private static final String FILE_NAME = "configuration.zip";

    @In
    private ServiceService serviceService;

    /**
     * Workspace controller
     */
    @In
    private WorkspaceController wscontroller;

    @In(value = "#{facesContext.externalContext}")
    private ExternalContext externalCtx;

    @In(value = "#{facesContext}")
    private FacesContext facesContext;

    private String newCoreName;
    private List<GeosearchTableVO> tables;
    private int tableIndex;
    private String core;
    private List<String> cores;
    private boolean newTable;
    private List<GeosearchFieldVO> schemaFields;
    private List<String> geosearchTypes;
    private boolean newCore;

    public GeosearchController() {
        cores = new LinkedList<String>();

        try {
            cores = Geosearch.getCores();
        } catch (GeosearchException e) {
            log.error("Error en la consulta de cores de Geobsquedas: " + e.getLocalizedMessage());
        }
        tables = new LinkedList<GeosearchTableVO>();
        tables.add(new GeosearchTableVO());
    }

    public void onSelectTable() {
        Table table = wscontroller.getTable();
        selectTable(table);
    }

    public void onSelectCore() {
        try {
            if (!StringUtils.isEmpty(core)) {
                geosearchTypes = Geosearch.getFieldTypes(core);
                schemaFields = Geosearch.getFields(core);
            }
        } catch (GeosearchException e) {
            log.error("Error en la consulta de los campos de Geobsquedas: " + e.getLocalizedMessage());
        }
    }

    public void selectTable(Table table) {
        if (table != null) {
            // checks if the table was already configured
            Integer condiguredTableIndex = null;
            for (int i = 0; i < tables.size(); i++) {
                GeosearchTableVO configuredTable = tables.get(i);
                if (table.equals(configuredTable.getTable())) {
                    condiguredTableIndex = i;
                    break;
                }
            }

            int lastIndex = tables.size() - 1;
            if (condiguredTableIndex != null) {
                // remove the new created table
                if (tables.get(lastIndex).getTable() == null) {
                    tables.remove(lastIndex);
                }
                tableIndex = condiguredTableIndex;
                newTable = false;
            } else {
                try {
                    tableIndex = lastIndex;
                    newTable = false;

                    // updates table index pointer and set the last table with the selected one
                    GeosearchTableVO geosearchTable = GeosearchUtils.toGeosearchTable(table);

                    // if it has not a new created table then creates one
                    if ((tables.get(lastIndex).getTable() != null) && !StringUtils.isEmpty(core)) {
                        tables.add(geosearchTable);
                        tableIndex++;
                    } else {
                        tables.set(tableIndex, geosearchTable);
                    }
                } catch (Exception e) {
                    String errorMessage = "No se ha podido obtener la configuracin de la tabla: "
                            + e.getLocalizedMessage();
                    StatusMessages.instance().add(Severity.ERROR, errorMessage);
                    log.error(errorMessage);
                }
            }
        }
    }

    public void addTable() {
        // add a new empty table
        tables.add(new GeosearchTableVO());
        tableIndex = tables.size() - 1;
        wscontroller.reset();
        newTable = true;
    }

    public void removeTable(int i) {
        tables.remove(i);
        tableIndex--;
    }

    /**
     * This method 
     * TODO
     *
     * Para realizar la configuracin se obtienen los archivos de configuracin
     * se realizan las modificaciones necesarias y se le facilita al usuario
     * dichos archivos para que finalice l el procedimiento de configuracin.
     * Las ltimas versiones de Solr admiten modificaciones del Schema a travs
     * de un API REST pero consideramos lioso realizar por un lado la configuracin
     * del schema mediante API y transparente al usuario y por otro lado darle los
     * archivos al usuario para que los sustituya en Geosearch.
     * 
     * @see https://wiki.apache.org/solr/SchemaRESTAPI
     */
    public void downloadConfig() {
        String errorMessage = null;

        ServletOutputStream os = null;

        try {
            // checks
            // checks if specified a table
            if (tables.isEmpty()) {
                throw new Exception("No se ha especificado ninguna tabla");
            }
            // checks if specified a field
            boolean specifiedField = false;
            tables_loop: for (GeosearchTableVO table : tables) {
                List<GeosearchFieldVO> fields = table.getFields();
                for (GeosearchFieldVO field : fields) {
                    if (field.isDefined()) {
                        specifiedField = true;
                        break tables_loop;
                    }
                }
            }
            if (!specifiedField) {
                throw new Exception("No se ha configurado ningn campo de las tablas seleccionadas");
            }
            // checks duplicated fields each table
            for (GeosearchTableVO table : tables) {
                if (tableHasDuplicatedFields(table)) {
                    throw new Exception("Existen campos duplicados en la tabla '".concat(table.getTable().getName())
                            .concat("'. Revise su configuracin."));
                }
            }

            // ovverides the duplicated field values
            overrideDuplicatedFields();

            checkFieldErrors();

            // gets the zip file with configuration
            byte[] configurationData = generateConfigurationZipData();

            // configures the response
            HttpServletResponse response = (HttpServletResponse) externalCtx.getResponse();
            response.setContentType(CONTENT_TYPE);
            response.addHeader("Content-disposition", "attachment; filename=\"".concat(FILE_NAME).concat("\""));

            os = response.getOutputStream();
            os.write(configurationData);
            os.flush();
            os.close();
            facesContext.responseComplete();
        } catch (GeosearchException e) {
            errorMessage = "Error en la generacin de los archivos de configuracin: " + e.getLocalizedMessage();
        } catch (ParserConfigurationException e) {
            errorMessage = "Error en la generacin de los archivos de configuracin: " + e.getLocalizedMessage();
        } catch (XPathExpressionException e) {
            errorMessage = "Error en la generacin de los archivos de configuracin: " + e.getLocalizedMessage();
        } catch (TransformerException e) {
            errorMessage = "Error al comprimir los archivos de configuracin: " + e.getLocalizedMessage();
        } catch (IOException e) {
            errorMessage = "Error al comprimir los archivos de configuracin: " + e.getLocalizedMessage();
        } catch (Exception e) {
            errorMessage = "Error en la descarga de la configuracin: " + e.getLocalizedMessage();
        } finally {
            try {
                if (os != null) {
                    os.flush();
                    os.close();
                }
            } catch (IOException e) {
                errorMessage = "Error al comprimir los archivos de configuracin: " + e.getLocalizedMessage();
            }
        }

        if (errorMessage != null) {
            StatusMessages.instance().add(Severity.ERROR, errorMessage);
            log.error(errorMessage);
        } else {
            // saves the new service for each table
            try {
                ServiceType geosearchType = serviceService.getServiceType("geobusquedas");
                for (GeosearchTableVO geosearchTable : tables) {
                    Table table = geosearchTable.getTable();
                    Service geosearchService = new Service();
                    geosearchService.setName(table.getName());
                    geosearchService.setServiceUrl(PanelSettings.geosearchMaster.getUrl().concat("/").concat(core));
                    geosearchService.setType(geosearchType);
                    serviceService.create(geosearchService, table);
                }
            } catch (Exception e) {
                errorMessage = "";
                StatusMessages.instance().add(Severity.ERROR, errorMessage);
                log.error(errorMessage);
            }
        }
    }

    private void checkFieldErrors() throws PanelException {
        for (GeosearchTableVO table : tables) {
            List<GeosearchFieldVO> fields = table.getFields();
            for (GeosearchFieldVO field : fields) {
                if (field.isDefined()) {
                    String fieldName = Utils.getFieldName(field);

                    // checks field name
                    if (StringUtils.isEmpty(fieldName)) {
                        String errorMessage = "No ha especificado nombre para el campo";
                        throw new PanelException(errorMessage);
                    } else if (!Utils.isValidName(fieldName)) {
                        String errorMessage = "Nombre del campo invlido: ".concat(fieldName);
                        throw new PanelException(errorMessage);
                    }

                    // checks type
                    if (StringUtils.isEmpty(field.getType())) {
                        String errorMessage = "No ha especificado tipo para el campo '" + fieldName + "'";
                        throw new PanelException(errorMessage);
                    }

                    // checks boost
                    String fieldBoost = field.getBoost();
                    if (!StringUtils.isEmpty(fieldBoost) && !Utils.isValidDouble(fieldBoost)) {
                        String errorMessage = "El peso del campo '" + fieldName + "' es invlido";
                        throw new PanelException(errorMessage);
                    }
                }
            }
        }
    }

    /**
     * Overrides the duplicated fields. These are the fields which
     * have equal names or nameOnTable attributes
     * @throws PanelException if some error occurs
     */
    private void overrideDuplicatedFields() {
        GeosearchTableVO currentTable = tables.get(this.tableIndex);
        List<GeosearchFieldVO> fields = currentTable.getFields();
        for (GeosearchFieldVO field : fields) {
            if (field.isDefined()) {
                // override each field
                overrideDuplicatedField(field);
            }
        }
    }

    /**
     * Generates the bytes of the compressed generated files: solrconfig.xml, schema.xml
     * and dataImport.xml for the selected configuration
     *
     * @return the bytes of the compressed generated files
     * 
     * @throws GeosearchException thrown if some error occurred while
     *  trying to connect with Geosearch
     * @throws ParserConfigurationException thrown by the configuration parser
     * @throws XPathExpressionException thrown while managing the configuration files
     * @throws TransformerException thrown while managing the configuration files
     * @throws IOException thrown while compressing the files
     */
    private byte[] generateConfigurationZipData() throws GeosearchException, ParserConfigurationException,
            XPathExpressionException, TransformerException, IOException {
        byte[] zipFile = null;

        // generates the configuration files
        // solrconfig.xml
        GeosearchConfigWriter configWriter = new GeosearchConfigWriter(tables, core);
        XMLFileVO configXML = configWriter.write();
        // schema.xml
        GeosearchSchemaWriter schemaWriter = new GeosearchSchemaWriter(tables, core);
        XMLFileVO schemaXML = schemaWriter.write();
        // dataimport.xml
        GeosearchDataImportWriter dataImportWriter = new GeosearchDataImportWriter(tables, core);
        XMLFileVO dataImportXML = dataImportWriter.write();

        XMLFileVO[] xmlFiles = { configXML, dataImportXML, schemaXML };
        zipFile = Utils.compressXMLFiles(xmlFiles);

        return zipFile;
    }

    public void createNewCore() {
        String errorMessage = null;

        try {
            if (StringUtils.isEmpty(newCoreName)) {
                errorMessage = "Debe especificar un nombre para el nuevo core";
            } else if (!Utils.isValidName(newCoreName)) {
                errorMessage = "El nombre para el nuevo core es invlido: " + newCoreName;
            } else if (Geosearch.existsCore(newCoreName)) {
                errorMessage = "El core '".concat(newCoreName).concat("' ya existe en Geobsquedas");
            } else {
                boolean created = Geosearch.createCore(newCoreName);
                if (created) {
                    // reloads the core list
                    cores = Geosearch.getCores();
                    // selects the new core
                    core = newCoreName;
                    // reset newCore flag
                    newCore = false;

                    // triggers the onSelectCore event
                    onSelectCore();

                    // informs to the user
                    String successMessage = "El core '".concat(core).concat("' ha sido creado satisfactoriamente");
                    StatusMessages.instance().add(Severity.INFO, successMessage);
                    log.info(successMessage);
                } else {
                    errorMessage = "El core no ha podido crearse. Compruebe la configuracin de Geobsquedas";
                }
            }
        } catch (IOException e) {
            errorMessage = "Error en la creacin de la carpeta del core: " + e.getLocalizedMessage();
        } catch (GeosearchException e) {
            errorMessage = "Error en la creacin del core: " + e.getLocalizedMessage();
        }

        if (errorMessage != null) {
            StatusMessages.instance().add(Severity.ERROR, errorMessage);
            log.error(errorMessage);
        }
    }

    public void reset() {
        newCoreName = null;
        tables.clear();
        tables.add(new GeosearchTableVO());
        tableIndex = 0;
        core = null;
        newTable = false;
        newCore = false;

        if (schemaFields != null) {
            schemaFields.clear();
        }

        if (geosearchTypes != null) {
            geosearchTypes.clear();
        }

        try {
            cores.clear();
            cores = Geosearch.getCores();
        } catch (GeosearchException e) {
            log.error("Error en la consulta de cores de Geobsquedas: " + e.getLocalizedMessage());
        }
        //      wscontroller.reset();
    }

    /**
     * Checks if the field exists in the schema.xml file of the
     * selected core or there are some fields using the same name
     *
     * @param field Field to check
     */
    public void overrideDuplicatedField(GeosearchFieldVO field) {
        field.setError(null);
        field.setInSchema(false);

        if (!field.isDefined()) {
            return;
        }

        // gets the column name
        String fieldName = Utils.getFieldName(field);

        /*
         * gets the selected fields with same name which is not in the current table and the fields in
         * the schema.xml
         */
        GeosearchTableVO tableOwn = tables.get(tableIndex);

        // checks duplicated fields on the own table
        boolean duplicatedOnTable = tableHasDuplicatedFields(tableOwn);
        if (duplicatedOnTable) {
            String errorMessage = "La tabla '".concat(tableOwn.getTable().getName())
                    .concat("' posee campos duplicados");
            StatusMessages.instance().add(Severity.ERROR, errorMessage);
            log.error(errorMessage);
        } else {
            GeosearchFieldVO selectedColumn = getSelectedColumn(fieldName, tableOwn.getTable());
            GeosearchFieldVO schemaField = getSchemaField(fieldName);

            // if there is a field in the schema.xml with the same name
            if (schemaField != null) {
                field.setIndexed(schemaField.isIndexed());
                field.setStored(schemaField.isStored());
                field.setType(schemaField.getType());
                field.setCopyToText(schemaField.isCopyToText());
                field.setMultivaluated(schemaField.isMultivaluated());
                field.setBoost(schemaField.getBoost());
                field.setInSchema(true);

                String errorMessage = "El campo '".concat(fieldName)
                        .concat("' ya existe en el schema.xml. Se usarn los valores definidos en l");
                field.setError(errorMessage);
            }
            // otherwise checks if exists a field
            else if (selectedColumn != null) {
                selectedColumn.setIndexed(field.isIndexed());
                selectedColumn.setStored(field.isStored());
                selectedColumn.setType(field.getType());
                selectedColumn.setCopyToText(field.isCopyToText());
                selectedColumn.setMultivaluated(field.isMultivaluated());
                selectedColumn.setBoost(field.getBoost());
                field.setError(selectedColumn.getError());
            } else {
                // reset errors and vars
                field.setError(null);
                field.setInSchema(false);
            }

            // checks field name
            if (StringUtils.isEmpty(fieldName)) {
                String errorMessage = "No ha especificado nombre para el campo";
                field.setError(errorMessage);
            } else if (!Utils.isValidName(fieldName)) {
                String errorMessage = "Nombre del campo invlido: ".concat(fieldName);
                field.setError(errorMessage);
            }

            // checks type
            if (StringUtils.isEmpty(field.getType())) {
                String errorMessage = "No ha especificado tipo para el campo '" + fieldName + "'";
                field.setError(errorMessage);
            }

            // checks boost
            String fieldBoost = field.getBoost();
            if (!StringUtils.isEmpty(fieldBoost) && !Utils.isValidDouble(fieldBoost)) {
                String errorMessage = "El peso del campo '" + fieldName + "' es invlido";
                field.setError(errorMessage);
            }
        }
    }

    private boolean tableHasDuplicatedFields(GeosearchTableVO table) {
        boolean duplicatedOnTable = false;
        Set<String> fieldNames = new HashSet<String>();
        for (GeosearchFieldVO field : table.getFields()) {
            String fieldName = Utils.getFieldName(field);
            if (fieldNames.contains(fieldName)) {
                duplicatedOnTable = true;
                break;
            }
            fieldNames.add(fieldName);
        }
        return duplicatedOnTable;
    }

    private GeosearchFieldVO getSelectedColumn(String fieldName, Table tableOwn) {
        GeosearchFieldVO schemaField = null;

        table_loop: for (GeosearchTableVO table : tables) {
            if (table.getTable().equals(tableOwn)) {
                continue table_loop;
            }
            List<GeosearchFieldVO> fields = table.getFields();
            for (GeosearchFieldVO field : fields) {
                String currentFieldName = Utils.getFieldName(field);
                if (currentFieldName.equals(fieldName)) {
                    schemaField = field;
                    String errorMessage = "Ya existe un campo con el nombre '".concat(fieldName)
                            .concat("' en la tabla '").concat(table.getTable().getName())
                            .concat("'. Se sobreescribirn las propiedades que se definan para este campo");
                    schemaField.setError(errorMessage);
                    break table_loop;
                }
            }
        }

        return schemaField;
    }

    private GeosearchFieldVO getSchemaField(String fieldName) {
        GeosearchFieldVO schemaField = null;

        for (GeosearchFieldVO field : schemaFields) {
            if (field.getName().equals(fieldName)) {
                schemaField = field;
                break;
            }
        }

        return schemaField;
    }

    /**
     * @return the url
     */
    public String getUrl() {
        return PanelSettings.geosearchMaster.getUrl();
    }

    /**
     * @return the tables
     */
    public List<GeosearchTableVO> getTables() {
        return tables;
    }

    /**
     * @param tables the tables to set
     */
    public void setTables(List<GeosearchTableVO> tables) {
        this.tables = tables;
    }

    /**
     * @return the geosearchTypes
     */
    public List<String> getGeosearchTypes() {
        return geosearchTypes;
    }

    /**
     * @param geosearchTypes the geosearchTypes to set
     */
    public void setGeosearchTypes(List<String> geosearchTypes) {
        this.geosearchTypes = geosearchTypes;
    }

    /**
     * @return the tableIndex
     */
    public int getTableIndex() {
        return tableIndex;
    }

    /**
     * @param tableIndex the tableIndex to set
     */
    public void setTableIndex(int tableIndex) {
        overrideDuplicatedFields();

        this.tableIndex = tableIndex;
        Table selectedTable = tables.get(tableIndex).getTable();
        this.wscontroller.setDataBase(selectedTable.getSchema().getDataBase());
        this.wscontroller.loadSchemas();
        this.wscontroller.setSchema(selectedTable.getSchema());
        this.wscontroller.loadTables();
        this.wscontroller.setTable(selectedTable);
    }

    /**
     * @return the core
     */
    public String getCore() {
        return core;
    }

    /**
     * @param core the core to set
     */
    public void setCore(String core) {
        this.core = core;
    }

    /**
     * @return the cores
     */
    public List<String> getCores() {
        return cores;
    }

    /**
     * @param cores the cores to set
     */
    public void setCores(List<String> cores) {
        this.cores = cores;
    }

    /**
     * @return the newTable
     */
    public boolean isNewTable() {
        return newTable;
    }

    /**
     * @param newTable the newTable to set
     */
    public void setNewTable(boolean newTable) {
        this.newTable = newTable;
    }

    /**
     * @return the schemaFields
     */
    public List<GeosearchFieldVO> getSchemaFields() {
        return schemaFields;
    }

    /**
     * @param schemaFields the schemaFields to set
     */
    public void setSchemaFields(List<GeosearchFieldVO> schemaFields) {
        this.schemaFields = schemaFields;
    }

    /**
     * @return the newCoreName
     */
    public String getNewCoreName() {
        return newCoreName;
    }

    /**
     * @param newCoreName the newCoreName to set
     */
    public void setNewCoreName(String newCoreName) {
        this.newCoreName = newCoreName;
    }

    /**
     * @return the newCore
     */
    public boolean isNewCore() {
        return newCore;
    }

    /**
     * @param newCore the newCore to set
     */
    public void setNewCore(boolean newCore) {
        this.newCore = newCore;
    }
}