Newer
Older
/*
* _____________________________________________________________________________
*
* 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.
*/
Sonia Zorba
committed
package it.inaf.ia2.tsm.webapp;
import it.inaf.ia2.tsm.ChildEntity;
import it.inaf.ia2.tsm.Column;
Sonia Zorba
committed
import it.inaf.ia2.tsm.webapp.env.CustomPartialResponseWriter;
import it.inaf.ia2.tsm.EntitiesContainer;
Sonia Zorba
committed
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;
Sonia Zorba
committed
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
Sonia Zorba
committed
import java.util.List;
Sonia Zorba
committed
import java.util.Objects;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
Sonia Zorba
committed
import org.apache.deltaspike.core.api.scope.WindowScoped;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @author Sonia Zorba {@literal <zorba at oats.inaf.it>}
*/
@Named("tapSchemaEditing")
Sonia Zorba
committed
@WindowScoped
public class TapSchemaEditingBean implements Serializable {
Sonia Zorba
committed
private static final long serialVersionUID = -6251004452688984277L;
Sonia Zorba
committed
private static final Logger LOG = LoggerFactory.getLogger(TapSchemaEditingBean.class);
private TapSchemaLoader tapSchemaLoader;
private TapSchema tapSchema;
private Schema selectedSchema;
private Table selectedTable;
private Column selectedColumn;
Sonia Zorba
committed
private boolean hasColumnsSorter;
private UpdateOperations updateOperations;
private EntitiesContainer currentAddingContainer;
Sonia Zorba
committed
private List<AddableItem> currentAddables;
private boolean addAlsoAllChildren;
Sonia Zorba
committed
@Inject
private SearchUCDDialog searchUCDDialog;
public Schema getSelectedSchema() {
return selectedSchema;
}
public Table getSelectedTable() {
return selectedTable;
}
public Column getSelectedColumn() {
return selectedColumn;
}
public VOUnitValidator getVoUnitValidator() {
return voUnitValidator;
}
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
public void setSelectedSchema(Schema selectedSchema) {
this.selectedSchema = selectedSchema;
if (selectedSchema == null) {
setSelectedTable(null);
} else {
List<Table> 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<Column> columns = selectedTable.getAddedOrRemovedChildren();
if (columns.isEmpty()) {
setSelectedColumn(null);
} else {
setSelectedColumn(columns.get(0));
}
}
}
public void setSelectedColumn(Column selectedColumn) {
this.selectedColumn = selectedColumn;
}
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 isShowWarning(String key) {
Sonia Zorba
committed
if (selectedColumn == null) {
return false;
}
EntityProperty dataTypeProp = selectedColumn.getProperty(key);
if (dataTypeProp.getDefaultValue() == null) {
return false;
}
Sonia Zorba
committed
return !Objects.equals(dataTypeProp.getDefaultValue(), dataTypeProp.getValue());
}
Sonia Zorba
committed
public static class AddableItem implements Serializable {
Sonia Zorba
committed
private static final long serialVersionUID = 2732253307571391962L;
private final String name;
Sonia Zorba
committed
private boolean selected;
Sonia Zorba
committed
AddableItem(String name) {
this.name = name;
}
Sonia Zorba
committed
public String getName() {
return name;
}
Sonia Zorba
committed
public boolean isSelected() {
return selected;
}
Sonia Zorba
committed
public void setSelected(boolean selected) {
this.selected = selected;
}
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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<Schema> schemas = tapSchema.getAddedOrRemovedChildren();
if (!schemas.isEmpty()) {
selectedSchema = schemas.get(0);
List<Table> tables = selectedSchema.getAddedOrRemovedChildren();
if (!tables.isEmpty()) {
selectedTable = tables.get(0);
if (!columns.isEmpty()) {
selectedColumn = columns.get(0);
}
}
}
Sonia Zorba
committed
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;
}
return "credentialsEditing.xhtml?faces-redirect=true";
public void undoRemove(ChildEntity entity) throws SQLException {
// re-add what was removed
entity.getParent().addChild(entity.getName());
Sonia Zorba
committed
}
public EntitiesContainer getCurrentAddingContainer() {
Sonia Zorba
committed
return currentAddingContainer;
}
public void openAddablesModal(EntitiesContainer<?> currentAddingContainer) {
this.addAlsoAllChildren = false;
Sonia Zorba
committed
this.currentAddingContainer = currentAddingContainer;
this.currentAddables = new ArrayList<>();
for (String name : currentAddingContainer.getAddableChildrenNames()) {
if (currentAddingContainer instanceof TapSchema) {
if (name.equals(tapSchema.getRealSchemaName(tapSchema.getName()))
&& tapSchema.getChild(tapSchema.getName()) != null) {
// we can manually add the TAP_SCHEMA schema into itself only if it has been accidentally removed
// Note: adding of TAP_SCHEMA schema should be fully managed by TASMAN during the consistency checking phase.
continue;
}
if (name.equals(tapSchema.getRealSchemaName(tapSchema.getIvoaSchemaName()))) {
// Ivoa schema adding/removal is fully managed by TASMAN
continue;
}
Sonia Zorba
committed
currentAddables.add(new AddableItem(name));
}
}
Sonia Zorba
committed
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);
}
}
}
Sonia Zorba
committed
public void addSelected() throws SQLException {
TapSchemaEntity lastAddedEntity = null;
boolean canAddChildren = isCanAddChildren();
Sonia Zorba
committed
for (AddableItem item : currentAddables) {
if (item.isSelected()) {
lastAddedEntity = currentAddingContainer.addChild(item.getName());
if (lastAddedEntity != null && canAddChildren && addAlsoAllChildren) {
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);
Sonia Zorba
committed
}
}
}
Sonia Zorba
committed
public List<AddableItem> 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;
}
Sonia Zorba
committed
public void saveUCD() {
if (!FacesContext.getCurrentInstance().isValidationFailed()) {
if (searchUCDDialog.isManualInsertion()) {
selectedColumn.setValue("ucd", searchUCDDialog.getUCDManualText());
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));
Sonia Zorba
committed
}
public void displayUpdateOperations() {
updateOperations = new UpdateOperations(tapSchema);
Sonia Zorba
committed
}
Sonia Zorba
committed
public void openUCDDialog() throws Exception {
searchUCDDialog.setDefault();
String description = selectedColumn.getValue("description", String.class);
if (description != null && !description.isEmpty()) {
Sonia Zorba
committed
searchUCDDialog.setDescription(description);
searchUCDDialog.search();
Sonia Zorba
committed
}
}
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));
Sonia Zorba
committed
}
Sonia Zorba
committed
public void removeColumn(String name) {
selectedTable.removeChild(name);
Sonia Zorba
committed
if (selectedColumn != null) {
for (Column column : selectedTable.getAddedOrRemovedChildren()) {
if (column.getName().equals(selectedColumn.getName())) {
Sonia Zorba
committed
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 column.getStatus() != Status.TO_REMOVE && column.getStatus() != Status.REMOVED_NOT_PERSISTED;
Sonia Zorba
committed
public boolean isHasColumnsSorter() {
return hasColumnsSorter;
}
public void reload() {
if (tapSchema.exists()) {
tapSchemaLoader.edit();
} else {
}
* 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);
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
public List<Key> getVisibleKeys() {
List<Key> 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<KeyColumn>(key.getKeyColumns(), ", ") {
@Override
public String getStringValue(KeyColumn kc) {
return kc.getFromColumn();
}
}).getString();
}
public String formatTargetColumns(Key key) {
return (new TSMUtil.StringJoiner<KeyColumn>(key.getKeyColumns(), ", ") {
@Override
public String getStringValue(KeyColumn kc) {
return kc.getTargetColumn();
}
}).getString();
}
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
/**
* Returns the columns list sorting them using {@code column_index} if
* available.
*/
public List<Column> getColumns() {
Table table = getSelectedTable();
if (table == null) {
return null;
}
List<Column> columns = new ArrayList<>(table.getAddedOrRemovedChildren());
if (hasColumnsSorter) {
Collections.sort(columns, new Comparator<Column>() {
@Override
public int compare(Column column1, Column column2) {
Integer columnIndex1 = column1.getValue(Column.COLUMN_INDEX, Integer.class);
Integer columnIndex2 = column2.getValue(Column.COLUMN_INDEX, Integer.class);
if (columnIndex1 == null && columnIndex2 == null) {
// When column index is not specified use the column name for sorting
return column1.getName().compareToIgnoreCase(column2.getName());
}
// Columns with the column index must be shown before the ones which don't have it.
if (columnIndex1 != null && columnIndex2 == null) {
return -1;
}
if (columnIndex1 == null && columnIndex2 != null) {
return 1;
}
// Compare the column indexes if they are not null.
return columnIndex1.compareTo(columnIndex2);
}
});
}
return columns;
}