
org.nuiton.topia.persistence.metadata.TopiaMetadataEntity Maven / Gradle / Ivy
Show all versions of topia-extension Show documentation
package org.nuiton.topia.persistence.metadata;
/*
* #%L
* ObServe Toolkit :: ToPIA Extension
* %%
* Copyright (C) 2017 - 2018 IRD, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* 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, see
* .
* #L%
*/
import com.google.common.base.MoreObjects;
import java.sql.Blob;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.topia.persistence.TopiaEntity;
/**
* Created on 03/01/16.
*
* @author Tony Chemit - [email protected]
* @since 3.0.1
*/
public class TopiaMetadataEntity {
private static final Log log = LogFactory.getLog(TopiaMetadataEntity.class);
/**
* L'entité parent (optionnelle).
*/
protected final String parent;
/**
* Le nom simple de l'entité (correspond au nom de l'énumération qui caractérise cette entité).
*/
protected final String type;
/**
* Le nom du schéma qui contient la table correspondant à l'entité.
*/
protected final String dbSchemaName;
/**
* Le nom de la table qui correspond à l'entité.
*/
protected final String dbTableName;
/**
* Le dictionnaire des associations simples (multiplicitié 1→n) (la clef est le nom de la propriété, la valeur son type).
*/
protected final Map oneToManyAssociations = new LinkedHashMap<>();
/**
* La liste des terminaisons des associations simples.
*
* Uniquement utilisé pour connaitre les colonnes physiques de la table sql.
*/
protected final Set oneToManyAssociationInverses = new TreeSet<>();
/**
* Le dictionnaire des associations inversées (la clef est le nom de la propriété, la valeur son type).
*/
protected final Map reversedAssociations = new LinkedHashMap<>();
/**
* Le dictionnaire des associations nm (multiplicitié n→m) (la clef est le nom de la propriété, la valeur son type).
*/
protected final Map manyToManyAssociations = new LinkedHashMap<>();
/**
* Le dictionnaire des compositions simples vers des entitées (la clef est le nom de la propriété, la valeur son type).
*/
protected final Map manyToOneAssociations = new LinkedHashMap<>();
/**
* Le dictionnaire des propriétés qui ne sont pas des entités (la clef est le nom de la propriété, la valeur son type).
*/
protected final Map properties = new LinkedHashMap<>();
/**
* La liste des propriétés de type {@link Blob}
*/
protected final Set blobProperties = new HashSet<>();
/**
* La liste des colomnes supplémentaires ajoutée.
*/
protected final Set extraColumnNames = new HashSet<>();
/**
* Le nom des colunnes correspondants aux propriétés de l'entité.
* Note: On ne conserve que les correspondances qui diffèrent du nom de la propriété.
*
* @see #getDbColumnName(String)
*/
protected final Map dbColumnsName = new LinkedHashMap<>();
/**
* Le nom des tables utilisées pour les associations nm.
*/
protected final Map dbManyToManyAssociationsTableName = new LinkedHashMap<>();
protected Set allDbColumnNames;
public TopiaMetadataEntity(String parent, String type, String dbSchemaName, String dbTableName) {
this.parent = parent;
this.type = type;
this.dbSchemaName = dbSchemaName;
this.dbTableName = dbTableName;
}
public String getType() {
return type;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TopiaMetadataEntity that = (TopiaMetadataEntity) o;
return Objects.equals(type, that.type);
}
@Override
public int hashCode() {
return Objects.hash(type);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("type", type)
.add("dbName", dbSchemaName + "." + dbTableName)
.toString();
}
public String getParent() {
return parent;
}
public String getDbSchemaName() {
return dbSchemaName;
}
public String getDbTableName() {
return dbTableName;
}
public Set getAllDbColumnNames() {
if (allDbColumnNames == null) {
allDbColumnNames = getProperties().keySet().stream()
.map(this::getDbColumnName)
.map(String::toLowerCase)
.collect(Collectors.toSet());
allDbColumnNames.addAll(getManyToOneAssociations().keySet().stream()
.map(this::getDbColumnName)
.map(String::toLowerCase)
.collect(Collectors.toSet()));
allDbColumnNames.addAll(getReversedAssociations().keySet().stream()
.map(this::getDbColumnName)
.map(String::toLowerCase)
.collect(Collectors.toSet()));
allDbColumnNames.addAll(getOneToManyAssociationInverses().stream()
.map(this::getDbColumnName)
.map(String::toLowerCase)
.collect(Collectors.toSet()));
allDbColumnNames.add(TopiaEntity.PROPERTY_TOPIA_ID.toLowerCase());
allDbColumnNames.add(TopiaEntity.PROPERTY_TOPIA_CREATE_DATE.toLowerCase());
allDbColumnNames.add(TopiaEntity.PROPERTY_TOPIA_VERSION.toLowerCase());
allDbColumnNames.addAll(extraColumnNames.stream().map(String::toLowerCase).collect(Collectors.toSet()));
}
return allDbColumnNames;
}
public Map getReversedAssociations() {
return reversedAssociations;
}
public Map getManyToManyAssociations() {
return manyToManyAssociations;
}
public Map getOneToManyAssociations() {
return oneToManyAssociations;
}
public Map getManyToOneAssociations() {
return manyToOneAssociations;
}
public Set getOneToManyAssociationInverses() {
return oneToManyAssociationInverses;
}
public Map getProperties() {
return properties;
}
public Set getExtraColumnNames() {
return extraColumnNames;
}
public Set getPrimitivePropertyNames(String primitiveType) {
Set names = new LinkedHashSet<>();
for (Map.Entry entry : properties.entrySet()) {
String propertyType = entry.getValue();
if (primitiveType.equals(propertyType)) {
names.add(entry.getKey());
}
}
return names;
}
public boolean withBlob() {
return !blobProperties.isEmpty();
}
public Set getBlobProperties() {
return blobProperties;
}
public Map getDbColumnsName() {
return dbColumnsName;
}
public String getDbColumnName(String propertyName) {
String dbColumnName = dbColumnsName.get(propertyName);
if (dbColumnName == null) {
dbColumnName = propertyName;
}
return dbColumnName;
}
public Map getDbManyToManyAssociationsTableName() {
return dbManyToManyAssociationsTableName;
}
public String getBdManyToManyAssociationTableName(String propertyName) {
return dbManyToManyAssociationsTableName.get(propertyName);
}
public void addOneToManyAssociation(TopiaMetadataEntity associationClazz, String name, String dbColumnName) {
log.debug(getType() + "/" + name + "(" + dbColumnName + ") →" + associationClazz.getType());
oneToManyAssociations.put(name, associationClazz.getType());
addDbColumnName(name, dbColumnName);
}
public void addExtraColumn(String extraColumn) {
extraColumnNames.add(extraColumn);
}
public void addOneToManyAssociationInverse(TopiaMetadataEntity associationClazz, String name, String dbColumnName) {
log.debug(getType() + "/" + name + "(" + dbColumnName + ") →" + associationClazz.getType());
oneToManyAssociationInverses.add(name);
addDbColumnName(name, dbColumnName);
}
public void addReversedAssociation(TopiaMetadataEntity associationClazz, String name, String dbColumnName) {
log.debug(getType() + "/" + name + "(" + dbColumnName + ") →" + associationClazz.getType());
reversedAssociations.put(name, associationClazz.getType());
addDbColumnName(name, dbColumnName);
}
public void addManyToManyAssociation(TopiaMetadataEntity associationClazz, String name, String dbColumnName, String dbManyToManyAssociationTableName, String reverseDbColumnName) {
log.debug(getType() + "/" + name + "(" + dbManyToManyAssociationTableName + ") →" + associationClazz.getType());
manyToManyAssociations.put(name, associationClazz.getType());
addDbColumnName(name, dbColumnName);
if (reverseDbColumnName!=null) {
addDbColumnName(dbManyToManyAssociationTableName, reverseDbColumnName);
}
dbManyToManyAssociationsTableName.put(name, dbManyToManyAssociationTableName);
}
public void addManyToOneAssociation(TopiaMetadataEntity associationClazz, String name, String dbColumnName) {
log.debug(getType() + "/" + name + "(" + dbColumnName + ") →" + associationClazz.getType());
manyToOneAssociations.put(name, associationClazz.getType());
addDbColumnName(name, dbColumnName);
}
public void addProperty(String name, String type, String dbColumnName) {
log.debug(getType() + "/" + name + "(" + dbColumnName + ") →" + type);
properties.put(name, type);
if (Blob.class.getName().equals(type)) {
blobProperties.add(name);
}
addDbColumnName(name, dbColumnName);
}
public void putAll(TopiaMetadataEntity metadataEntity) {
metadataEntity.getOneToManyAssociations().putAll(getOneToManyAssociations());
metadataEntity.getOneToManyAssociationInverses().addAll(getOneToManyAssociationInverses());
metadataEntity.getReversedAssociations().putAll(getReversedAssociations());
metadataEntity.getManyToManyAssociations().putAll(getManyToManyAssociations());
metadataEntity.getManyToOneAssociations().putAll(getManyToOneAssociations());
metadataEntity.getProperties().putAll(getProperties());
metadataEntity.getExtraColumnNames().addAll(getExtraColumnNames());
metadataEntity.getDbColumnsName().putAll(getDbColumnsName());
metadataEntity.getDbColumnsName().putAll(getDbManyToManyAssociationsTableName());
}
public void accept(TopiaMetadataModelVisitor visitor, TopiaMetadataModel metadataModel) {
visitor.visitEntityStart(metadataModel, this);
for (Map.Entry entry : reversedAssociations.entrySet()) {
String propertyName = entry.getKey();
String propertyType = entry.getValue();
visitor.visitReversedAssociation(metadataModel, this, propertyName, metadataModel.getEntity(propertyType));
}
for (Map.Entry entry : oneToManyAssociations.entrySet()) {
String propertyName = entry.getKey();
String propertyType = entry.getValue();
visitor.visitOneToManyAssociation(metadataModel, this, propertyName, metadataModel.getEntity(propertyType));
}
for (String propertyType : oneToManyAssociationInverses) {
visitor.visitOneToManyAssociationInverse(metadataModel, this, propertyType, metadataModel.getEntity(propertyType));
}
for (Map.Entry entry : manyToManyAssociations.entrySet()) {
String propertyName = entry.getKey();
String propertyType = entry.getValue();
visitor.visitManyToManyAssociation(metadataModel, this, propertyName, metadataModel.getEntity(propertyType));
}
for (Map.Entry entry : manyToOneAssociations.entrySet()) {
String propertyName = entry.getKey();
String propertyType = entry.getValue();
visitor.visitManyToOneAssociation(metadataModel, this, propertyName, metadataModel.getEntity(propertyType));
}
for (Map.Entry entry : properties.entrySet()) {
String propertyName = entry.getKey();
String propertyType = entry.getValue();
visitor.visitProperty(metadataModel, this, propertyName, propertyType);
}
visitor.visitEntityEnd(metadataModel, this);
}
public boolean withShell() {
return !(reversedAssociations.isEmpty() && oneToManyAssociations.isEmpty() && manyToManyAssociations.isEmpty());
}
private void addDbColumnName(String name, String dbColumnName) {
if (!name.equals(dbColumnName)) {
dbColumnsName.put(name, dbColumnName);
}
}
public boolean withEntities() {
return withShell() || !manyToOneAssociations.isEmpty();
}
}