make CasserMappingRepository immutable for multi-threading env

This commit is contained in:
Albert Shift 2015-04-03 17:04:57 -07:00
parent f5c990d18f
commit e67bb3cd85
4 changed files with 117 additions and 80 deletions

View file

@ -36,6 +36,7 @@ import com.noorq.casser.core.tuple.Tuple6;
import com.noorq.casser.core.tuple.Tuple7;
import com.noorq.casser.mapping.CasserMappingEntity;
import com.noorq.casser.mapping.CasserMappingRepository;
import com.noorq.casser.mapping.MappingRepositoryBuilder;
import com.noorq.casser.mapping.MappingUtil;
import com.noorq.casser.mapping.value.ColumnValuePreparer;
import com.noorq.casser.mapping.value.ColumnValueProvider;
@ -57,13 +58,13 @@ public class CasserSession extends AbstractSessionOperations implements Closeabl
CasserSession(Session session,
String usingKeyspace,
boolean showCql,
CasserMappingRepository mappingRepository,
MappingRepositoryBuilder mappingRepositoryBuilder,
Executor executor,
boolean dropSchemaOnClose) {
this.session = session;
this.usingKeyspace = Objects.requireNonNull(usingKeyspace, "keyspace needs to be selected before creating session");
this.showCql = showCql;
this.mappingRepository = mappingRepository.setReadOnly();
this.mappingRepository = mappingRepositoryBuilder.build();
this.executor = executor;
this.dropSchemaOnClose = dropSchemaOnClose;

View file

@ -28,11 +28,10 @@ import com.datastax.driver.core.UserType;
import com.google.common.util.concurrent.MoreExecutors;
import com.noorq.casser.mapping.CasserEntityType;
import com.noorq.casser.mapping.CasserMappingEntity;
import com.noorq.casser.mapping.CasserMappingRepository;
import com.noorq.casser.mapping.MappingRepositoryBuilder;
import com.noorq.casser.mapping.value.ColumnValuePreparer;
import com.noorq.casser.mapping.value.ColumnValueProvider;
import com.noorq.casser.mapping.value.RowColumnValueProvider;
import com.noorq.casser.mapping.value.StatementColumnValuePreparer;
import com.noorq.casser.support.CasserException;
public class SessionInitializer extends AbstractSessionOperations {
@ -42,7 +41,7 @@ public class SessionInitializer extends AbstractSessionOperations {
private boolean showCql = false;
private Executor executor = MoreExecutors.sameThreadExecutor();
private CasserMappingRepository mappingRepository = new CasserMappingRepository();
private MappingRepositoryBuilder mappingRepository = new MappingRepositoryBuilder();
private boolean dropUnusedColumns = false;
private boolean dropUnusedIndexes = false;
@ -74,12 +73,12 @@ public class SessionInitializer extends AbstractSessionOperations {
@Override
public ColumnValueProvider getValueProvider() {
return new RowColumnValueProvider(mappingRepository);
throw new CasserException("not expected call");
}
@Override
public ColumnValuePreparer getValuePreparer() {
return new StatementColumnValuePreparer(mappingRepository);
throw new CasserException("not expected call");
}
public SessionInitializer showCql() {

View file

@ -16,92 +16,35 @@
package com.noorq.casser.mapping;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.UserType;
import com.noorq.casser.support.CasserException;
import com.google.common.collect.ImmutableMap;
import com.noorq.casser.support.CasserMappingException;
import com.noorq.casser.support.Either;
public class CasserMappingRepository {
private final ImmutableMap<String, UserType> userTypeMap;
private static final Optional<CasserEntityType> OPTIONAL_UDT = Optional.of(CasserEntityType.USER_DEFINED_TYPE);
private final Map<Class<?>, CasserMappingEntity> entityMap = new HashMap<Class<?>, CasserMappingEntity>();
private final ImmutableMap<Class<?>, CasserMappingEntity> entityMap;
private final Map<String, UserType> userTypeMap = new HashMap<String, UserType>();
private boolean readOnly = false;
public CasserMappingRepository setReadOnly() {
this.readOnly = true;
return this;
}
public void addUserType(String name, UserType userType) {
if (readOnly) {
throw new CasserException("read-only mode");
}
userTypeMap.putIfAbsent(name.toLowerCase(), userType);
public CasserMappingRepository(MappingRepositoryBuilder builder) {
userTypeMap = ImmutableMap.<String, UserType>builder()
.putAll(builder.getUserTypeMap())
.build();
entityMap = ImmutableMap.<Class<?>, CasserMappingEntity>builder()
.putAll(builder.getEntityMap())
.build();
}
public UserType findUserType(String name) {
return userTypeMap.get(name.toLowerCase());
}
public void add(Object dsl) {
add(dsl, Optional.empty());
}
public void add(Object dsl, Optional<CasserEntityType> type) {
if (readOnly) {
throw new CasserException("read-only mode");
}
Class<?> iface = MappingUtil.getMappingInterface(dsl);
if (!entityMap.containsKey(iface)) {
CasserMappingEntity entity = type.isPresent() ?
new CasserMappingEntity(iface, type.get()) :
new CasserMappingEntity(iface);
if (null == entityMap.putIfAbsent(iface, entity)) {
addUserDefinedTypes(entity.getMappingProperties());
}
}
}
private void addUserDefinedTypes(Collection<CasserMappingProperty> props) {
for (CasserMappingProperty prop : props) {
Either<DataType, IdentityName> type = prop.getColumnType();
if (type.isRight()) {
add(prop.getJavaType(), OPTIONAL_UDT);
}
}
}
public Collection<CasserMappingEntity> entities() {
return Collections.unmodifiableCollection(entityMap.values());
return entityMap.values();
}
public CasserMappingEntity getEntity(Class<?> iface) {
@ -114,5 +57,4 @@ public class CasserMappingRepository {
return entity;
}
}

View file

@ -0,0 +1,95 @@
/*
* Copyright (C) 2015 Noorq, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.noorq.casser.mapping;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.UserType;
import com.noorq.casser.support.Either;
public final class MappingRepositoryBuilder {
private static final Optional<CasserEntityType> OPTIONAL_UDT = Optional.of(CasserEntityType.USER_DEFINED_TYPE);
private final Map<Class<?>, CasserMappingEntity> entityMap = new HashMap<Class<?>, CasserMappingEntity>();
private final Map<String, UserType> userTypeMap = new HashMap<String, UserType>();
public CasserMappingRepository build() {
return new CasserMappingRepository(this);
}
public Collection<CasserMappingEntity> entities() {
return entityMap.values();
}
protected Map<Class<?>, CasserMappingEntity> getEntityMap() {
return entityMap;
}
protected Map<String, UserType> getUserTypeMap() {
return userTypeMap;
}
public void addUserType(String name, UserType userType) {
userTypeMap.putIfAbsent(name.toLowerCase(), userType);
}
public void add(Object dsl) {
add(dsl, Optional.empty());
}
public void add(Object dsl, Optional<CasserEntityType> type) {
Class<?> iface = MappingUtil.getMappingInterface(dsl);
if (!entityMap.containsKey(iface)) {
CasserMappingEntity entity = type.isPresent() ?
new CasserMappingEntity(iface, type.get()) :
new CasserMappingEntity(iface);
if (null == entityMap.putIfAbsent(iface, entity)) {
addUserDefinedTypes(entity.getMappingProperties());
}
}
}
private void addUserDefinedTypes(Collection<CasserMappingProperty> props) {
for (CasserMappingProperty prop : props) {
Either<DataType, IdentityName> type = prop.getColumnType();
if (type.isRight()) {
add(prop.getJavaType(), OPTIONAL_UDT);
}
}
}
}