Package org.hibernate.ogm.options.navigation.impl

Source Code of org.hibernate.ogm.options.navigation.impl.OptionsContext

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*/
package org.hibernate.ogm.options.navigation.impl;

import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.hibernate.ogm.options.spi.Option;
import org.hibernate.ogm.options.spi.OptionsContainer;
import org.hibernate.ogm.options.spi.OptionsService.OptionsServiceContext;

/**
* Keeps track of all the options set using one or more invocations of the mapping API; All the options are separated in
* different contexts: global, per entity and per property. Instances of this class are maintained per session factory
* and/or per session by {@link org.hibernate.ogm.options.spi.OptionsService}.
* <p>
* This class is safe to be accessed from several threads at the same time.
*
* @author Davide D'Alto <davide@hibernate.org>
* @author Gunnar Morling
* @see org.hibernate.ogm.options.spi.OptionsService
*/
public class OptionsContext implements OptionsServiceContext {

  private final OptionsContainer globaloptions = new OptionsContainer();
  private final ConcurrentMap<Class<?>, OptionsContainer> optionsPerEntity = new ConcurrentHashMap<Class<?>, OptionsContainer>();
  private final ConcurrentMap<PropertyKey, OptionsContainer> optionsPerProperty = new ConcurrentHashMap<PropertyKey, OptionsContainer>();

  public void addGlobalOption(Option<?> option) {
    add( option, globaloptions );
  }

  public void addEntityOption(Class<?> entityType, Option<?> option) {
    OptionsContainer entityOptions = optionsPerEntity.get( entityType );

    if ( entityOptions == null ) {
      entityOptions = getAndCacheAnnotationBasedEntityOptions( entityType );
    }

    add( option, entityOptions );
  }

  public void addPropertyOption(Class<?> entityType, String propertyName, Option<?> option) {
    PropertyKey key = new PropertyKey( entityType, propertyName );
    OptionsContainer propertyOptions = optionsPerProperty.get( key );

    if ( propertyOptions == null ) {
      propertyOptions = getAndCacheAnnotationBasedPropertyOptions( key );
    }

    add( option, propertyOptions );
  }

  private void add(Option<?> option, OptionsContainer container) {
    //TODO only needed for SF-scoped context?
    synchronized ( container ) {
      container.add( option );
    }
  }

  @Override
  public OptionsContainer getGlobalOptions() {
    return copy( globaloptions );
  }

  @Override
  public OptionsContainer getEntityOptions(Class<?> entityType) {
    OptionsContainer entityOptions = optionsPerEntity.get( entityType );

    if (entityOptions == null ) {
      entityOptions = getAndCacheAnnotationBasedEntityOptions( entityType );
    }

    return copy( entityOptions );
  }

  @Override
  public OptionsContainer getPropertyOptions(Class<?> entityType, String propertyName) {
    PropertyKey key = new PropertyKey( entityType, propertyName );

    OptionsContainer propertyOptions = optionsPerProperty.get( key );

    if (propertyOptions == null ) {
      propertyOptions = getAndCacheAnnotationBasedPropertyOptions( key );
    }

    return copy( propertyOptions );
  }

  private OptionsContainer copy(OptionsContainer container) {
    //TODO only needed for SF-scoped context?
    synchronized ( container ) {
      return new OptionsContainer( container );
    }
  }

  /**
   * Retrieves a container with the annotation-based options for the given entity, adding the container to the cache.
   *
   * @param entityType the entity type for which to return the options
   * @return a container with the annotation-based options for the given entity, never {@code null}.
   */
  private OptionsContainer getAndCacheAnnotationBasedEntityOptions(Class<?> entityType) {
    OptionsContainer entityOptions = AnnotationProcessor.getEntityOptions( entityType );

    OptionsContainer cachedOptions = optionsPerEntity.putIfAbsent( entityType, entityOptions );
    if ( cachedOptions != null ) {
      entityOptions = cachedOptions;
    }

    return entityOptions;
  }

  /**
   * Retrieves a container with the annotation-based options for the given property, adding the container to the
   * cache.
   *
   * @param key the property for which to return the options
   * @return a container with the annotation-based options for the given property, never {@code null}.
   */
  private OptionsContainer getAndCacheAnnotationBasedPropertyOptions(PropertyKey key) {
    Map<PropertyKey, OptionsContainer> allPropertyOptions = AnnotationProcessor.getPropertyOptions( key.getEntity() );

    for ( Entry<PropertyKey, OptionsContainer> option : allPropertyOptions.entrySet() ) {
      optionsPerProperty.putIfAbsent( option.getKey(), option.getValue() );
    }

    OptionsContainer propertyOptions = optionsPerProperty.get( key );

    //cache an empty container in case the given property has no annotation based options
    if ( propertyOptions == null ) {
      propertyOptions = new OptionsContainer();
      OptionsContainer cachedOptions = optionsPerProperty.putIfAbsent( key, propertyOptions );
      if ( cachedOptions != null ) {
        propertyOptions = cachedOptions;
      }
    }

    return propertyOptions;
  }

  @Override
  public String toString() {
    return "OptionsContext [globaloptions=" + globaloptions + ", optionsPerEntity=" + optionsPerEntity + ", optionsPerProperty=" + optionsPerProperty + "]";
  }
}
TOP

Related Classes of org.hibernate.ogm.options.navigation.impl.OptionsContext

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.