     return outProxy[ports[0]]
   return outProxy
 
-checkWirePatternPreconditions = (component, config, input, output) ->
+checkWirePatternPreconditions = (config, input, output) ->
   # First check for required params
-  paramsMet = true
-  inputsMet = true
-  droppedPackets = false
+  paramsOk = checkWirePatternPreconditionsParams config, input
+  # Then check actual input ports
+  inputsOk = checkWirePatternPreconditionsInput config, input
+  # If input port has data but param requirements are not met, and we're in dropInput
+  # mode, read the data and call done
+  if config.dropInput and not paramsOk
+    # Drop all received input packets since params are not available
+    packetsDropped = false
+    for port in config.inPorts
+      if input.ports[port].isAddressable()
+        attached = input.attached port
+        continue unless attached.length
+        for idx in attached
+          while input.has [port, idx]
+            packetsDropped = true
+            input.get([port, idx]).drop()
+        continue
+      while input.has port
+        packetsDropped = true
+        input.get(port).drop()
+    # If we ended up dropping inputs because of missing params, we need to
+    # deactivate here
+    output.done() if packetsDropped
+  # Pass precondition check only if both params and inputs are OK
+  return inputsOk and paramsOk
+
+checkWirePatternPreconditionsParams = (config, input) ->
   for param in config.params
     continue unless input.ports[param].isRequired()
     if input.ports[param].isAddressable()
       attached = input.attached param
-      unless attached.length
-        paramsMet = false
-        continue
+      return false unless attached.length
       withData = attached.filter (idx) -> input.hasData [param, idx]
       if config.arrayPolicy.params is 'all'
-        paramsMet = false unless withData.length is attached.length
+        return false unless withData.length is attached.length
         continue
-      paramsMet = false unless withData.length
+      return false unless withData.length
       continue
-    paramsMet = false unless input.hasData param
-  # Then check actual input ports
+    return false unless input.hasData param
+  true
+
+checkWirePatternPreconditionsInput = (config, input) ->
+  collatedBy = undefined if config.group or config.field
+  validate = (ip) ->
+    if ip.type is 'data'
+      if config.field
+        # Use first data packet to define what to collate by
+        collatedBy = ip.data[config.field] if collatedBy is undefined
+        return ip.data[config.field] is collatedBy
+      # Without collation rules any data packet is OK
+      return true
+    false
+
   for port in config.inPorts
     if input.ports[port].isAddressable()
       attached = input.attached port
-      unless attached.length
-        inputsMet = false
+      return false unless attached.length
+      withData = attached.filter (idx) -> input.has [port, idx], validate
+      if config.arrayPolicy['in'] is 'all'
+        return false unless withData.length is attached.length
         continue
-      withData = attached.filter (idx) -> input.hasData [port, idx]
-      if config.arrayPolicy['in'] is 'all'
-        inputsMet = false unless withData.length is attached.length
-        continue
-      inputsMet = false unless withData.length
+      return false unless withData.length
       continue
-    unless input.hasData port
-      inputsMet = false
-      continue
-    # If input port has data but param requirements are not
-    # met, and we're in dropInput mode, read the data and
-    # call done
-    if config.dropInput and not paramsMet
-      input.getData port
-      droppedPackets = true
-
-  output.done() if droppedPackets and not paramsMet
-  return inputsMet and paramsMet
+    return false unless input.has port, validate
+  true
 
 # Wraps OutPort in WirePattern to add transparent scope support
 class OutPortWrapper

    params[paramPort] = input.getData paramPort
  return params

getInputData = (config, input) ->
  data = {}
  for port in config.inPorts

      data[port] = {}
      for idx in input.attached port
        continue unless input.hasData [port, idx]
        handleInputCollation data, config, input, port, idx
        data[port][idx] = input.getData [port, idx]
      continue
    continue unless input.hasData port
    handleInputCollation data, config, input, port
    data[port] = input.getData port
  if config.inPorts.length is 1
    return data[config.inPorts[0]]
