/* * Copyright (c) 2017 OBiBa. All rights reserved. * * This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.obiba.magma.support; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; import javax.validation.constraints.NotNull; import org.obiba.magma.AbstractAttributeAware; import org.obiba.magma.Attribute; import org.obiba.magma.Datasource; import org.obiba.magma.NoSuchValueTableException; import org.obiba.magma.Timestamps; import org.obiba.magma.Value; import org.obiba.magma.ValueTable; import org.obiba.magma.ValueTableWriter; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.ListMultimap; import com.google.common.collect.Sets; public abstract class AbstractDatasource extends AbstractAttributeAware implements Datasource { private final String name; private final String type; private final List<ValueTable> valueTables = new ArrayList<>(100); private final ListMultimap<String, Attribute> attributes = LinkedListMultimap.create(); protected AbstractDatasource(@NotNull String name, @NotNull String type) { Preconditions.checkNotNull(name, "name cannot be null"); Preconditions.checkNotNull(type, "type cannot be null"); this.name = name; this.type = type; } @Override public String getName() { return name; } @Override public String getType() { return type; } @Override public Set<ValueTable> getValueTables() { return Collections.unmodifiableSet(Sets.newHashSet(valueTables)); } @Override public boolean hasValueTable(String tableName) { for(ValueTable vt : getValueTables()) { if(vt.getName().equals(tableName)) { return true; } } return false; } @Override public boolean hasEntities(Predicate<ValueTable> predicate) { return Iterables.filter(getValueTables(), predicate).iterator().hasNext(); } @Override public ValueTable getValueTable(String tableName) throws NoSuchValueTableException { try { return getValueTables().stream() .filter(input -> tableName.equals(input.getName())) .findFirst() .get(); } catch(NoSuchElementException e) { throw new NoSuchValueTableException(getName(), tableName); } } @Override public void initialise() { Collection<DatasourceParsingException> parsingErrors = new ArrayList<>(); onInitialise(); for(String valueTable : getValueTableNames()) { ValueTable vt = initialiseValueTable(valueTable); try { Initialisables.initialise(vt); addValueTable(vt); } catch(DatasourceParsingException pe) { parsingErrors.add(pe); } } if(parsingErrors.size() > 0) { DatasourceParsingException parent = new DatasourceParsingException( "Errors while parsing tables of datasource: " + getName(), "DatasourceDefinitionErrors", getName()); parent.setChildren(parsingErrors); throw parent; } } @Override public void dispose() { Disposables.dispose(getValueTables()); onDispose(); } @NotNull @Override public ValueTableWriter createWriter(@NotNull String tableName, @NotNull String entityType) { throw new UnsupportedOperationException("createWriter() is not supported by datasource of type " + getType()); } @Override public void setAttributeValue(String name, Value value) { Attribute attribute = Attribute.Builder.newAttribute(name).withValue(value).build(); List<Attribute> attributesForName = getInstanceAttributes().get(name); if(attributesForName.isEmpty()) { attributesForName.add(attribute); } else { attributesForName.set(0, attribute); } } @Override public boolean canDropTable(String tableName) { return false; } @Override public void dropTable(@NotNull String tableName) { throw new UnsupportedOperationException("cannot drop table"); } @Override public boolean canRenameTable(String tableName) { return false; } @Override public void renameTable(String tableName, String newName) { throw new UnsupportedOperationException("cannot rename table"); } @Override public boolean canDrop() { return false; } @Override public void drop() { throw new UnsupportedOperationException("cannot drop datasource"); } @NotNull @Override public Timestamps getTimestamps() { return new UnionTimestamps(getValueTables()); } @Override protected ListMultimap<String, Attribute> getInstanceAttributes() { return attributes; } @Override public boolean isTransactional() { return false; } protected void addValueTable(ValueTable vt) { if(!valueTables.contains(vt)) valueTables.add(vt); } protected void removeValueTable(String tableName) { try { removeValueTable(getValueTable(tableName)); } catch (NoSuchValueTableException e) { // ignore } } protected void removeValueTable(ValueTable toRemove) { try { valueTables.remove(toRemove); Disposables.dispose(toRemove); } catch (NoSuchValueTableException e) { // ignore } } @SuppressWarnings("NoopMethodInAbstractClass") protected void onInitialise() { } @SuppressWarnings("NoopMethodInAbstractClass") protected void onDispose() { } @Override public int hashCode() { return Objects.hash(name); } @Override public boolean equals(Object obj) { if(this == obj) { return true; } if(obj == null || getClass() != obj.getClass()) { return false; } AbstractDatasource other = (AbstractDatasource) obj; return Objects.equals(name, other.name); } protected abstract Set<String> getValueTableNames(); protected abstract ValueTable initialiseValueTable(String tableName); }