/* * This is a common dao with basic CRUD operations and is not limited to any * persistent layer implementation * * Copyright (C) 2010 Imran M Yousuf (imyousuf@smartitengineering.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package com.smartitengineering.dao.impl.hbase.spi.impl; import com.google.inject.Inject; import com.google.inject.internal.Nullable; import com.google.inject.name.Named; import com.smartitengineering.dao.impl.hbase.spi.DomainIdInstanceProvider; import com.smartitengineering.dao.impl.hbase.spi.Externalizable; import com.smartitengineering.dao.impl.hbase.spi.FilterConfig; import com.smartitengineering.dao.impl.hbase.spi.FilterConfigs; import com.smartitengineering.dao.impl.hbase.spi.SchemaInfoProvider; import com.smartitengineering.domain.PersistentDTO; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.text.ParseException; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateFormatUtils; import org.apache.commons.lang.time.DateUtils; import org.apache.hadoop.hbase.util.Bytes; /** * * @author imyousuf */ public class SchemaInfoProviderImpl<T extends PersistentDTO, IdType> implements SchemaInfoProvider<T, IdType> { private String schemaNamespace, mainTableName; private byte[] versionColumnFamily, versionColumnQualifier; private boolean transactionalDomain; private Map<String, FilterConfig> filterConfigs; private long waitTime; private TimeUnit unit; @Inject private Class<IdType> idTypeClass; @Inject @Nullable private DomainIdInstanceProvider provider; public SchemaInfoProviderImpl() { filterConfigs = new HashMap<String, FilterConfig>(); } public Class<IdType> getIdTypeClass() { return idTypeClass; } public void setIdTypeClass(Class<IdType> idTypeClass) { this.idTypeClass = idTypeClass; } @Inject public void setBaseConfig(SchemaInfoProviderBaseConfig<T> config) { this.schemaNamespace = config.getSchemaNamespace(); this.mainTableName = config.getMainTableName(); this.transactionalDomain = config.isTransactionalDomain(); if (StringUtils.isNotBlank(config.getVersionColumnFamily())) { this.versionColumnFamily = Bytes.toBytes(config.getVersionColumnFamily()); } if (StringUtils.isNotBlank(config.getVersionColumnQualifier())) { this.versionColumnQualifier = Bytes.toBytes(config.getVersionColumnQualifier()); } } @Inject public void setUnit(@Named("unit") TimeUnit unit) { this.unit = unit; } @Inject public void setWaitTime(@Named("waitTime") Long waitTime) { this.waitTime = waitTime; } @Inject public void setFilterConfigs(FilterConfigs<T> configs) { this.filterConfigs = configs.getConfigs(); } public Map<String, FilterConfig> getFilterConfigs() { return Collections.unmodifiableMap(filterConfigs); } public void addFilterConfig(String propertyName, FilterConfig filterConfig) { this.filterConfigs.put(propertyName, filterConfig); } public FilterConfig removeFilterConfig(String propertyName) { return this.filterConfigs.remove(propertyName); } public void setFilterConfigs(Map<String, FilterConfig> filterConfigs) { this.filterConfigs.clear(); if (filterConfigs != null && !filterConfigs.isEmpty()) { this.filterConfigs.putAll(filterConfigs); } } public void setMainTableName(String mainTableName) { this.mainTableName = mainTableName; } public void setSchemaNamespace(String schemaNamespace) { this.schemaNamespace = schemaNamespace; } public void setTransactionalDomain(boolean transactionalDomain) { this.transactionalDomain = transactionalDomain; } @Override public byte[] getVersionColumnFamily() { return versionColumnFamily; } @Override public byte[] getVersionColumnQualifier() { return versionColumnQualifier; } @Override public long getWaitTime() { return waitTime; } @Override public TimeUnit getUnit() { return unit; } @Override public String getSchemaNamespace() { return schemaNamespace; } @Override public boolean isTransactionalDomain() { return transactionalDomain; } @Override public Map<String, Class> getTableNames(Object domainInstance) { throw new UnsupportedOperationException("Not supported yet."); } @Override public String getMainTableName() { return mainTableName; } @Override public FilterConfig getFilterConfig(String propertyName) { return filterConfigs.get(propertyName); } @Override public byte[] getRowIdFromRow(T instance) throws IOException { final Object id = instance.getId(); return getRowIdFromId((IdType) id); } @Override public byte[] getRowIdFromId(IdType id) throws IOException { final byte[] rowId; if (id instanceof Integer) { rowId = Bytes.toBytes((Integer) id); } else if (id instanceof String) { rowId = Bytes.toBytes((String) id); } else if (id instanceof Long) { rowId = Bytes.toBytes((Long) id); } else if (id instanceof Double) { rowId = Bytes.toBytes((Double) id); } else if (id instanceof Date) { rowId = Bytes.toBytes(DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(((Date) id))); } else if (id instanceof Externalizable) { final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); final DataOutputStream outputStream = new DataOutputStream(byteArrayOutputStream); ((Externalizable) id).writeExternal(outputStream); IOUtils.closeQuietly(outputStream); rowId = byteArrayOutputStream.toByteArray(); } else if (id != null) { final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); final ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(id); IOUtils.closeQuietly(objectOutputStream); IOUtils.closeQuietly(byteArrayOutputStream); rowId = byteArrayOutputStream.toByteArray(); } else { rowId = new byte[0]; } return rowId; } @Override public IdType getIdFromRowId(byte[] id) throws IOException, ClassNotFoundException { final Object idInstance; if (Externalizable.class.isAssignableFrom(idTypeClass)) { idInstance = provider.getInstance(idTypeClass); DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(id)); ((Externalizable) idInstance).readExternal(inputStream); } else if (Integer.class.isAssignableFrom(idTypeClass)) { idInstance = Bytes.toInt(id); } else if (String.class.isAssignableFrom(idTypeClass)) { idInstance = Bytes.toString(id); } else if (Long.class.isAssignableFrom(idTypeClass)) { idInstance = Bytes.toLong(id); } else if (Double.class.isAssignableFrom(idTypeClass)) { idInstance = Bytes.toDouble(id); } else if (Date.class.isAssignableFrom(idTypeClass)) { try { idInstance = DateUtils.parseDate(Bytes.toString(id), new String[]{DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT. getPattern()}); } catch (ParseException ex) { throw new IOException(ex); } } else { idInstance = (IdType) new ObjectInputStream(new ByteArrayInputStream(id)).readObject(); } return (IdType) idInstance; } }