public override IMatrixData ProcessData(IMatrixData[] inputData, Parameters param, ref IMatrixData[] supplTables,
                                                ref IDocumentData[] documents, ProcessInfo processInfo)
        {
            Metadata mtd = new Metadata();

            string name = string.Format("{0}{1}{2}", MetadataElement.MZTAB, MZTabConstants.MINUS,
                                        MetadataProperty.MZTAB_VERSION);
            StringParam stringParam = FindParam(param, name) as StringParam;
            if (stringParam != null && !string.IsNullOrEmpty(stringParam.Value)){
                mtd.MZTabVersion = stringParam.Value;
            }

            name = string.Format("{0}{1}{2}", MetadataElement.MZTAB, MZTabConstants.MINUS, MetadataProperty.MZTAB_MODE);
            SingleChoiceParam single = FindParam(param, name) as SingleChoiceParam;
            if (single != null && !string.IsNullOrEmpty(single.SelectedValue)){
                MzTabMode mode;
                if (Enum.TryParse(single.SelectedValue, true, out mode)){
                    mtd.MzTabMode = mode;
                }
            }

            name = string.Format("{0}{1}{2}", MetadataElement.MZTAB, MZTabConstants.MINUS, MetadataProperty.MZTAB_TYPE);
            single = FindParam(param, name) as SingleChoiceParam;
            if (single != null && !string.IsNullOrEmpty(single.SelectedValue)){
                MzTabType type;
                if (Enum.TryParse(single.SelectedValue, true, out type)){
                    mtd.MzTabType = type;
                }
            }

            name = string.Format("{0}{1}{2}", MetadataElement.MZTAB, MZTabConstants.MINUS, MetadataProperty.MZTAB_ID);
            stringParam = FindParam(param, name) as StringParam;
            if (stringParam != null && !string.IsNullOrEmpty(stringParam.Value)){
                mtd.MZTabID = stringParam.Value;
            }

            stringParam = FindParam(param, MetadataElement.TITLE.Name) as StringParam;
            if (stringParam != null && !string.IsNullOrEmpty(stringParam.Value)){
                mtd.SetTitle(stringParam.Value);
            }

            stringParam = FindParam(param, MetadataElement.DESCRIPTION.Name) as StringParam;
            if (stringParam != null && !string.IsNullOrEmpty(stringParam.Value)){
                mtd.SetDescription(stringParam.Value);
            }

            SingleChoiceWithSubParams singleSub =
                FindParam(param, MetadataElement.SAMPLE_PROCESSING.Name) as SingleChoiceWithSubParams;
            if (singleSub != null){
                SampleProcessingParam sub =
                    singleSub.SubParams[singleSub.Value].GetAllParameters().FirstOrDefault() as SampleProcessingParam;
                if (sub != null){
                    if (sub.Value != null){
                        for (int j = 0; j < sub.Value.Length; j++){
                            mtd.SampleProcessingMap.Add(j + 1, sub.Value[j]);
                        }
                    }
                }
            }

            singleSub = FindParam(param, MetadataElement.INSTRUMENT.Name) as SingleChoiceWithSubParams;
            if (singleSub != null){
                InstrumentParam sub =
                    singleSub.SubParams[singleSub.Value].GetAllParameters().FirstOrDefault() as InstrumentParam;
                if (sub != null){
                    if (sub.Value != null){
                        for (int j = 0; j < sub.Value.Length; j++){
                            mtd.InstrumentMap.Add(j + 1, sub.Value[j]);
                        }
                    }
                }
            }

            singleSub = FindParam(param, MetadataElement.SOFTWARE.Name) as SingleChoiceWithSubParams;
            if (singleSub != null){
                SoftwareParam sub =
                    singleSub.SubParams[singleSub.Value].GetAllParameters().FirstOrDefault() as SoftwareParam;
                if (sub != null){
                    if (sub.Value != null){
                        for (int j = 0; j < sub.Value.Length; j++){
                            mtd.SoftwareMap.Add(j + 1, sub.Value[j]);
                        }
                    }
                }
            }

            MultiChoiceParam multi = FindParam(param, MetadataElement.FALSE_DISCOVERY_RATE.Name) as MultiChoiceParam;
            if (multi != null && multi.SelectedValues != null && multi.SelectedValues.Any()){
                foreach (string sel in multi.SelectedValues){
                    string[] items = sel.Split('=');
                    if (items.Length != 2){
                        continue;
                    }
                    string key = items[0];
                    string value = items[1];

                    if (ContainsParameterKey(parameters.protein_fdr, key)){
                        key = "prot:global FDR";
                    } else if (ContainsParameterKey(parameters.psm_fdr, key)) {
                        key = "pep:global FDR";
                    } else if (ContainsParameterKey(parameters.site_fdr, key)) {
                        key = "site:global FDR";
                    }

                    Lib.Model.Param p = cv.GetParam(key, "MS", value);
                    if (p != null){
                        mtd.FalseDiscoveryRate.Add(p);
                    }
                }
            }

            singleSub = FindParam(param, MetadataElement.PUBLICATION.Name) as SingleChoiceWithSubParams;
            if (singleSub != null){
                PublicationParam sub =
                    singleSub.SubParams[singleSub.Value].GetAllParameters().FirstOrDefault() as PublicationParam;
                if (sub != null){
                    if (sub.Value != null){
                        for (int j = 0; j < sub.Value.Length; j++){
                            mtd.PublicationMap.Add(j + 1, sub.Value[j]);
                        }
                    }
                }
            }

            singleSub = FindParam(param, MetadataElement.CONTACT.Name) as SingleChoiceWithSubParams;
            if (singleSub != null){
                ContactParam sub =
                    singleSub.SubParams[singleSub.Value].GetAllParameters().FirstOrDefault() as ContactParam;
                if (sub != null){
                    if (sub.Value != null){
                        for (int j = 0; j < sub.Value.Length; j++){
                            mtd.ContactMap.Add(j + 1, sub.Value[j]);
                        }
                    }
                }
            }

            singleSub = FindParam(param, MetadataElement.FIXED_MOD.Name) as SingleChoiceWithSubParams;
            if (singleSub != null){
                ModificationParam sub =
                    singleSub.SubParams[singleSub.Value].GetAllParameters().FirstOrDefault() as ModificationParam;
                if (sub != null){
                    if (sub.Value != null){
                        for (int j = 0; j < sub.Value.Length; j++){
                            mtd.FixedModMap.Add(j + 1, (FixedMod) sub.Value[j]);
                        }
                    }
                }
            }

            singleSub = FindParam(param, MetadataElement.VARIABLE_MOD.Name) as SingleChoiceWithSubParams;
            if (singleSub != null){
                ModificationParam sub =
                    singleSub.SubParams[singleSub.Value].GetAllParameters().FirstOrDefault() as ModificationParam;
                if (sub != null){
                    if (sub.Value != null){
                        for (int j = 0; j < sub.Value.Length; j++){
                            mtd.VariableModMap.Add(j + 1, (VariableMod) sub.Value[j]);
                        }
                    }
                }
            }

            single = FindParam(param, MetadataElement.QUANTIFICATION_METHOD.Name) as SingleChoiceParam;
            if (single != null && !string.IsNullOrEmpty(single.SelectedValue)){
                Lib.Model.Param temp;
                mtd.QuantificationMethod = Lib.Model.Param.TryParse(single.SelectedValue, out temp)
                                               ? temp
                                               : cv.GetParam(single.SelectedValue, "MS");
            }

            name = string.Format("{0}{1}{2}", MetadataElement.PROTEIN, MZTabConstants.MINUS,
                                 MetadataProperty.PROTEIN_QUANTIFICATION_UNIT);
            single = FindParam(param, name) as SingleChoiceParam;
            if (single != null && !string.IsNullOrEmpty(single.SelectedValue)){
                Lib.Model.Param temp;
                mtd.ProteinQuantificationUnit = Lib.Model.Param.TryParse(single.SelectedValue, out temp)
                                                    ? temp
                                                    : cv.GetParam(single.SelectedValue, "PRIDE");
            }

            name = string.Format("{0}{1}{2}", MetadataElement.PEPTIDE, MZTabConstants.MINUS,
                                 MetadataProperty.PROTEIN_QUANTIFICATION_UNIT);
            single = FindParam(param, name) as SingleChoiceParam;
            if (single != null && !string.IsNullOrEmpty(single.SelectedValue)){
                Lib.Model.Param temp;
                mtd.PeptideQuantificationUnit = Lib.Model.Param.TryParse(single.SelectedValue, out temp)
                                                    ? temp
                                                    : cv.GetParam(single.SelectedValue, "PRIDE");
            }

            Regex regex = new Regex("[A-Z]{1}:/");
            MsRunParam msrunParam = FindParam(param, MetadataElement.MS_RUN.Name) as MsRunParam;
            if (msrunParam != null){
                if (msrunParam.Value != null){
                    for (int j = 0; j < msrunParam.Value.Length; j++){
                        MsRunImpl runImpl = msrunParam.Value[j];
                        if (regex.IsMatch(runImpl.Location.Value)){
                            runImpl.Location = new Url("file:\\\\\\" + runImpl.Location.Value);
                        }
                        mtd.MsRunMap.Add(j + 1, runImpl);
                    }
                }
            }

            SampleParam sampleParam = FindParam(param, MetadataElement.SAMPLE.Name) as SampleParam;
            if (sampleParam != null){
                if (sampleParam.Value != null){
                    for (int j = 0; j < sampleParam.Value.Length; j++){
                        mtd.SampleMap.Add(j + 1, sampleParam.Value[j]);
                    }
                }
            }

            AssayParam assayParam = FindParam(param, MetadataElement.ASSAY.Name) as AssayParam;
            if (assayParam != null){
                if (assayParam.Value != null){
                    for (int j = 0; j < assayParam.Value.Length; j++){
                        mtd.AssayMap.Add(j + 1, assayParam.Value[j]);
                    }
                }
            }

            StudyVariableParam studyVariableParam =
                FindParam(param, MetadataElement.STUDY_VARIABLE.Name) as StudyVariableParam;
            if (studyVariableParam != null){
                if (studyVariableParam.Value != null){
                    for (int j = 0; j < studyVariableParam.Value.Length; j++){
                        mtd.StudyVariableMap.Add(j + 1, studyVariableParam.Value[j]);
                    }
                }
            }

            multi = FindParam(param, MetadataElement.CV.Name) as MultiChoiceParam;
            if (multi != null && multi.SelectedValues != null){
                var headers = cv.Headers;
                foreach (string value in multi.SelectedValues){
                    var temp = headers.FirstOrDefault(x => x.FullName.Equals(value));
                    if (temp == null){
                        continue;
                    }
                    int id = mtd.CvMap.Count + 1;
                    mtd.CvMap.Add(id,
                                  new CV(id){
                                      FullName = temp.FullName,
                                      Label = temp.Label,
                                      Url = temp.Url,
                                      Version = temp.Version
                                  });
                }
            }

            string mtdString = mtd.ToString();
            string[] lines = mtdString.Split(new[]{"\n"}, StringSplitOptions.RemoveEmptyEntries);

            List<string> columnames = new List<string>{"MTH", "key", "value"};
            List<string[]> columns = columnames.Select(columname => new string[lines.Length]).ToList();

            for (int n = 0; n < lines.Length; n++){
                string[] items = lines[n].Split(new[]{"\t", "\n", "\r"}, StringSplitOptions.None);
                if (items.Length < 3){
                    continue;
                }
                columns[0][n] = items[0];
                columns[1][n] = items[1];
                columns[2][n] = items[2];
            }
            int nrows = lines.Length;
            int ncols = columnames.Count;
            IMatrixData data = (IMatrixData) inputData[0].CreateNewInstance(DataType.Matrix);
            data.SetData(Matrix.MetadataSection, new List<string>(), new float[nrows,ncols], columnames, columns,
                         new List<string>(), new List<string[][]>(), new List<string>(), new List<double[]>(),
                         new List<string>(), new List<double[][]>(), new List<string>(), new List<string[][]>(),
                         new List<string>(), new List<double[]>());

            return data;
        }