Package org.hibernate.ogm.utils

Source Code of org.hibernate.ogm.utils.InvokedOperationsLoggingDialect

/*
* 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.utils;

import java.io.IOException;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.ogm.datastore.spi.DatastoreProvider;
import org.hibernate.ogm.dialect.batch.spi.InsertOrUpdateAssociationOperation;
import org.hibernate.ogm.dialect.batch.spi.InsertOrUpdateTupleOperation;
import org.hibernate.ogm.dialect.batch.spi.Operation;
import org.hibernate.ogm.dialect.batch.spi.OperationsQueue;
import org.hibernate.ogm.dialect.batch.spi.RemoveAssociationOperation;
import org.hibernate.ogm.dialect.batch.spi.RemoveTupleOperation;
import org.hibernate.ogm.dialect.impl.ForwardingGridDialect;
import org.hibernate.ogm.dialect.query.spi.BackendQuery;
import org.hibernate.ogm.dialect.query.spi.ClosableIterator;
import org.hibernate.ogm.dialect.spi.AssociationContext;
import org.hibernate.ogm.dialect.spi.GridDialect;
import org.hibernate.ogm.dialect.spi.TupleContext;
import org.hibernate.ogm.model.key.spi.AssociationKey;
import org.hibernate.ogm.model.key.spi.EntityKey;
import org.hibernate.ogm.model.key.spi.EntityKeyMetadata;
import org.hibernate.ogm.model.key.spi.RowKey;
import org.hibernate.ogm.model.spi.Association;
import org.hibernate.ogm.model.spi.Tuple;

/**
* A testing dialect wrapper which logs all the invoked {@link GridDialect} operations.
*
* @author Gunnar Morling
*/
public class InvokedOperationsLoggingDialect extends ForwardingGridDialect<Serializable> {

  /**
   * Path for the logging file to be created, relative to the current working directory.
   */
  private static final String PATH = "invocations.log";

  /**
   * Set to {@code true} if a log with all the ops and their parameters should be written into the file specified
   * above.
   */
  private final boolean writeFile = false;

  private int opIndex = 0;
  private Path file;
  private final List<String> operations = new ArrayList<String>();

  public InvokedOperationsLoggingDialect(DatastoreProvider provider) {
    super( TestHelper.getCurrentGridDialect( provider ) );

    if ( writeFile ) {
      resetFile();
    }
  }

  public List<String> getOperations() {
    return Collections.unmodifiableList( operations );
  }

  public void reset() {
    operations.clear();
    if ( writeFile ) {
      resetFile();
    }
  }

  @Override
  public Tuple getTuple(EntityKey key, TupleContext tupleContext) {
    Tuple tuple = super.getTuple( key, tupleContext );
    log( "getTuple", key.toString(), tuple != null ? tuple.toString() : "null" );
    return tuple;
  }

  @Override
  public Tuple createTuple(EntityKey key, TupleContext tupleContext) {
    Tuple tuple = super.createTuple( key, tupleContext );
    log( "createTuple", key.toString(), tuple != null ? tuple.toString() : "null" );
    return tuple;
  }

  @Override
  public void insertOrUpdateTuple(EntityKey key, Tuple tuple, TupleContext tupleContext) {
    super.insertOrUpdateTuple( key, tuple, tupleContext );
    log( "insertOrUpdateTuple", key.toString() + ", " + tuple.toString(), "VOID" );
  }

  @Override
  public void removeTuple(EntityKey key, TupleContext tupleContext) {
    super.removeTuple( key, tupleContext );
    log( "removeTuple", key.toString(), "VOID" );
  }

  @Override
  public Association getAssociation(AssociationKey key, AssociationContext associationContext) {
    Association association = super.getAssociation( key, associationContext );
    log( "getAssociation", key.toString(), toShortString( association ) );
    return association;
  }

  @Override
  public Association createAssociation(AssociationKey key, AssociationContext associationContext) {
    Association association = super.createAssociation( key, associationContext );
    log( "createAssociation", key.toString(), toShortString( association ) );
    return association;
  }

  @Override
  public void insertOrUpdateAssociation(AssociationKey key, Association association, AssociationContext associationContext) {
    super.insertOrUpdateAssociation( key, association, associationContext );
    log( "insertOrUpdateAssociation", key.toString() + ", " + toShortString( association ), "VOID" );
  }

  @Override
  public void removeAssociation(AssociationKey key, AssociationContext associationContext) {
    super.removeAssociation( key, associationContext );
    log( "removeAssociation", key.toString(), "VOID" );
  }

  @Override
  public boolean updateTupleWithOptimisticLock(EntityKey entityKey, Tuple oldLockState, Tuple tuple, TupleContext tupleContext) {
    boolean success = super.updateTupleWithOptimisticLock( entityKey, oldLockState, tuple, tupleContext );
    log( "updateTuple", entityKey.toString() + ", " + tuple.toString(), String.valueOf( success ) );
    return success;
  }

