private void generateColumnSliceIfNeeded(CFMappingDef<?> cfMapDef) { if (cfMapDef.isColumnSliceRequired()) { Collection<PropertyMappingDefinition> propColl = cfMapDef.getAllProperties(); String[] columnNames = new String[cfMapDef.isPersistableEntity() ? propColl.size() : propColl.size() + 1]; Iterator<PropertyMappingDefinition> iter = propColl.iterator(); int pos = 0; while (iter.hasNext()) { columnNames[pos++] = iter.next().getColName(); } // if an inheritance hierarchy exists we need to add in the discriminator // column if (!cfMapDef.isPersistableEntity()) { columnNames[pos] = cfMapDef.getDiscColumn(); } cfMapDef.setSliceColumnNameArr(columnNames); } }
private <T> void validateDerivedClassInheritance(CFMappingDef<T> cfMapDef) { if (null == cfMapDef.getDiscValue()) { throw new HectorObjectMapperException("Base class " + cfMapDef.getCfBaseMapDef().getEffectiveClass().getName() + " requested single table inheritance, but this class, " + cfMapDef.getEffectiveClass().getName() + ", did not specify a " + DiscriminatorValue.class.getSimpleName() + " annotation"); } }
/** * Examine class hierarchy using {@link CFMappingDef} objects to discover the * given class' "base inheritance" class. A base inheritance class is * determined by {@link CFMappingDef#isBaseEntity()} * * @param <T> * * @param cfMapDef * @return returns the base in the ColumnFamily mapping hierarchy */ public <T> CFMappingDef<? super T> findBaseClassViaMappings(CFMappingDef<T> cfMapDef) { CFMappingDef<? super T> tmpDef = cfMapDef; CFMappingDef<? super T> cfSuperDef; while (null != (cfSuperDef = tmpDef.getCfSuperMapDef())) { if (cfSuperDef.isBaseEntity()) { return cfSuperDef; } tmpDef = cfSuperDef; } return null; }
private <T> void validatePersistableDerivedEntityClass(ClassCacheMgr cacheMgr, CFMappingDef<T> cfMapDef) { // save this class in the base class for reference during loading cfMapDef.getCfBaseMapDef().addDerivedClassMap(cfMapDef); }
public boolean isPersistableDerivedEntity() { return !isBaseEntity() && null != getDiscValue() && !isAbstract(); }
@Test public void testInheritanceOfEntity() { ClassCacheMgr cacheMgr = new ClassCacheMgr(); CFMappingDef<MyRedTestBean> cfMapDef = cacheMgr.initializeCacheForClass(MyRedTestBean.class); // 13 is valid when custom conversion of enumerations works again // don't like hard coding numbers into JUnits, but took easy way for now assertEquals(14, cfMapDef.getAllProperties().size()); assertNotNull(cfMapDef.getCfBaseMapDef()); assertEquals(MyRedTestBean.class, cfMapDef.getEffectiveClass()); assertEquals("TestBeanColumnFamily", cfMapDef.getEffectiveColFamName()); assertEquals("myType", cfMapDef.getDiscColumn()); assertEquals(DiscriminatorType.STRING, cfMapDef.getDiscType()); assertEquals("baseId", cfMapDef.getKeyDef().getIdPropertyMap().values().iterator().next() .getPropDesc().getName()); // check super class settings assertEquals( MyRedTestBean.class.getSuperclass(), cfMapDef.getCfSuperMapDef().getRealClass()); assertFalse( cfMapDef.getCfSuperMapDef().isColumnSliceRequired()); }
@Test public void testInheritanceWithMultiLevels() { ClassCacheMgr cacheMgr = new ClassCacheMgr(); CFMappingDef<Desk> cfMapDef = cacheMgr.initializeCacheForClass(Desk.class); CFMappingDef<Furniture> cfBaseMapDef = cacheMgr.getCfMapDef(Furniture.class, true); assertEquals(7, cfMapDef.getAllProperties().size()); assertNotNull(cfMapDef.getCfSuperMapDef()); assertNotNull(cfMapDef.getCfBaseMapDef()); assertEquals(Desk.class.getSuperclass(), cfMapDef.getCfSuperMapDef().getEffectiveClass()); assertEquals(Desk.class.getSuperclass().getSuperclass(), cfMapDef.getCfSuperMapDef() .getCfSuperMapDef() .getEffectiveClass()); assertEquals(cfBaseMapDef.getEffectiveColFamName(), cfMapDef.getEffectiveColFamName()); assertEquals("type", cfMapDef.getDiscColumn()); assertEquals("table_desk", cfMapDef.getDiscValue()); assertEquals(DiscriminatorType.STRING, cfMapDef.getDiscType()); assertEquals("id", cfMapDef.getKeyDef().getIdPropertyMap().values().iterator().next() .getPropDesc().getName()); }
public void testValidateDerivedClass() { CFMappingDef<MyTestBean> cfBaseMapDef = new CFMappingDef<MyTestBean>( MyTestBean.class); cfBaseMapDef.setInheritanceType(InheritanceType.SINGLE_TABLE); cfBaseMapDef.setDiscColumn("myType"); CFMappingDef<MyBlueTestBean> cfMapDef = new CFMappingDef<MyBlueTestBean>( MyBlueTestBean.class); cfMapDef.setCfBaseMapDef(cfBaseMapDef); cfMapDef.setDiscValue("blue"); InheritanceParserValidator val = new InheritanceParserValidator(); try { val.validateAndSetDefaults(null, cfMapDef); } catch (HectorObjectMapperException e) { fail(e.getMessage()); } }
try { Map<String, HColumn<String, byte[]>> colSet = new HashMap<String, HColumn<String, byte[]>>(); Collection<PropertyMappingDefinition> coll = cfMapDef.getAllProperties(); for (PropertyMappingDefinition md : coll) { Collection<HColumn<String, byte[]>> colColl = createColumnsFromProperty(obj, md); if (null != cfMapDef.getCfBaseMapDef()) { CFMappingDef<?> cfSuperMapDef = cfMapDef.getCfBaseMapDef(); String discColName = cfSuperMapDef.getDiscColumn(); DiscriminatorType discType = cfSuperMapDef.getDiscType(); createHColumn(discColName, convertDiscTypeToColValue(discType, cfMapDef.getDiscValue())));
@Test(expected = HectorObjectMapperException.class) public void testValidateDerivedClassMissingDiscriminatorValue() { ClassCacheMgr cacheMgr = new ClassCacheMgr(); CFMappingDef<MyTestBean> cfBaseMapDef = new CFMappingDef<MyTestBean>( MyTestBean.class); cfBaseMapDef.setInheritanceType(InheritanceType.SINGLE_TABLE); cfBaseMapDef.setDiscColumn("myType"); CFMappingDef<MyBlueTestBean> cfMapDef = new CFMappingDef<MyBlueTestBean>( MyBlueTestBean.class); cfMapDef.setCfSuperMapDef(cfBaseMapDef); cfMapDef.setCfBaseMapDef(cfBaseMapDef); InheritanceParserValidator val = new InheritanceParserValidator(); val.validateAndSetDefaults(cacheMgr, cfMapDef); fail("should have reported missing discriminator value annotation"); }
private <T> void validateSingleTableInheritance(CFMappingDef<T> cfMapDef) { // validating the base class in an inheritance hierarchy. must have a // discriminator column defined if (null == cfMapDef.getDiscColumn()) { throw new HectorObjectMapperException("Class, " + cfMapDef.getRealClass().getName() + ", requested single table inheritance, but you did not specify a " + DiscriminatorColumn.class.getSimpleName() + " annotation"); } // if it is abstract, cannot be instantiated and therefore should not have a // discriminator value defined if (cfMapDef.isAbstract() && null != cfMapDef.getDiscValue()) { throw new HectorObjectMapperException("Abstract class, " + cfMapDef.getRealClass().getName() + ", has an @" + DiscriminatorValue.class.getSimpleName() + " annotation, but cannot be instantiated"); } else if (!cfMapDef.isAbstract() && null == cfMapDef.getDiscValue()) { throw new HectorObjectMapperException("Class, " + cfMapDef.getEffectiveClass().getName() + ", is a part of inheritance hierarchy, but did not specify a " + DiscriminatorValue.class.getSimpleName() + " annotation. Should it be 'abstract'?"); } }
private <T> CFMappingDef<? extends T> determineClassType(CFMappingDef<T> cfMapDef, ColumnSlice<String, byte[]> slice) { if (null == cfMapDef.getInheritanceType()) { return cfMapDef; String discColName = cfMapDef.getDiscColumn(); DiscriminatorType discType = cfMapDef.getDiscType(); Map<Object, CFMappingDef<? extends T>> derivedClasses = cfMapDef.getDerivedClassMap(); if (null == derivedCfMapDef) { throw new RuntimeException("Cannot find derived class of " + cfMapDef.getEffectiveClass().getName() + " with discriminator value of " + discValue);
@Test public void testGetColFamMapDefByClass() { ClassCacheMgr cacheMgr = new ClassCacheMgr(); cacheMgr.initializeCacheForClass(MyTestBean.class); CFMappingDef<?> cfMapDef = cacheMgr.getCfMapDef(MyTestBean.class, false); assertNotNull(cfMapDef); assertEquals( "TestBeanColumnFamily", cfMapDef.getColFamName()); assertNotNull( "Column family not registered properly", cacheMgr.getCfMapDef("TestBeanColumnFamily", false)); assertEquals(MyTestBean.class, cfMapDef.getEffectiveClass()); assertEquals("did not find @Id properly", "baseId", cfMapDef.getKeyDef().getIdPropertyMap() .values().iterator().next() .getPropDesc().getName()); assertEquals("did not setup properties properly", ColorConverter.class, cfMapDef.getPropMapByColumnName("color").getConverter().getClass()); }
private <T> void validateDerivedEntityClass(ClassCacheMgr cacheMgr, CFMappingDef<T> cfMapDef) { findAndSetBaseClassViaMappings(cacheMgr, cfMapDef); if (null == cfMapDef.getCfBaseMapDef()) { throw new HectorObjectMapperException("@" + Table.class.getSimpleName() + " used by class, " + cfMapDef.getRealClass().getName() + ", " + " has already been specified by base class, " + cfMapDef.getCfBaseMapDef().getEffectiveClass().getName()); } }
@Test(expected = HectorObjectMapperException.class) public void testValidateMissingDiscriminatorValue() { CFMappingDef<MyTestBean> cfMapDef = new CFMappingDef<MyTestBean>(MyTestBean.class); cfMapDef.setInheritanceType(InheritanceType.SINGLE_TABLE); cfMapDef.setDiscColumn("myType"); InheritanceParserValidator val = new InheritanceParserValidator(); val.validateAndSetDefaults(null, cfMapDef); fail("should have reported missing discriminator value annotation"); }
cfMapDef = new CFMappingDef<T>(realClass); Class<T> effectiveType = cfMapDef.getEffectiveClass(); CFMappingDef<? super T> cfSuperMapDef = null; try { cfSuperMapDef = initializeCacheForClass(effectiveType.getSuperclass()); cfMapDef.setCfSuperMapDef(cfSuperMapDef); } catch (HomMissingEntityAnnotationException e) {
try { try { obj = cfMapDefInstance.getEffectiveClass().newInstance(); } catch (InstantiationException e) { throw new HectorObjectMapperException(cfMapDefInstance.getEffectiveClass().getName() + ", must have default constructor", e); PropertyMappingDefinition md = cfMapDefInstance.getPropMapByColumnName(colName); if (null != md && null != md.getPropDesc()) { if (!md.isCollectionType()) { else if (null != cfMapDef.getDiscColumn() && colName.equals(cfMapDef.getDiscColumn())) { continue; } else {
@Test public void testInheritanceOfNonEntity() { ClassCacheMgr cacheMgr = new ClassCacheMgr(); CFMappingDef<MyPurpleTestBean> cfMapDef = cacheMgr.initializeCacheForClass(MyPurpleTestBean.class); assertEquals(2, cfMapDef.getAllProperties().size()); assertNull(cfMapDef.getCfBaseMapDef()); assertEquals(MyPurpleTestBean.class, cfMapDef.getEffectiveClass()); }
private <T> void parseTableAnnotation(ClassCacheMgr cacheMgr, Table anno, CFMappingDef<T> cfMapDef) { CFMappingDef<?> tmpDef; // column family can only be mapped to one class (base class) if (null != (tmpDef = cacheMgr.getCfMapDef(anno.name(), false))) { throw new HectorObjectMapperException( "classes, " + cfMapDef.getEffectiveClass().getName() + " and " + tmpDef.getEffectiveClass().getName() + ", are both mapped to ColumnFamily, " + tmpDef.getEffectiveColFamName() + ". Can only have one Class/ColumnFamily mapping - if multiple classes can be derived from a single ColumnFamily, use @" + Inheritance.class.getSimpleName()); } cfMapDef.setColFamName(anno.name()); }
@Test(expected = HectorObjectMapperException.class) public void testValidateInvalidInheritanceType() { CFMappingDef<MyTestBean> cfMapDef = new CFMappingDef<MyTestBean>(MyTestBean.class); cfMapDef.setInheritanceType(InheritanceType.JOINED); InheritanceParserValidator val = new InheritanceParserValidator(); val.validateAndSetDefaults(null, cfMapDef); fail("should have found invalid inheritance type"); }