User Defined Entity Properties

Entity attributes are user-defined properties, and viewed in the same way as entity properites defined in Java classes. For example, a class Book may define properties: name and author. These properties are defined in Java classes and called Entity Properties. If a user needs to create a piano Book, the user may want to define additional attributes such as music style and whether it includes a audio CD. These attributes are defined by users and called Entity Attributes.

Define EntityAttr and Options

For an entity to support attributes, there must be a place to define attributes and store their values. By default, if an entity has a Hierarchy, the system will look for attribute definitions in its Hierarchy if the Hierarchy class implements EntityAttrSupport.

An EntityAttr has a name, display name, type and whether it is required. It can has a number of options. For example, Book attributes are defined in book hierarchy (category).


@Entity(name = "BookAttr")
@Table(name = "BookAttr")
@ParentType({BookAttrOption.class})
public class BookAttr extends EntityAttrBase {	
	private BookHierarchy bookHierarchy;
	
	@ParentEntity
	@ManyToOne
	@JoinColumn(nullable=false, name="bookHierarchyId")
	public BookHierarchy getBookHierarchy() {
		return bookHierarchy;
	}

	public void setBookHierarchy(BookHierarchy bookHierarchy) {
		this.bookHierarchy = bookHierarchy;
	}

	@Override
	@Column(nullable=false, length=20)
	public String getName() {
		return name;
	}
	
	@Override
	@Column(length=20)
	public String getDisplayName() {
		return displayName;
	}

	@Override
	@OneToMany(cascade={CascadeType.ALL}, orphanRemoval=true, fetch=FetchType.LAZY, 
		mappedBy=BookAttrOption.PROPERTY_ATTRIBUTE, targetEntity=BookAttrOption.class)
	@OrderBy(BookAttr.PROPERTY_SEQUENCE_NO + " ASC")
	public List<EntityAttrOption> getOptions() {
		return options;
	}
	
}


@Entity(name = "BookAttrOption")
@Table(name = "BookAttrOption")
public class BookAttrOption extends EntityAttrOptionBase {
	
	@ParentEntity
	@ManyToOne(targetEntity=BookAttr.class)
	@JoinColumn(nullable=false, name="bookAttrId")
	public EntityAttr getAttribute() {
		return attribute;
	}

	@Override
	@Column(nullable=false, length=20)
	public String getName() {
		return name;
	}
	
	@Override
	@Column(nullable=false, length=20)
	public String getValue() {
		return value;
	}

}

Book attributes are defined in book hierarchies.

public class BookHierarchy extends SimpleHierarchyEntity implements EntityAttrSupport {
	@Override
	@OneToMany(cascade={CascadeType.ALL}, orphanRemoval=true, fetch=FetchType.LAZY, 
		mappedBy="bookHierarchy", targetEntity=BookAttr.class)
	@OrderBy(BookAttr.PROPERTY_SEQUENCE_NO + " ASC")
	public List<EntityAttr> getEntityAttrs() {
		return bookAttrs;
	}
	
	public void setEntityAttrs(List<EntityAttr> bookAttrs) {
		this.bookAttrs = bookAttrs;
	}
}

Entity Attribute Values

An EntityAttrValue is used to store one attribute value. An entity type that implements EntityAttrValue can extend EntityAttrValueBase and define O/R mapping. For example,

public class BookAttrValue extends EntityAttrValueBase {
	
	private Book book;
	
	@ParentEntity
	@ManyToOne
	@JoinColumn(nullable=false, name="bookId")
	public Book getBook() {
		return book;
	}
	
	public void setBook(Book book) {
		this.book = book;
	}
	
	@Override
	@ManyToOne(targetEntity=BookAttr.class)
	@JoinColumn(nullable=false, name="bookAttrId")
	public EntityAttr getAttribute() {
		return attribute;
	}
	
	@Override
	@Column(nullable=false, length=20)
	public String getValue() {
		return value;
	}
	
}
An entity type that supports attribute values must implement EntityAttrValueSupport. For example,

public class Book extends PersistenceEntityBase implements 
	HierarchySupport<BookHierarchy>, EntityAttrValueSupport {
	private String name;
	private String author;
	private BookHierarchy hierarchy;

	...
	
	@ManyToOne
	@JoinColumn(name="hierarchy")
	public ProductHierarchy getHierarchy() {
		return hierarchy;
	}

	public void setHierarchy(ProductHierarchy hierarchy) {
		this.hierarchy = hierarchy;
	}
	
	@Override
	@OneToMany(cascade={CascadeType.ALL}, orphanRemoval=true, fetch=FetchType.LAZY, 
		mappedBy="book", targetEntity=BookAttrValue.class)
	public List<EntityAttrValue> getEntityAttrValues() {
		return this.attrValues;
	}

	public void setEntityAttrValues(List<EntityAttrValue> attrValues) {
		this.attrValues = attrValues;
	}
}

Inheritance

If entity attributes are defined in Hierarchy, they are inheritable by hierarchy. Entity attribute definitions will be inherited from its parent and ancestor Hirarchy. For example, Hierarchy MusicBook has a child hierarchy TextMusicBook.
MusicBook
   |  (instrument)
   |
TextMusicBook
      (grade)

The MusicBook defines an attribute called instrument, and the TextMusicBook defines an attribute called grade, inheriting the instrument attribute from its ancestor hierarchy.

If you create a Book under MusicBook, you can set value for instrument. If you create a Book under TextMusicBook, you can set values for instrument and grade.

If entity attributes are not defined in Hierarchy, then need to override the following method in its EntityBackingBean:


	@Override
	protected List<EntityAttr> getEntityAttrs(PersistenceDataBackingBean<T> backingBean, T entity) {

	}
	

Attribute Property Names

The property names of EntityProperty(s) for entity attributes start with attr_. For an attribute whose name is foo, its property name is attr_foo. attr_* in ViewConfig stands for all user-defined attributes of an entity type. For example,

<viewConfig>
	<propertiesToShow>name,attr_*,author</propertiesToShow>
	
	<propertyGrouping>
		<group name="attributes" nameLocalized="false" 
				position="2" layout="FLOW">attr_*</group>		
	</propertyGrouping>	
</viewConfig>