package com.openMap1.mapper.query; import java.util.Hashtable; import java.util.Iterator; import org.eclipse.emf.ecore.EReference; import com.openMap1.mapper.AssocEndMapping; import com.openMap1.mapper.AssocMapping; import com.openMap1.mapper.MappingCondition; import com.openMap1.mapper.core.MapperException; import com.openMap1.mapper.util.ModelUtil; /** * class for a link association in a query * @author Robert * */ public class LinkAssociation extends QueryMappingUser{ private QueryClass startClass; public QueryClass startClass() {return startClass;} private QueryClass endClass; public QueryClass endClass() {return endClass;} private EReference ref; public EReference ref() {return ref;} private Hashtable<String,AssocMapping> mappings; /** * * @param startClass * @param ref * @param endClass */ public LinkAssociation(QueryClass startClass,EReference ref, QueryClass endClass, QueryParser parser) { super(parser); this.startClass = startClass; this.ref = ref; this.endClass = endClass; mappings = new Hashtable<String,AssocMapping>(); } /** * @return the full association name, as used in MDL association mappings * If the EReference has no opposite, this is just the EReference (role) name. * If it has an opposite, the full name is the two role names concatenated, * (in lexicographic order) with '|' between */ public String assocName() { EReference opposite = ref.getEOpposite(); if (opposite == null) return ref.getName(); else return ModelUtil.assocName(ref.getName(), opposite.getName()); } /** * @return the 'start end' 1 or 2 as used in MDL association mappings * If the EReference has no opposite, this is always 1. * If there is an opposite, return 2 only if the opposite role name comes first in the * association name. */ public int startEnd() { EReference opposite = ref.getEOpposite(); if (opposite == null) return 1; else if (assocName().startsWith(ref.getName() + "|")) return 1; else return 2; } /** * array form of link association ,for use in earlier query tools * @return */ public String[] arrayForm() { String[] array = new String[3]; array[0] = startClass.className(); array[1] = assocName(); array[2] = endClass.className(); return array; } /** * @return key for storing all link associations in a hashtable */ public String key() { return (startClass.identifier() + "_" + assocName() + endClass.identifier()); } /** * remember one association mapping for a data source * @param code * @param mapping */ public void setMapping(String code, AssocMapping mapping) { mappings.put(code,mapping); } /** * * @param code * @return one association mapping for a data source, or null if there is none */ public AssocMapping getMapping(String code) { return mappings.get(code); } /** * add all tables, columns and conditions to an SQLQuery to ensure it retrieves the smallest DOM * required to support a query */ public void buildQuery(SQLQuery query, String code) throws MapperException { // this link condition is core if the QueryClass it leads to is core boolean isCore = endClass.isCore(); AssocMapping mapping = getMapping(code); if (mapping != null) { // add a table for the association mapping String tName = getTableName(mapping); if (tName == null) throw new MapperException("No table for association mapping"); query.addTable(tName,isCore); // add columns and SQL conditions for any ValueConditions in the association mapping for (Iterator<MappingCondition> it = mapping.getMappingConditions().iterator();it.hasNext();) handleMappingCondition(it.next(),mapping,query,code,isCore); // association end mappings; mainly pick up cross-conditions for (int end = 0; end < 2; end++) { AssocEndMapping aem = mapping.getMappedEnd(end); for (Iterator<MappingCondition> it = aem.getMappingConditions().iterator();it.hasNext();) handleMappingCondition(it.next(),aem,query,code,isCore); } } } }