/* * _____________________________________________________________________________ * * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of * Trieste INAF - IA2 Italian Center for Astronomical Archives * _____________________________________________________________________________ * * Copyright (C) 2016 Istituto Nazionale di Astrofisica * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License Version 3 as published by the * Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package it.inaf.ia2.tsm.webapp; import it.inaf.ia2.tsm.ChildEntity; import it.inaf.ia2.tsm.Column; import it.inaf.ia2.tsm.webapp.env.CustomPartialResponseWriter; import it.inaf.ia2.tsm.EntitiesContainer; import it.inaf.ia2.tsm.EntityProperty; import it.inaf.ia2.tsm.Key; import it.inaf.ia2.tsm.KeyColumn; import it.inaf.ia2.tsm.Schema; import it.inaf.ia2.tsm.Status; import it.inaf.ia2.tsm.TSMUtil; import it.inaf.ia2.tsm.Table; import it.inaf.ia2.tsm.TapSchema; import it.inaf.ia2.tsm.TapSchemaEntity; import it.inaf.ia2.tsm.UpdateOperations; import java.io.Serializable; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Objects; import javax.faces.context.FacesContext; import javax.inject.Inject; import javax.inject.Named; import org.apache.deltaspike.core.api.scope.WindowScoped; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author Sonia Zorba {@literal } */ @Named("tapSchemaEditing") @WindowScoped public class TapSchemaEditingBean implements Serializable { private static final long serialVersionUID = -6251004452688984277L; private static final Logger LOG = LoggerFactory.getLogger(TapSchemaEditingBean.class); @Inject private TapSchemaLoader tapSchemaLoader; private TapSchema tapSchema; private Schema selectedSchema; private Table selectedTable; private Column selectedColumn; private boolean hasColumnsSorter; private UpdateOperations updateOperations; private EntitiesContainer currentAddingContainer; private List currentAddables; private boolean addAlsoAllChildren; private VOUnitValidator voUnitValidator; @Inject private SearchUCDDialog searchUCDDialog; public Schema getSelectedSchema() { return selectedSchema; } public Table getSelectedTable() { return selectedTable; } public Column getSelectedColumn() { return selectedColumn; } public VOUnitValidator getVoUnitValidator() { return voUnitValidator; } public void setSelectedSchema(Schema selectedSchema) { this.selectedSchema = selectedSchema; if (selectedSchema == null) { setSelectedTable(null); } else { List tables = selectedSchema.getAddedOrRemovedChildren(); if (tables.isEmpty()) { setSelectedTable(null); } else { setSelectedTable(tables.get(0)); } } } public void setSelectedTable(Table selectedTable) { this.selectedTable = selectedTable; if (selectedTable == null) { setSelectedColumn(null); } else { List columns = selectedTable.getAddedOrRemovedChildren(); if (columns.isEmpty()) { setSelectedColumn(null); } else { setSelectedColumn(columns.get(0)); } } } public void setSelectedColumn(Column selectedColumn) { this.selectedColumn = selectedColumn; selectedColumnChanged(); } public UpdateOperations getUpdateOperations() { return updateOperations; } public String getUpdatedValues(TapSchemaEntity entity) { StringBuilder sb = new StringBuilder(); boolean first = true; for (String key : entity.getPropertiesKeys()) { if (entity.isChanged(key)) { if (!first) { sb.append(", "); } sb.append(key); first = false; } } return sb.toString(); } public boolean isShowWarningOnDataType() { if (selectedColumn == null) { return false; } EntityProperty dataTypeProp = selectedColumn.getProperty("datatype"); return !Objects.equals(dataTypeProp.getDefaultValue(), dataTypeProp.getValue()); } public static class AddableItem implements Serializable { private static final long serialVersionUID = 2732253307571391962L; private final String name; private boolean selected; AddableItem(String name) { this.name = name; } public String getName() { return name; } public boolean isSelected() { return selected; } public void setSelected(boolean selected) { this.selected = selected; } } public boolean toRemove(ChildEntity child) { return child.getStatus() == Status.REMOVED_NOT_PERSISTED || child.getStatus() == Status.TO_REMOVE; } public String getForeignKeyString(Column column) throws SQLException { Key foreignKey = column.getForeignKey(); if (foreignKey == null) { return null; } if (foreignKey.isVisible()) { String columnName = column.getName(); StringBuilder sb = new StringBuilder(); sb.append(foreignKey.getFromTableCompleteName()); sb.append("."); sb.append(columnName); sb.append(" -> "); for (KeyColumn keyColumn : foreignKey.getKeyColumns()) { if (keyColumn.getFromColumn().equals(columnName)) { sb.append(foreignKey.getTargetTableCompleteName()); sb.append(keyColumn.getTargetColumn()); break; } } return sb.toString(); } return null; } public TapSchema getTapSchema() { return tapSchema; } private void setupSelected() { selectedSchema = null; selectedTable = null; selectedColumn = null; List schemas = tapSchema.getAddedOrRemovedChildren(); if (!schemas.isEmpty()) { selectedSchema = schemas.get(0); List
tables = selectedSchema.getAddedOrRemovedChildren(); if (!tables.isEmpty()) { selectedTable = tables.get(0); List columns = selectedTable.getAddedOrRemovedChildren(); if (!columns.isEmpty()) { selectedColumn = columns.get(0); } } } selectedColumnChanged(); hasColumnsSorter = tapSchema.getTapSchemaModel().getTable(TapSchema.COLUMNS_TABLE).get(Column.COLUMN_INDEX) != null; } private void selectedColumnChanged() { if (selectedColumn == null) { voUnitValidator = new VOUnitValidator(null); } else { voUnitValidator = new VOUnitValidator(selectedColumn.getValue("unit", String.class)); } } public void setTapSchema(TapSchema tapSchema) { this.tapSchema = tapSchema; setupSelected(); } public void update() throws SQLException { tapSchema.save(); setupSelected(); } public SearchUCDDialog getSearchUCDDialog() { return searchUCDDialog; } public String back() { return "credentialsEditing.xhtml?faces-redirect=true"; } public void undoRemove(ChildEntity entity) throws SQLException { // re-add what was removed entity.getParent().addChild(entity.getName()); } public EntitiesContainer getCurrentAddingContainer() { return currentAddingContainer; } public void openAddablesModal(EntitiesContainer currentAddingContainer) { this.addAlsoAllChildren = false; this.currentAddingContainer = currentAddingContainer; this.currentAddables = new ArrayList<>(); for (String name : currentAddingContainer.getAddableChildrenNames()) { if (currentAddingContainer instanceof TapSchema && !tapSchema.exists() && name.equals(tapSchema.getName())) { // we can't add the TAP_SCHEMA into itself when it doesn't // created yet. continue; } currentAddables.add(new AddableItem(name)); } } public void checkAllEntities(boolean value) { for (AddableItem item : currentAddables) { item.setSelected(value); } } private void addAllChildren(TapSchemaEntity childEntity) throws SQLException { if (childEntity instanceof Schema) { Schema schema = (Schema) childEntity; for (String tableName : schema.getAddableChildrenNames()) { Table table = schema.addChild(tableName); addAllChildren(table); } } else if (childEntity instanceof Table) { Table table = (Table) childEntity; for (String column : table.getAddableChildrenNames()) { table.addChild(column); } } } public void addSelected() throws SQLException { TapSchemaEntity lastAddedEntity = null; boolean canAddChildren = isCanAddChildren(); for (AddableItem item : currentAddables) { if (item.isSelected()) { lastAddedEntity = currentAddingContainer.addChild(item.getName()); if (lastAddedEntity != null && canAddChildren) { addAllChildren(lastAddedEntity); } } } if (lastAddedEntity != null) { if (lastAddedEntity instanceof Schema) { setSelectedSchema((Schema) lastAddedEntity); } else if (lastAddedEntity instanceof Table) { setSelectedTable((Table) lastAddedEntity); } else if (lastAddedEntity instanceof Column) { setSelectedColumn((Column) lastAddedEntity); } } } public List getCurrentAddables() { return currentAddables; } public boolean isCanAddChildren() { if (currentAddingContainer == null) { return false; } return currentAddingContainer instanceof TapSchema || currentAddingContainer instanceof Schema; } public boolean isAddAlsoAllChildren() { return addAlsoAllChildren; } public void setAddAlsoAllChildren(boolean addAlsoAllChildren) { this.addAlsoAllChildren = addAlsoAllChildren; } public void saveUCD() { if (!FacesContext.getCurrentInstance().isValidationFailed()) { if (searchUCDDialog.isManualInsertion()) { selectedColumn.setValue("ucd", searchUCDDialog.getUCDManualText()); } else { selectedColumn.setValue("ucd", searchUCDDialog.getSelectedUCD()); } // New UCD is set and we can notify the client to close the UCD Search modal dialog. CustomPartialResponseWriter.getCurrentInstance().addCustomJSUpdate(String.valueOf(true)); } } public void displayUpdateOperations() { updateOperations = new UpdateOperations(tapSchema); } public void openUCDDialog() throws Exception { searchUCDDialog.setDefault(); String description = selectedColumn.getValue("description", String.class); if (description != null && !description.isEmpty()) { searchUCDDialog.setDescription(description); searchUCDDialog.search(); } } public void textInputChanged(TapSchemaEntity entity, String key) { final boolean isChanged = entity.isChanged(key); if (key.equals("unit")) { voUnitValidator = new VOUnitValidator(entity.getValue(key, String.class)); } CustomPartialResponseWriter.getCurrentInstance().addCustomJSUpdate(String.valueOf(isChanged)); } public void removeColumn(String name) { selectedTable.removeChild(name); if (selectedColumn != null) { for (Column column : selectedTable.getAddedOrRemovedChildren()) { if (column.getName().equals(selectedColumn.getName())) { break; } } } } public void undoRemoveColumn() throws SQLException { this.undoRemove(selectedColumn); for (Column column : selectedTable.getAddedOrRemovedChildren()) { if (column.getName().equals(selectedColumn.getName())) { break; } } } public boolean isSchemaRemovable(Schema schema) { return !schema.getName().equals(tapSchema.getName()) && !schema.getName().equals("ivoa"); } public boolean isColumnRemovable(Column column) { boolean parentSchemaRemovable = isSchemaRemovable(column.getParent().getParent()); if (!parentSchemaRemovable) { return !column.isMandatory(); } return true; } public boolean isHasColumnsSorter() { return hasColumnsSorter; } public void reload() { if (tapSchema.exists()) { tapSchemaLoader.edit(); } else { tapSchemaLoader.create(); } } /** * In TAP_SCHEMA 1.0 some columns have an integer data type and use 1 for * true and 0 for false, but we want to edit them using a JSF * booleanCheckbox, so we need this workaround for obtaining compatible * getters and setters. */ public Boolean getCompatibleBoolValue(String key) { Column column = getSelectedColumn(); if (column != null && column.getProperty(key) != null) { Object objValue = column.getValue(key); if (objValue == null) { return null; } if (objValue instanceof Integer) { return ((Integer) objValue) == 1; } return (Boolean) objValue; } return null; } public void setCompatibleBoolValue(String key, Boolean value) { Column column = getSelectedColumn(); if (column != null) { Class type = column.getPropertyType(key); if (type == Integer.class) { column.setValue(key, value ? 1 : 0); } else { column.setValue(key, value); } } } public Boolean getStd() { return getCompatibleBoolValue("std"); } public void setStd(Boolean value) { setCompatibleBoolValue("std", value); } public Boolean getPrincipal() { return getCompatibleBoolValue("principal"); } public void setPrincipal(Boolean value) { setCompatibleBoolValue("principal", value); } public List getVisibleKeys() { List keys = new ArrayList<>(); for (Key key : tapSchema.getAllKeys()) { if (key.isVisible()) { keys.add(key); } } return keys; } public String formatFromColumns(Key key) { return (new TSMUtil.StringJoiner(key.getKeyColumns(), ", ") { @Override public String getStringValue(KeyColumn kc) { return kc.getFromColumn(); } }).getString(); } public String formatTargetColumns(Key key) { return (new TSMUtil.StringJoiner(key.getKeyColumns(), ", ") { @Override public String getStringValue(KeyColumn kc) { return kc.getTargetColumn(); } }).getString(); } }