  @Override
  public boolean removeTupleWithOptimisticLock(EntityKey entityKey, Tuple oldLockState, TupleContext tupleContext) {
    boolean success = super.removeTupleWithOptimisticLock( entityKey, oldLockState, tupleContext );
    log( "removeTuple", entityKey.toString(), String.valueOf( success ) );
    return success;
  }

  @Override
  public Tuple createTuple(EntityKeyMetadata entityKeyMetadata, TupleContext tupleContext) {
    return super.createTuple( entityKeyMetadata, tupleContext );
  }

  @Override
  public void insertTuple(EntityKeyMetadata entityKeyMetadata, Tuple tuple, TupleContext tupleContext) {
    super.insertTuple( entityKeyMetadata, tuple, tupleContext );
    log( "insertTuple", entityKeyMetadata.toString() + ", " + tuple.toString(), "VOID" );
  }

  @Override
  public ClosableIterator<Tuple> executeBackendQuery(BackendQuery<Serializable> query, QueryParameters queryParameters) {
    ClosableIterator<Tuple> result = super.executeBackendQuery( query, queryParameters );
    log( "executeBackendQuery", query.toString() + ", " + queryParameters.toString(), "tbd." );
    return result;
  }

  @Override
  public void executeBatch(OperationsQueue queue) {
    OperationsQueue newQueue = new OperationsQueue();
    StringBuilder sb = new StringBuilder();

    if ( !queue.isClosed() ) {
      Operation operation = queue.poll();
      while ( operation != null ) {
        newQueue.add( operation );

        if ( operation instanceof InsertOrUpdateTupleOperation ) {
          sb.append( "InsertOrUpdateTuple(" ).append( ( (InsertOrUpdateTupleOperation) operation ).getEntityKey() ).append( " )" );
        }
        else if ( operation instanceof RemoveTupleOperation ) {
          sb.append( "RemoveTuple(" ).append( ( (RemoveTupleOperation) operation ).getEntityKey() ).append( " )" );
        }
        else if ( operation instanceof InsertOrUpdateAssociationOperation ) {
          sb.append( "InsertOrUpdateAssociation(" ).append( ( (InsertOrUpdateAssociationOperation) operation ).getAssociationKey() ).append( " )" );
        }
        else if ( operation instanceof RemoveAssociationOperation ) {
          sb.append( "RemoveAssociation(" ).append( ( (RemoveAssociationOperation) operation ).getAssociationKey() ).append( " )" );
        }

        operation = queue.poll();

        if ( operation != null ) {
          sb.append( ", " );
        }
      }
    }

    super.executeBatch( newQueue );

    log( "executeBatch", sb.toString(), "VOID" );
  }

  private void log(String operation, String parameters, String returnValue) {
    operations.add( operation );

    if ( !writeFile ) {
      return;
    }

    String line = opIndex + "\t| " + operation + "\t| " + parameters + "\t| " + returnValue + System.lineSeparator();
    try {
      Files.write( file, line.getBytes(), StandardOpenOption.APPEND );
    }
    catch (IOException e) {
      throw new RuntimeException( e );
    }

    opIndex++;
  }

  private String toShortString(Association association) {
    if ( association == null ) {
      return null;
    }

    StringBuilder sb = new StringBuilder( "Association[");

    Iterator<RowKey> rowKeys = association.getKeys().iterator();

    while ( rowKeys.hasNext() ) {
      RowKey rowKey = rowKeys.next();
      sb.append( toShortString( rowKey ) ).append( "=" ).append( toShortString( association.get( rowKey ) ) );

      if ( rowKeys.hasNext() ) {
        sb.append( ",\n" );
      }
    }

    sb.append( "]" );
    return sb.toString();
  }

  private String toShortString(RowKey rowKey) {
    final StringBuilder sb = new StringBuilder();
    sb.append( "(" );
    int i = 0;
    for ( String column : rowKey.getColumnNames() ) {
      sb.append( column ).append( "=" ).append( rowKey.getColumnValue( column ) );
      i++;
      if ( i < rowKey.getColumnNames().length ) {
        sb.append( ", " );
      }
    }
    sb.append( ")" );
    return sb.toString();
  }

  private String toShortString(Tuple tuple) {
    StringBuilder sb = new StringBuilder( "(");
    int i = 0;
    for ( String column : tuple.getColumnNames() ) {
      sb.append( column ).append( "=" ).append( tuple.get( column ) );
      i++;
      if ( i < tuple.getColumnNames().size() ) {
        sb.append( ", " );
      }
    }

    sb.append( ")" );
    return sb.toString();
  }

  private void resetFile() {
    file = Paths.get( PATH );
    try {
      if ( !Files.exists( file ) ) {
        file = Files.createFile( file );
      }
      Files.write( file, ("#\top\tparameters\tresult" + System.lineSeparator() ).getBytes(), StandardOpenOption.TRUNCATE_EXISTING );
    }
    catch (IOException e) {
      throw new RuntimeException( e );
    }
  }
}
TOP

Related Classes of org.hibernate.ogm.utils.InvokedOperationsLoggingDialect

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.