package gw.exportimport uses gw.api.locale.DisplayKey uses gw.exportimport.resolver.ColumnDataResolver uses java.lang.IllegalArgumentException uses java.lang.IllegalStateException uses java.util.Collections uses java.util.Map uses java.util.Collection uses gw.api.extension.ExtensionInterfaces /** * ColumnInfo contains the metadata of a particular column (e.g. its type or the header etc.). */ @ReadOnly final class ColumnInfo { /** * Indicates that the column should be locked in an exported format */ var _locked : boolean as readonly Locked /** * The dotted path notation identifying the bean value to be exported and imported */ var _path : String as readonly Path /** * The header display key */ var _header : String as readonly Header /** * Indicates that this column is responsible for uniquely identifying * the base {@link KeyableBean} in which to work. * * This is required to to access the entity, but if not {@link Locked} and * with no value it can also be used to indicate that the entity is to be * created. */ var _flagEntityId : boolean as readonly FlagsEntityId /** * Indicates that this column is responsible for uniquely identifying * the parent {@link KeyableBean} in which to work (e.g. CPLocation in a CPBuilding). */ var _flagParentEntityId : boolean as readonly FlagsParentEntityId /** * Indicates the action to perform on the row (e.g. "Add" or "Delete" etc.) * */ var _flagsAction : boolean as readonly FlagsAction /** * The column type (e.g. "CovTerm" or "String" or "State" etc.) */ var _columnType : Type as readonly ColumnType /** * Specifies if the column belongs to a parent entity * (e.g. column belonging to location is a parent column on building entity) */ var _parentColumn : boolean as ParentColumn /** * Indicates whether the entity is required on import. */ var _flagRequiredForImport : boolean as readonly RequiredForImport /** * Indicates whether the column should be excluded while exporting a template. */ var _flagExcludeFromTemplate : boolean as readonly ExcludeFromTemplate /** * The ColumnInfos this ColumnInfo depends on. The Map keys define the contract between the ColumnInfo * and its related ColumnInfos. */ var _dependentOn : Map as readonly DependentOn /** * The String value that uniquely identifies this column description. */ property get ColumnIdentifier() : String { return Header } private construct(builder : Builder) { _header = builder._header _parentColumn = builder._parentColumn _flagsAction = builder._flagsAction _flagExcludeFromTemplate = builder._flagExcludeFromTemplate _flagRequiredForImport = builder._flagRequiredForImport if (not _flagsAction) { _locked = builder._locked _path = builder._path _columnType = builder._columnType _dependentOn = Collections.unmodifiableMap(builder._dependentOn) _flagEntityId = builder._flagsEntityIdentifier _flagParentEntityId = builder._flagsParentEntityIdentifier } } private construct(columnInfo : ColumnInfo) { _header = columnInfo._header _parentColumn = columnInfo._parentColumn _flagsAction = columnInfo._flagsAction _flagExcludeFromTemplate = columnInfo._flagExcludeFromTemplate _flagRequiredForImport = columnInfo._flagRequiredForImport if (not _flagsAction) { _locked = columnInfo._locked _path = columnInfo._path _columnType = columnInfo._columnType _dependentOn = Collections.unmodifiableMap(columnInfo._dependentOn) _flagEntityId = columnInfo._flagEntityId _flagParentEntityId = columnInfo._flagParentEntityId } } /** * Return a locked copy of the ColumnInfo with a path that is a copy * but with the specified root path prefix removed. * * @param rootPath The root prefix to be removed from the path. */ internal function copyLockedWithRootPathRemoved(rootPath : String) : ColumnInfo { var copy = new ColumnInfo(this) if ( this.Path.startsWith(rootPath) ) { copy._path = this.Path.substring(rootPath.length + 1) } copy._locked = true return copy } public static class Builder { var _locked : boolean = false var _path : String as readonly Path var _header : String var _columnType : Type var _parentColumn : boolean = false var _flagsEntityIdentifier : boolean = false var _flagsParentEntityIdentifier : boolean = false var _flagsAction : boolean = false var _flagRequiredForImport : boolean = false var _flagExcludeFromTemplate : boolean = false var _dependentOn : Map = {} var _dependentOnNames : Map = null final function locked(isLocked : boolean) : Builder { _locked = isLocked return this } final function path(aPath : String) : Builder { _path = aPath _flagsAction = false return this } final function header(aHeader : String) : Builder { _header = aHeader return this } final function columnType(columnType : Type) : Builder { _columnType = columnType return this } final function parentColumn() : Builder { _parentColumn = true return this } final function flagsEntityId() : Builder { _flagsEntityIdentifier = true return this } final function flagsParentEntityId() : Builder { _flagsParentEntityIdentifier = true return this } final function flagsAction() : Builder { _flagsAction = true _path = null _columnType = null _flagsEntityIdentifier = false _flagRequiredForImport = true return this } final function flagsRequiredForImport() : Builder { _flagRequiredForImport = true return this } final function flagsExcludeFromTemplate() : Builder { _flagExcludeFromTemplate = true return this } final function addDependent(purpose : String, columnInfo : ColumnInfo) : Builder { if ( _dependentOn == null ) { // lazy initialization... _dependentOn = {} } _dependentOn.put(purpose, columnInfo) return this } final function addDependentName(purpose : String, columnName : String) : Builder { if ( _dependentOnNames == null ) { // lazy initialization... _dependentOnNames = {} } _dependentOnNames.put(purpose, columnName) return this } final function hasDependentNames() : boolean { return ( _dependentOnNames != null ) && ! _dependentOnNames.Empty } final property get DependentNames() : Collection { return ( _dependentOnNames != null ) ? _dependentOnNames.Values : null } final function resolveDependents(dependentsMap : Map) : Builder { if ( _dependentOnNames != null ) { _dependentOnNames.eachKeyAndValue(\ purpose, name -> { var colInfo = dependentsMap.get(name) if ( colInfo == null ) { throw new IllegalArgumentException( DisplayKey.get("Import.Configuration.Errors.UnknownDependentColumn", name)) } addDependent(purpose, colInfo) _dependentOnNames.remove(purpose) }) } return this } function build() : ColumnInfo { if ( hasDependentNames() ) { throw new IllegalStateException("Must resolve all dependents before building") } return new ColumnInfo(this) } } override function equals(o : Object) : boolean { if (this === o) { return true } if (not (o typeis ColumnInfo)) { return false } var columnInfo = o as ColumnInfo if ( _flagsAction != columnInfo._flagsAction ) { return false } if (not (this._header == null ? columnInfo._header == null : this._header == columnInfo._header)) { return false } if (this._locked != columnInfo._locked) { return false } if (this._parentColumn != columnInfo._parentColumn) { return false } if (not (this._path == null ? columnInfo._path == null : this._path == columnInfo._path)) { return false } if (not (this._columnType == null ? columnInfo._columnType == null : this._columnType == columnInfo._columnType)) { return false } if (this._flagEntityId != columnInfo._flagEntityId) { return false } if (this._flagParentEntityId != columnInfo._flagParentEntityId) { return false } if (this._flagRequiredForImport != columnInfo._flagRequiredForImport) { return false } if (this._dependentOn != columnInfo._dependentOn) { return false } return true } override function hashCode() : int { var result = 17 result = 31 * result + (_header == null ? 0 : _header.hashCode()) result = 31 * result + (_flagsAction ? 1 : 0) result = 31 * result + (_locked ? 1 : 0) result = 31 * result + (_parentColumn ? 1 : 0) result = 31 * result + (_path == null ? 0 : _path.hashCode()) result = 31 * result + (_columnType == null ? 0 : _columnType.hashCode()) result = 31 * result + (_flagEntityId ? 1 : 0) result = 31 * result + (_flagParentEntityId ? 1 : 0) result = 31 * result + (_flagRequiredForImport ? 1 : 0) result = 31 * result + (_dependentOn == null ? 0 : _dependentOn.hashCode()) return result } property get Resolver() : ColumnDataResolver { return ExtensionInterfaces.IColumnDataResolverFactoryExtensions.Instance.createResolver(this) } }