All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xdev.ui.MasterDetail Maven / Gradle / Ivy

package xdev.ui;

/*-
 * #%L
 * XDEV Application Framework
 * %%
 * Copyright (C) 2003 - 2020 XDEV Software
 * %%
 * This program 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 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 Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */


import java.util.HashMap;
import java.util.Map;

import xdev.util.StringUtils;
import xdev.vt.Cardinality;
import xdev.vt.EntityRelationship;
import xdev.vt.EntityRelationship.Entity;
import xdev.vt.EntityRelationships;
import xdev.vt.KeyValues;
import xdev.vt.VirtualTable;
import xdev.vt.VirtualTable.VirtualTableRow;
import xdev.vt.VirtualTableColumn;
import xdev.vt.VirtualTableException;


/**
 * Registry for the current used {@link MasterDetailHandler}.
 * 
 * @author XDEV Software
 */
public final class MasterDetail
{
	private MasterDetail()
	{
	}
	
	private static MasterDetailHandler	handler;
	
	
	/**
	 * Sets the new MasterDetailHandler which is used to manage the corporation
	 * between {@link MasterDetailComponent}s or a {@link Formular} and a
	 * {@link MasterDetailComponent}.
	 * 
	 * @param handler
	 *            the new {@link MasterDetailHandler}
	 */
	public static void setHandler(MasterDetailHandler handler)
	{
		MasterDetail.handler = handler;
	}
	
	
	private static MasterDetailHandler getHandler()
	{
		if(handler == null)
		{
			handler = new DefaultMasterDetailHandler();
		}
		
		return handler;
	}
	
	
	/**
	 * Connects two {@link MasterDetailComponent}s.
	 * 

* The detail is filled with the appropriate records depending on the * master's selection. *

* The maching master is selected if the detail's selection changes. * * @param master * the component which operates as master * @param detail * the component which operates as detail view * @throws MasterDetailException * if necessary properties like the linked {@link VirtualTable} * are not set or insufficient entity relation information is * available */ public static void connect(MasterDetailComponent master, MasterDetailComponent detail) throws MasterDetailException { getHandler().connect(master,detail); } /** * Connects a {@link MasterDetailComponent} with a {@link Formular}, meaning * the formular (detail) is filled with the current selected * record ( {@link VirtualTableRow}) of the master. * * @param master * the component which operates as master * @param detail * the {@link Formular} which operates as detail view * @throws MasterDetailException * if necessary properties like the linked {@link VirtualTable} * are not set or insufficient entity relation information is * available */ public static void connect(final MasterDetailComponent master, final Formular detail) { getHandler().connect(master,detail); } /** * @since 4.0 */ public static VirtualTableRow getMasterRow(VirtualTableRow detailRecord, VirtualTable master) throws MasterDetailException, VirtualTableException { return master.getRow(getPrimaryKeyValues(detailRecord,master)); } /** * @since 4.0 */ public static VirtualTableRow getMasterRow(VirtualTableRow detailRecord, VirtualTable master, EntityRelationship relation) throws MasterDetailException, VirtualTableException { return master.getRow(getPrimaryKeyValues(detailRecord,master,relation)); } /** * @since 4.0 */ public static VirtualTableRow getMasterRow(VirtualTableRow detailRecord, VirtualTable master, VirtualTableColumn... foreignKey) throws MasterDetailException, VirtualTableException { EntityRelationship relation = getRelation(detailRecord,master,foreignKey); return master.getRow(getPrimaryKeyValues(detailRecord,master,relation)); } /** * @since 4.0 */ public static EntityRelationship getRelation(VirtualTableRow detailRecord, VirtualTable master, VirtualTableColumn... foreignKey) throws MasterDetailException, VirtualTableException { VirtualTable detail = detailRecord.getVirtualTable(); VirtualTableColumn[] pkColumns = master.getPrimaryKeyColumns(); if(pkColumns.length == 0) { throw new MasterDetailException(master,detail,"no primary key defined in '" + master.getName() + "'"); } String[] pkColumnNames = VirtualTableColumn.getNamesOf(pkColumns); String[] fkColumnNames = VirtualTableColumn.getNamesOf(foreignKey); EntityRelationship relation = EntityRelationships.getModel().getRelationship( master.getName(),pkColumnNames,detail.getName(),fkColumnNames); if(relation == null) { throw new MasterDetailException(master,detail,"no relation found for " + master.getName() + "(" + StringUtils.concat(",",(Object[])pkColumnNames) + ")' - '" + detail.getName() + "(" + StringUtils.concat(",",(Object[])fkColumnNames) + ")'"); } return relation; } /** * @since 4.0 */ public static KeyValues getPrimaryKeyValues(VirtualTableRow detailRecord, VirtualTable master) throws MasterDetailException, VirtualTableException { VirtualTable detail = detailRecord.getVirtualTable(); VirtualTableColumn[] pkColumns = master.getPrimaryKeyColumns(); if(pkColumns.length == 0) { throw new MasterDetailException(master,detail,"no primary key defined in '" + master.getName() + "'"); } String[] pkColumnNames = VirtualTableColumn.getNamesOf(pkColumns); EntityRelationship relation = EntityRelationships.getModel().getRelationship( master.getName(),pkColumnNames,detail.getName()); if(relation == null) { throw new MasterDetailException(master,detail,"no foreign key for " + master.getName() + "(" + StringUtils.concat(",",(Object[])pkColumnNames) + ") found in '" + detail.getName() + "'"); } return getPrimaryKeyValues(detailRecord,master,relation); } /** * @since 4.0 */ public static KeyValues getPrimaryKeyValues(VirtualTableRow detailRecord, VirtualTable master, VirtualTableColumn... foreignKey) throws MasterDetailException, VirtualTableException { EntityRelationship relation = getRelation(detailRecord,master,foreignKey); return getPrimaryKeyValues(detailRecord,master,relation); } /** * @since 4.0 */ public static KeyValues getPrimaryKeyValues(VirtualTableRow detailRecord, VirtualTable master, EntityRelationship relation) throws MasterDetailException, VirtualTableException { VirtualTable detail = detailRecord.getVirtualTable(); Entity masterEntity = relation.getReferrer(master.getName()); if(masterEntity.getCardinality() != Cardinality.ONE) { throw new MasterDetailException(master,detail, "invalid master detail relation: master's cardinality = MANY"); } Map map = new HashMap(); Entity detailEntity = relation.getOther(masterEntity); int columnCount = relation.getColumnCount(); for(int i = 0; i < columnCount; i++) { String columnName = masterEntity.getColumnName(i); VirtualTableColumn masterColumn = master.getColumn(columnName); if(masterColumn == null) { VirtualTableException.throwColumnNotFound(master,columnName); } map.put(masterColumn.getName(),detailRecord.get(detailEntity.getColumnName(i))); } return new KeyValues(master,map); } /** * @since 4.0 */ public static KeyValues getForeignKeyValues(VirtualTableRow masterRecord, VirtualTable detail) throws MasterDetailException, VirtualTableException { VirtualTable master = masterRecord.getVirtualTable(); VirtualTableColumn[] pkColumns = master.getPrimaryKeyColumns(); int columnCount = pkColumns.length; if(columnCount == 0) { throw new MasterDetailException(master,detail,"no primary key defined in '" + master.getName() + "'"); } String[] pkColumnNames = VirtualTableColumn.getNamesOf(pkColumns); EntityRelationship relation = EntityRelationships.getModel().getRelationship( master.getName(),pkColumnNames,detail.getName()); if(relation == null) { throw new MasterDetailException(master,detail,"no foreign key for " + master.getName() + "(" + StringUtils.concat(",",(Object[])pkColumnNames) + ") found in '" + detail.getName() + "'"); } Entity masterEntity = relation.getReferrer(master.getName()); if(masterEntity.getCardinality() != Cardinality.ONE) { throw new MasterDetailException(master,detail, "invalid master detail relation: master's cardinality = MANY"); } Map map = new HashMap(); Entity detailEntity = relation.getOther(masterEntity); for(int i = 0; i < columnCount; i++) { String columnName = detailEntity.getColumnName(i); VirtualTableColumn detailColumn = detail.getColumn(columnName); if(detailColumn == null) { VirtualTableException.throwColumnNotFound(detail,columnName); } map.put(detailColumn.getName(),masterRecord.get(master.getColumnIndex(pkColumns[i]))); } return new KeyValues(detail,map); } static void updateForeignKeys(VirtualTable vt, KeyValues keyValues) throws VirtualTableException { String[] columns = keyValues.getColumnNames(); int cc = columns.length; int[] indices = new int[cc]; for(int c = 0; c < cc; c++) { indices[c] = vt.getColumnIndex(columns[c]); if(indices[c] == -1) { VirtualTableException.throwColumnNotFound(vt,columns[c]); } } int rc = vt.getRowCount(); for(int r = 0; r < rc; r++) { VirtualTableRow row = vt.getRow(r); for(int c = 0; c < cc; c++) { row.set(indices[c],keyValues.getValue(columns[c])); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy