if (sofaMappings != null) {
for (int s = 0; s < sofaMappings.length; s++) {
String componentKey = sofaMappings[s].getComponentKey();
ResourceSpecifier componentSpec = getComponentSpecifier(componentKey);
if (componentSpec == null) {
throw new ResourceInitializationException(
ResourceInitializationException.SOFA_MAPPING_HAS_UNDEFINED_COMPONENT_KEY,
new Object[] { componentKey, sofaMappings[s].getAggregateSofaName(), aggName,
getSourceUrlString() });
}
String componentSofaName = sofaMappings[s].getComponentSofaName();
if (componentSofaName == null) {
componentSofaName = CAS.NAME_DEFAULT_SOFA;
} else if (componentSpec instanceof AnalysisEngineDescription
&& !CAS.NAME_DEFAULT_SOFA.equals(componentSofaName)
&& !declaresSofa((AnalysisEngineDescription) componentSpec, componentSofaName)) {
throw new ResourceInitializationException(
ResourceInitializationException.SOFA_MAPPING_HAS_UNDEFINED_COMPONENT_SOFA,
new Object[] { componentKey, componentSofaName,
sofaMappings[s].getAggregateSofaName(), aggName, getSourceUrlString() });
}
String compoundKey = sofaMappings[s].getComponentKey() + "@/@"
+ sofaMappings[s].getComponentSofaName();
String aggSofaName = sofaMappings[s].getAggregateSofaName();
// check for double-mapping
String existingMapping = (String) sofamap.get(compoundKey);
if (existingMapping != null && !existingMapping.equals(aggSofaName)) {
throw new ResourceInitializationException(
ResourceInitializationException.SOFA_MAPPING_CONFLICT, new Object[] {
sofaMappings[s].getComponentSofaName(), sofaMappings[s].getComponentKey(),
aggName, existingMapping, aggSofaName, getSourceUrlString() });
} else {
sofamap.put(compoundKey, aggSofaName);
}
}
}
// Rules for SofAs:
// (1) Each component output sofa must be mapped to an aggregate output sofa
// (2) Each aggregate output sofa must be mapped to a component output sofa
// (3) Each component input sofa must be mapped to an aggregate input sofa OR a component output
// sofa
// (4) Each aggregate input sofa must be mapped to a component input sofa
// From (1) and (3) we derive that:
// Each component input sofa must be mapped to an aggregate input sofa OR an aggregate output
// sofa
// (which is easier to check)
// Exception: if aggregate contains a remote component, we cannot check that remote
// component's input or output sofas, so rules (2) and (4) cannot be checked.
boolean containsRemote = false;
Set<String> correctlyMappedAggregateOutputs = new HashSet<String>();
Set<String> correctlyMappedAggregateInputs = new HashSet<String>();
Iterator<Map.Entry<String, ResourceSpecifier>> iter;
try {
iter = getDelegateAnalysisEngineSpecifiers().entrySet().iterator();
} catch (InvalidXMLException e) {
throw new ResourceInitializationException(e);
}
while (iter.hasNext()) {
Map.Entry<String, ResourceSpecifier> entry = iter.next();
String componentKey = entry.getKey();
ResourceSpecifier delegateSpec = entry.getValue();
if (delegateSpec instanceof AnalysisEngineDescription) {
Capability[] caps = ((AnalysisEngineDescription) delegateSpec).getAnalysisEngineMetaData()
.getCapabilities();
for (int i = 0; i < caps.length; i++) {
// all component output sofas must be mapped to aggregate output sofas
String[] outputSofas = caps[i].getOutputSofas();
for (int j = 0; j < outputSofas.length; j++) {
String aggSofa = (String) sofamap.get(componentKey + "@/@" + outputSofas[j]);
if (aggSofa == null) // no declared mapping, name remains unchanged
{
aggSofa = outputSofas[j];
}
if (!capabilitiesContainSofa(aggSofa, true)) {
throw new ResourceInitializationException(
ResourceInitializationException.OUTPUT_SOFA_NOT_DECLARED_IN_AGGREGATE,
new Object[] { outputSofas[j], componentKey, aggName, getSourceUrlString() });
}
correctlyMappedAggregateOutputs.add(aggSofa);
}
// all component input sofas must be mapped to aggregate input OR output sofas
String[] inputSofas = caps[i].getInputSofas();
for (int j = 0; j < inputSofas.length; j++) {
String aggSofa = (String) sofamap.get(componentKey + "@/@" + inputSofas[j]);
if (aggSofa == null) // no declared mapping, name remains unchanged
{
aggSofa = inputSofas[j];
}
if (!capabilitiesContainSofa(aggSofa, false) && !capabilitiesContainSofa(aggSofa, true)) {
throw new ResourceInitializationException(
ResourceInitializationException.INPUT_SOFA_HAS_NO_SOURCE, new Object[] {
inputSofas[j], componentKey, aggName, getSourceUrlString() });
}
correctlyMappedAggregateInputs.add(aggSofa);
}
// also check default text sofa
String aggDefSofa = (String) sofamap.get(componentKey + "@/@" + CAS.NAME_DEFAULT_SOFA);
if (aggDefSofa != null) {
if (capabilitiesContainSofa(aggDefSofa, true)) {
correctlyMappedAggregateOutputs.add(aggDefSofa);
} else {
correctlyMappedAggregateInputs.add(aggDefSofa);
}
}
}
} // delegateSpec is not an AnalysisEngineDescription
else {
containsRemote = true;
}
}
if (!containsRemote) {
// check that all aggregate outputs and inputs were mapped correclty to
// component inputs/outputs
Capability[] caps = this.getAnalysisEngineMetaData().getCapabilities();
for (int i = 0; i < caps.length; i++) {
String[] sofas = caps[i].getOutputSofas();
for (int j = 0; j < sofas.length; j++) {
if (!correctlyMappedAggregateOutputs.contains(sofas[j])) {
throw new ResourceInitializationException(
ResourceInitializationException.AGGREGATE_SOFA_NOT_MAPPED, new Object[] {
sofas[j], aggName, getSourceUrlString() });
}
}
sofas = caps[i].getInputSofas();
for (int j = 0; j < sofas.length; j++) {
if (!correctlyMappedAggregateInputs.contains(sofas[j])) {
throw new ResourceInitializationException(
ResourceInitializationException.AGGREGATE_SOFA_NOT_MAPPED, new Object[] {
sofas[j], aggName, getSourceUrlString() });
}
}
}