/* * Hibernate OGM, Domain model persistence for NoSQL datastores * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.ogm.datastore.mongodb.dialect.impl; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import org.hibernate.ogm.datastore.document.association.spi.AssociationRow; import org.hibernate.ogm.datastore.document.association.spi.AssociationRow.AssociationRowAccessor; import org.hibernate.ogm.datastore.document.association.spi.AssociationRowFactory; import org.hibernate.ogm.datastore.document.association.spi.StructureOptimizerAssociationRowFactory; import org.bson.Document; /** * {@link AssociationRowFactory} which creates association rows based on the {@link Document} based representation used * in MongoDB. * * @author Gunnar Morling * @author Emmanuel Bernard <emmanuel@hibernate.org> */ public class MongoDBAssociationRowFactory extends StructureOptimizerAssociationRowFactory<Document> { public static final MongoDBAssociationRowFactory INSTANCE = new MongoDBAssociationRowFactory(); private MongoDBAssociationRowFactory() { super( Document.class ); } @Override protected Document getSingleColumnRow(String columnName, Object value) { Document dbObjectAsRow = new Document( ); MongoHelpers.setValue( dbObjectAsRow, columnName, value ); return dbObjectAsRow; } @Override protected AssociationRowAccessor<Document> getAssociationRowAccessor(String[] prefixedColumns, String prefix) { return prefix != null ? new MongoDBAssociationRowAccessor( prefixedColumns, prefix ) : MongoDBAssociationRowAccessor.INSTANCE; } private static class MongoDBAssociationRowAccessor implements AssociationRow.AssociationRowAccessor<Document> { private static final MongoDBAssociationRowAccessor INSTANCE = new MongoDBAssociationRowAccessor(); private final String prefix; private final List<String> prefixedColumns; public MongoDBAssociationRowAccessor() { this( null, null ); } public MongoDBAssociationRowAccessor(String[] prefixedColumns, String prefix) { this.prefix = prefix; if ( prefix != null ) { this.prefixedColumns = Arrays.asList( prefixedColumns ); } else { this.prefixedColumns = new ArrayList<String>( 0 ); } } @Override public Set<String> getColumnNames(Document row) { Set<String> columnNames = new HashSet<String>(); addColumnNames( row, columnNames, "" ); for ( String prefixedColumn : prefixedColumns ) { String unprefixedColumn = removePrefix( prefixedColumn ); if ( columnNames.contains( unprefixedColumn ) ) { columnNames.remove( unprefixedColumn ); columnNames.add( prefixedColumn ); } } return columnNames; } // only call if you have a prefix private String removePrefix(String prefixedColumn) { return prefixedColumn.substring( prefix.length() + 1 ); // prefix + "." } private void addColumnNames(Document row, Set<String> columnNames, String prefix) { for ( String field : row.keySet() ) { Object sub = row.get( field ); if ( sub instanceof Document ) { addColumnNames( (Document) sub, columnNames, MongoHelpers.flatten( prefix, field ) ); } else { columnNames.add( MongoHelpers.flatten( prefix, field ) ); } } } @Override public Object get(Document row, String column) { if ( prefixedColumns.contains( column ) ) { column = removePrefix( column ); } return MongoHelpers.getValueOrNull( row, column ); } } }