package com.temenos.interaction.core.entity; /* * #%L * interaction-core * %% * Copyright (C) 2012 - 2013 Temenos Holdings N.V. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; import org.joda.time.LocalDateTime; import org.joda.time.LocalTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.temenos.interaction.core.entity.vocabulary.Term; import com.temenos.interaction.core.entity.vocabulary.TermFactory; import com.temenos.interaction.core.entity.vocabulary.Vocabulary; import com.temenos.interaction.core.entity.vocabulary.terms.TermComplexGroup; import com.temenos.interaction.core.entity.vocabulary.terms.TermComplexType; import com.temenos.interaction.core.entity.vocabulary.terms.TermIdField; import com.temenos.interaction.core.entity.vocabulary.terms.TermListType; import com.temenos.interaction.core.entity.vocabulary.terms.TermMandatory; import com.temenos.interaction.core.entity.vocabulary.terms.TermRestriction; import com.temenos.interaction.core.entity.vocabulary.terms.TermRestriction.Restriction; import com.temenos.interaction.core.entity.vocabulary.terms.TermValueType; /** * Metadata class holding vocabularies used to describe an entity. */ public class EntityMetadata { private final static Logger logger = LoggerFactory.getLogger(EntityMetadata.class); private TermFactory termFactory = new TermFactory(); private String entityName; //Entity name private Vocabulary vocabulary = null; //Entity Vocabulary //Map of <Entity property, Vocabulary> private Map<String, Vocabulary> propertyVocabularies = new HashMap<String, Vocabulary>(); // Map of fully qualified property name to simple property name private Map<String, String> propertyNames = new HashMap<String, String>(); public EntityMetadata(String entityName) { this.entityName = entityName; } /** * Returns the entity name associated to this metadata * @return entity name */ public String getEntityName() { return entityName; } /** * Gets the vocabulary associated to this entity. * @return Vocabulary */ public Vocabulary getVocabulary() { return vocabulary; } /** * Sets the vocabulary associated to this entity. * @param vocabulary Entity vocabulary */ public void setVocabulary(Vocabulary vocabulary) { this.vocabulary = vocabulary; } /** * Gets the vocabulary associated to the specified entity property * @param propertyName Property name * @return Vocabulary */ public Vocabulary getPropertyVocabulary(String propertyName) { return propertyVocabularies.get(propertyName); } /** * Gets the list of vocalularyProperty names in this Vocabulary * @return The set of vocabulary names */ public Set<String> getPropertyVocabularyKeySet() { return propertyVocabularies.keySet(); } /** * Gets the top level properties. * I.e. names of properties which do not belong to any complex group. * @return The set of property names */ public Set<String> getTopLevelProperties() { Set<String> props = new HashSet<String>(); for(String prop : propertyVocabularies.keySet()) { Vocabulary voc = propertyVocabularies.get(prop); if(voc == null || voc.getTerm(TermComplexGroup.TERM_NAME) == null) { props.add(prop); } } return props; } /** * Sets the vocabulary for the specified entity property. * @param propertyName Property name * @param vocabulary Vocabulary */ public void setPropertyVocabulary(String propertyName, Vocabulary vocabulary) { setPropertyVocabulary(propertyName, vocabulary, new Stack<String>().elements()); } /** * Sets the vocabulary for the specified entity property. * @param propertyName Property name * @param vocabulary Vocabulary * @param collectionNames names of the collections this property belong to */ public void setPropertyVocabulary(String propertyName, Vocabulary vocabulary, Enumeration<String> collectionNames) { // build fully qualified group name String fullyQualifiedGroupName = ""; if (collectionNames.hasMoreElements()) { fullyQualifiedGroupName = collectionNames.nextElement() ; while(collectionNames.hasMoreElements()) { fullyQualifiedGroupName = fullyQualifiedGroupName + "." + collectionNames.nextElement(); } } // update the complex group term with the fully qualified group name Term complexGroupTerm = vocabulary.getTerm(TermComplexGroup.TERM_NAME); if (complexGroupTerm != null && !fullyQualifiedGroupName.isEmpty()) { complexGroupTerm = new TermComplexGroup(fullyQualifiedGroupName); vocabulary.setTerm(complexGroupTerm); } // build the fully qualified property name String fullyQualifiedPropertyName = propertyName; if (!fullyQualifiedGroupName.isEmpty()){ fullyQualifiedPropertyName = fullyQualifiedGroupName + "." + propertyName; } propertyVocabularies.put(fullyQualifiedPropertyName, vocabulary); propertyNames.put(fullyQualifiedPropertyName, propertyName); } /** * Checks whether a property is a complex type or not * @param propertyName The name of the property to check * @return Whether the property is a complex type or not */ public boolean isPropertyComplex( String propertyName ) { boolean complexType = false; Vocabulary voc = propertyVocabularies.get(propertyName); if(voc != null) { TermComplexType term = (TermComplexType) voc.getTerm(TermComplexType.TERM_NAME); complexType = term != null && term.isComplexType(); } return complexType; } /** * Check whether a property is a List type or not * @param propertyName The name of the property to check * @return Whether the property is a List type or not */ public boolean isPropertyList( String propertyName ) { boolean isList = false; Vocabulary voc = propertyVocabularies.get(propertyName); if(voc != null) { TermListType term = (TermListType) voc.getTerm(TermListType.TERM_NAME); isList = term != null && term.isListType(); } return isList; } /** * Returns the complex type group name of a property * @param propertyName The name of the property to process * @return The name of the complex type group - if any */ public String getPropertyComplexGroup( String propertyName ) { String complexGroup = ""; Vocabulary voc = propertyVocabularies.get(propertyName); if(voc != null) { TermComplexGroup term = (TermComplexGroup) voc.getTerm(TermComplexGroup.TERM_NAME); complexGroup = (term != null ? term.getComplexGroup() : ""); } return complexGroup; } private TermValueType getTermValueType (String propertyName) { TermValueType term = null; Vocabulary voc = propertyVocabularies.get(propertyName); if(voc != null) { term = (TermValueType) voc.getTerm(TermValueType.TERM_NAME); } return term; } /** * Checks whether a property is a text type or not * @param propertyName The name of the property to check * @return Whether the property is a text type or not */ public boolean isPropertyText( String propertyName ) { boolean textValue = true; TermValueType term = getTermValueType(propertyName); textValue = term == null || term.isText(); return textValue; } /** * Checks whether a property is a number type or not * @param propertyName The name of the property to check * @return Whether the property is a number type or not */ public boolean isPropertyNumber( String propertyName ) { boolean numberValue = false; TermValueType term = getTermValueType(propertyName); if(term != null) { numberValue = term.isNumber(); } return numberValue; } /** * Checks whether a property is a date type or not * @param propertyName The name of the property to check * @return Whether the property is a date type or not */ public boolean isPropertyDate( String propertyName ) { boolean dateType = false; TermValueType term = getTermValueType(propertyName); if(term != null) { dateType = term.isDate(); } return dateType; } /** * Checks whether a property is a timestamp type or not * @param propertyName The name of the property to check * @return Whether the property is a timestamp type or not */ public boolean isPropertyTimestamp( String propertyName ) { boolean timestampType = false; TermValueType term = getTermValueType(propertyName); if(term != null) { timestampType = term.isTimestamp(); } return timestampType; } /** * Checks whether a property is a time type or not * @param propertyName The name of the property to check * @return Whether the property is a time type or not */ public boolean isPropertyTime( String propertyName ) { boolean timeType = false; TermValueType term = getTermValueType(propertyName); if(term != null) { timeType = term.isTime(); } return timeType; } /** * Checks whether a property is a boolean type or not * @param propertyName The name of the property to check * @return Whether the property is a boolean type or not */ public boolean isPropertyBoolean( String propertyName ) { boolean booelanType = false; TermValueType term = getTermValueType(propertyName); if(term != null) { booelanType = term.isBoolean(); } return booelanType; } /** * Converts the field value in to a string (for TEXT and NUMBER types) * @param propertyName The name of the property to convert * @return The property value as a string */ public String getPropertyValueAsString( EntityProperty property ) { if (property == null){ return null; // a new ID ? } String propertyName = property.getFullyQualifiedName(); Object propertyValue = property.getValue(); return getPropertyValueAsString(propertyName, propertyValue); } /** * Converts the field value in to a string * @param propertyName Property name * @param propertyValue Property value * @return The property value as a string */ public String getPropertyValueAsString(String propertyName, Object propertyValue) { String value = ""; String termValueType = getTermValue(propertyName, TermValueType.TERM_NAME); if(propertyValue == null) { value = ""; } else if (propertyValue instanceof String) { return propertyValue.toString(); } else if(termValueType.equals(TermValueType.TEXT) || termValueType.equals(TermValueType.RECURRENCE) || termValueType.equals(TermValueType.ENCRYPTED_TEXT) || termValueType.equals(TermValueType.INTEGER_NUMBER) || termValueType.equals(TermValueType.NUMBER) || termValueType.equals(TermValueType.BOOLEAN)) { value = String.valueOf(propertyValue); } else if(termValueType.equals(TermValueType.TIMESTAMP) || termValueType.equals(TermValueType.DATE) || termValueType.equals(TermValueType.TIME)) { if (propertyValue instanceof LocalDateTime) { value = DateFormat.getDateTimeInstance().format(((LocalDateTime) propertyValue).toDateTime().toDate()); } else if (propertyValue instanceof LocalTime) { value = ((LocalTime) propertyValue).toString(); } else { value = DateFormat.getDateTimeInstance().format((Date) propertyValue); } } else if(termValueType.equals(TermValueType.ENUMERATION)) { if(propertyValue instanceof String[]) { String[] enumValues = (String[]) propertyValue; for(String item : enumValues) { value += value.isEmpty() ? item : "," + item; } } else { value = String.valueOf(propertyValue); } } else { logger.warn("Unable to return a text representation for field " + propertyName + " of type " + termValueType); } return value; } /** * Returns the value of a property vocabulary term. * If the term does not exist it returns it default value or null if it * does not have a default value. * @param propertyName Property name * @param termName Vocabulary term name * @return The term value as a string or null if not available */ public String getTermValue(String propertyName, String termName) { Vocabulary voc = getPropertyVocabulary(propertyName); if(voc != null) { Term term = voc.getTerm(termName); if(term != null) { return term.getValue(); } } return termFactory.getTermDefaultValue(termName); } /** * Returns the value of an entity vocabulary term. * If the term does not exist it returns it default value or null if it * does not have a default value. * @param termName Vocabulary term name * @return The term value as a string or null if not available */ public String getTermValue(String termName) { if(vocabulary != null) { Term term = vocabulary.getTerm(termName); if(term != null) { return term.getValue(); } } return termFactory.getTermDefaultValue(termName); } /** * Returns a list of fields which have the TermIdField vocabulary term * @return list of id fields */ public List<String> getIdFields() { List<String> idFields = new ArrayList<String>(); for(String propertyName : getPropertyVocabularyKeySet()) { if(getTermValue(propertyName, TermIdField.TERM_NAME).equals("true")) { idFields.add(propertyName); } } return idFields; } /** * Returns a new empty EntityProperty. * The value will be defaulted to according to the properties value type. * @param propertyName Entity property name * @return Entity property */ public EntityProperty createEmptyEntityProperty(String propertyName) { boolean isNullable = isPropertyNullable(propertyName); // If not nullable then initialise properly if (!isNullable) { String termValue = getTermValue(propertyName, TermValueType.TERM_NAME); if(termValue.equals(TermValueType.INTEGER_NUMBER)) { return new EntityProperty(propertyName, new Long(0)); } else if(termValue.equals(TermValueType.NUMBER)) { return new EntityProperty(propertyName, new Double(0.0)); } else if(termValue.equals(TermValueType.BOOLEAN)) { return new EntityProperty(propertyName, new Boolean(false)); } else if(termValue.equals(TermValueType.TIMESTAMP) || termValue.equals(TermValueType.DATE) || termValue.equals(TermValueType.TIME)) { return new EntityProperty(propertyName, new Date()); } else if(termValue.equals(TermValueType.ENUMERATION)) { String[] enumValues = {}; return new EntityProperty(propertyName, enumValues); } else { return new EntityProperty(propertyName, ""); } } else { // Leave it empty return new EntityProperty(propertyName, null); } } /** * Returns the simple property name to the passed in fully qualified property name. * If no such property exists in the entity metadata then <i>null</i> is returned. * @param fullyQualifiedPropertyName * @return simple property name */ public String getSimplePropertyName(String fullyQualifiedPropertyName) { return propertyNames.get(fullyQualifiedPropertyName); } /** * Method to find out if property is nullable * @param fullyQualifiedPropertyName * @return */ public boolean isPropertyNullable(String fullyQualifiedPropertyName) { return !(getTermValue(fullyQualifiedPropertyName, TermMandatory.TERM_NAME).equals("true") || getTermValue(fullyQualifiedPropertyName, TermIdField.TERM_NAME).equals("true")); } /** * Method to find out if property is display only * @param fullyQualifiedPropertyName * @return */ public boolean isPropertyDisplayOnly(String fullyQualifiedPropertyName) { return getTermValue(fullyQualifiedPropertyName, TermRestriction.TERM_NAME) .equals(Restriction.DISPLAYONLY.getValue()); } /** * Method to find out if property is filter only * @param fullyQualifiedPropertyName * @return */ public boolean isPropertyFilterOnly(String fullyQualifiedPropertyName) { return getTermValue(fullyQualifiedPropertyName, TermRestriction.TERM_NAME) .equals(Restriction.FILTEREONLY.getValue()); } }