/* * Copyright 2012 EMBL - European Bioinformatics Institute * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package uk.ac.ebi.fg.annotare2.magetabcheck.checks.sdrf; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import uk.ac.ebi.fg.annotare2.magetabcheck.checker.annotation.MageTabCheck; import uk.ac.ebi.fg.annotare2.magetabcheck.efo.MageTabCheckEfo; import uk.ac.ebi.fg.annotare2.magetabcheck.model.FileLocation; import uk.ac.ebi.fg.annotare2.magetabcheck.model.idf.Protocol; import uk.ac.ebi.fg.annotare2.magetabcheck.model.idf.ProtocolType; import uk.ac.ebi.fg.annotare2.magetabcheck.model.sdrf.*; import javax.annotation.Nullable; import java.util.ArrayDeque; import java.util.Collection; import java.util.List; import java.util.Queue; import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.collect.Collections2.filter; import static com.google.common.collect.Lists.newArrayList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static uk.ac.ebi.fg.annotare2.magetabcheck.checker.CheckApplicationType.HTS_ONLY; import static uk.ac.ebi.fg.annotare2.magetabcheck.checker.CheckApplicationType.MICRO_ARRAY_ONLY; import static uk.ac.ebi.fg.annotare2.magetabcheck.checker.CheckModality.WARNING; import static uk.ac.ebi.fg.annotare2.magetabcheck.checker.CheckPositionSetter.setCheckPosition; import static uk.ac.ebi.fg.annotare2.magetabcheck.checks.idf.IdfConstants.DATE_FORMAT; import static uk.ac.ebi.fg.annotare2.magetabcheck.checks.matchers.IsDateString.isDateString; import static uk.ac.ebi.fg.annotare2.magetabcheck.checks.matchers.IsValidFileLocation.isValidFileLocation; import static uk.ac.ebi.fg.annotare2.magetabcheck.efo.MageTabCheckEfo.*; /** * @author Olga Melnichuk */ public class SdrfSimpleChecks { MageTabCheckEfo efo; @Inject public SdrfSimpleChecks(MageTabCheckEfo efo) { this.efo = efo; } @MageTabCheck( ref = "SR01", value = "A source (starting sample for the experiment) must have name specified") @SuppressWarnings("unused") public void sourceNodeMustHaveName(SdrfSourceNode sourceNode) { assertNotEmptyName(sourceNode); } @MageTabCheck( ref = "SR02", value = "A source (starting sample for the experiment) should have a 'Material Type' attribute specified", modality = WARNING) @SuppressWarnings("unused") public void sourceNodeShouldHaveMaterialTypeAttribute(SdrfSourceNode sourceNode) { setLinePosition(sourceNode); assertNotNull(sourceNode.getMaterialType()); setCellPosition(sourceNode.getMaterialType()); assertNotEmptyString(sourceNode.getMaterialType().getValue()); } @MageTabCheck( ref = "SR03", value = "A source (starting sample for the experiment) should have 'Provider' attribute specified", modality = WARNING) @SuppressWarnings("unused") public void sourceNodeShouldHaveProviderAttribute(SdrfSourceNode sourceNode) { setLinePosition(sourceNode); assertNotNull(sourceNode.getProvider()); setCellPosition(sourceNode.getProvider()); assertNotEmptyString(sourceNode.getProvider().getValue()); } @MageTabCheck( ref = "SR04", value = "A source (starting sample for the experiment) must have an 'Organism' characteristic specified") @SuppressWarnings("unused") public void sourceNodeMustHaveOrganismCharacteristic(SdrfSourceNode sourceNode) { setLinePosition(sourceNode); Collection<SdrfCharacteristicAttribute> characteristics = sourceNode.getCharacteristics(); assertNotNull(characteristics); assertThat(characteristics.isEmpty(), is(Boolean.FALSE)); SdrfCharacteristicAttribute organism = getOrganism(characteristics); assertNotNull(organism); setCellPosition(organism); assertNotEmptyString(organism.getValue()); } private SdrfCharacteristicAttribute getOrganism(Collection<SdrfCharacteristicAttribute> characteristics) { for (SdrfCharacteristicAttribute attr : characteristics) { if ("Organism".equalsIgnoreCase(attr.getType())) { return attr; } } return null; } @MageTabCheck( ref = "SR05", value = "A source (starting sample for the experiment) should have more than 2 characteristic attributes", modality = WARNING) @SuppressWarnings("unused") public void sourceNodeShouldHaveMoreThan2Characteristics(SdrfSourceNode sourceNode) { setLinePosition(sourceNode); Collection<SdrfCharacteristicAttribute> characteristics = sourceNode.getCharacteristics(); assertNotNull(characteristics); assertThat(characteristics.size(), greaterThanOrEqualTo(2)); } /* not sure what is the idea behind this check @MageTabCheck( ref = "SR07", value = "A source (starting sample for the experiment) should be described by a protocol", modality = WARNING) @SuppressWarnings("unused") public void sourceNodeShouldBeDescribedByProtocol(SdrfSourceNode sourceNode) { assertNodeIsDescribedByProtocol(sourceNode); } */ @MageTabCheck( ref = "SR08", value = "A growth, treatment or sample collection protocol must be included") @SuppressWarnings("unused") public void growthTreatmentOrSampleCollectionProtocolMustBeDefined(SdrfSourceNode sourceNode) { setLinePosition(sourceNode); assertThat( isProtocolTypeMatching( getFollowingProtocolNodes(sourceNode), GROWTH_PROTOCOL, TREATMENT_PROTOCOL, SAMPLE_COLLECTION_PROTOCOL), is(Boolean.TRUE)); } private boolean isProtocolTypeMatching(Collection<SdrfProtocolNode> protocolNodes, String... protocolTypes) { for (SdrfProtocolNode protocolNode : protocolNodes) { if (null == protocolNode.getProtocol()) { continue; } ProtocolType type = protocolNode.getProtocol().getType(); for (String matchingType : protocolTypes) { if (efo.isProtocolType(type, matchingType)) { return true; } } } return false; } @MageTabCheck( ref = "SM01", value = "A sample must have name specified") @SuppressWarnings("unused") public void sampleNodeMustHaveName(SdrfSampleNode sampleNode) { setCellPosition(sampleNode); assertNotEmptyName(sampleNode); } @MageTabCheck( ref = "SM02", value = "A sample should have a 'Material Type' attribute specified", modality = WARNING) @SuppressWarnings("unused") public void sampleNodeShouldHaveMaterialTypeAttribute(SdrfSampleNode sampleNode) { setLinePosition(sampleNode); assertNotNull(sampleNode.getMaterialType()); } @MageTabCheck( ref = "SM03", value = "A sample should be described by a protocol", modality = WARNING) @SuppressWarnings("unused") public void sampleNodeShouldBeDescribedByProtocol(SdrfSampleNode sampleNode) { setLinePosition(sampleNode); assertNodeIsDescribedByProtocol(sampleNode); } @MageTabCheck( ref = "EX01", value = "An extract must have name specified") @SuppressWarnings("unused") public void extractNodeMustHaveName(SdrfExtractNode extractNode) { setCellPosition(extractNode); assertNotEmptyName(extractNode); } @MageTabCheck( ref = "EX02", value = "An extract should have a 'Material Type' attribute specified", modality = WARNING) @SuppressWarnings("unused") public void extractNodeShouldHaveMaterialTypeAttribute(SdrfExtractNode extractNode) { setLinePosition(extractNode); assertNotNull(extractNode.getMaterialType()); } @MageTabCheck( ref = "EX03", value = "A nucleic acid extraction protocol must be included", application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void extractNodeShouldBeDescribedByProtocol(SdrfExtractNode extractNode) { setLinePosition(extractNode); assertThat( isProtocolTypeMatching( getParentProtocolNodes(extractNode), EXTRACTION_PROTOCOL), is(Boolean.TRUE)); } @MageTabCheck( ref = "EX04", value = "A nucleic acid library construction protocol must be included", application = HTS_ONLY) @SuppressWarnings("unused") public void extractNodeMustBeDescribedByLibraryConstructionProtocol(SdrfExtractNode extractNode) { setLinePosition(extractNode); assertThat( isProtocolTypeMatching( getParentProtocolNodes(extractNode), LIBRARY_CONSTRUCTION_PROTOCOL), is(Boolean.TRUE)); } @MageTabCheck( ref = "LE02", value = "A labeled extract must have name specified", application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void labeledExtractNodeMustHaveName(SdrfLabeledExtractNode labeledExtractNode) { setCellPosition(labeledExtractNode); assertNotEmptyName(labeledExtractNode); } @MageTabCheck( ref = "LE03", value = "A labeled extract should have a 'Material Type' attribute specified", modality = WARNING, application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void labeledExtractNodeShouldHaveMaterialTypeAttribute(SdrfLabeledExtractNode labeledExtractNode) { setLinePosition(labeledExtractNode); assertNotNull(labeledExtractNode.getMaterialType()); } @MageTabCheck( ref = "LE04", value = "A labeled extract must have 'Label' attribute specified", application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void labeledExtractNodeMustHaveLabelAttribute(SdrfLabeledExtractNode labeledExtractNode) { setLinePosition(labeledExtractNode); assertNotNull(labeledExtractNode.getLabel()); } @MageTabCheck( ref = "LE05", value = "A nucleic acid labeling protocol must be included", application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void labeledExtractNodeShouldBeDescribedByProtocol(SdrfLabeledExtractNode labeledExtractNode) { setLinePosition(labeledExtractNode); assertThat( isProtocolTypeMatching( getParentProtocolNodes(labeledExtractNode), LABELING_PROTOCOL), is(Boolean.TRUE)); } @MageTabCheck( ref = "L01", value = "A label attribute should have name specified", modality = WARNING, application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void labelAttributeShouldHaveName(SdrfLabelAttribute labelAttribute) { setCellPosition(labelAttribute); assertNotEmptyName(labelAttribute); } @MageTabCheck( ref = "L02", value = "A label attribute should have term source specified", modality = WARNING, application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void labelAttributeShouldHaveTermSource(SdrfLabelAttribute labelAttribute) { setCellPosition(labelAttribute); assertNotEmptyString(labelAttribute.getTermSourceRef()); } @MageTabCheck( ref = "L03", value = "Term source of a label attribute must be defined in IDF", application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void termSourceOfLabelAttributeMustBeValid(SdrfLabelAttribute labelAttribute) { setCellPosition(labelAttribute); assertTermSourceIsValid(labelAttribute); } @MageTabCheck( ref = "MT01", value = "A material type attribute should have a name specified", modality = WARNING) @SuppressWarnings("unused") public void materialTypeAttributeShouldHaveName(SdrfMaterialTypeAttribute materialTypeAttribute) { setCellPosition(materialTypeAttribute); assertNotEmptyName(materialTypeAttribute); } @MageTabCheck( ref = "MT02", value = "A material type attribute should have a term source specified", modality = WARNING) @SuppressWarnings("unused") public void materialTypeAttributeShouldHaveTermSource(SdrfMaterialTypeAttribute materialTypeAttribute) { setCellPosition(materialTypeAttribute); assertNotEmptyString(materialTypeAttribute.getTermSourceRef()); } @MageTabCheck( ref = "MT03", value = "Term source of a material type attribute must be defined in IDF") @SuppressWarnings("unused") public void termSourceOfMaterialTypeAttributeMustBeValid(SdrfMaterialTypeAttribute materialTypeAttribute) { setCellPosition(materialTypeAttribute); assertTermSourceIsValid(materialTypeAttribute); } @MageTabCheck( ref = "PN01", value = "A protocol must have a name specified") @SuppressWarnings("unused") public void protocolNodeMustHaveName(SdrfProtocolNode protocolNode) { assertNotEmptyName(protocolNode); } @MageTabCheck( ref = "PN04", value = "A protocol node should have a term source specified", modality = WARNING) @SuppressWarnings("unused") public void protocolNodeShouldHaveTermSource(SdrfProtocolNode protocolNode) { setCellPosition(protocolNode); assertNotEmptyString(protocolNode.getTermSourceRef()); } @MageTabCheck( ref = "PN05", value = "Term source value of a protocol node must be defined in IDF") @SuppressWarnings("unused") public void termSourceOfProtocolMustBeValid(SdrfProtocolNode protocolNode) { setCellPosition(protocolNode); assertTermSourceIsValid(protocolNode); } @MageTabCheck( ref = "PN03", value = "A protocol's date must be in 'YYYY-MM-DD' format") @SuppressWarnings("unused") public void protocolNodeDateFormat(SdrfProtocolNode protocolNode) { String date = protocolNode.getDate(); if (isNullOrEmpty(date)) { return; } setCellPosition(protocolNode); assertThat(date, isDateString(DATE_FORMAT)); } @MageTabCheck( ref = "PN06", value = "A nucleic acid sequencing protocol must have a 'performer' attribute specified", application = HTS_ONLY) @SuppressWarnings("unused") public void sequencingProtocolNodeMustHavePerformerAttribute(SdrfProtocolNode protocolNode) { Protocol protocol = protocolNode.getProtocol(); if (protocol != null && efo.isProtocolType(protocol.getType(), SEQUENCING_PROTOCOL)) { assertProtocolHasPerformerAttribute(protocolNode); } } @MageTabCheck( ref = "PN07", value = "A protocol should have a 'performer' attribute specified", modality = WARNING, application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void protocolNodeShouldHavePerformerAttribute(SdrfProtocolNode protocolNode) { assertProtocolHasPerformerAttribute(protocolNode); } private void assertProtocolHasPerformerAttribute(SdrfProtocolNode protocolNode) { setLinePosition(protocolNode); SdrfPerformerAttribute attr = protocolNode.getPerformer(); assertNotNull(attr); setCellPosition(attr); assertNotEmptyString(attr.getValue()); } @MageTabCheck( ref = "AN01", value = "An assay must have a name specified") @SuppressWarnings("unused") public void assayNodeMustHaveName(SdrfAssayNode assayNode) { assertNotEmptyName(assayNode); } @MageTabCheck( ref = "AN02", value = "An assay must have a 'Technology Type' attribute specified") @SuppressWarnings("unused") public void assayNodeMustHaveTechnologyTypeAttribute(SdrfAssayNode assayNode) { setCellPosition(assayNode); assertNotNull(assayNode.getTechnologyType()); } @MageTabCheck( ref = "AN03", value = "A nucleic acid sequencing protocol must be included", application = HTS_ONLY) @SuppressWarnings("unused") public void assayNodeMustBeDescribedBySequencingProtocol(SdrfAssayNode assayNode) { setLinePosition(assayNode); assertThat( isProtocolTypeMatching( getParentProtocolNodes(assayNode), SEQUENCING_PROTOCOL), is(Boolean.TRUE)); } @MageTabCheck( ref = "AN04", value = "A nucleic acid hybridization to array protocol must be included", application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void assayNodeMustBeDescribedByHybridizationProtocol(SdrfAssayNode assayNode) { setLinePosition(assayNode); assertThat( isProtocolTypeMatching( getParentProtocolNodes(assayNode), ARRAY_HYBRIDIZATION_PROTOCOL), is(Boolean.TRUE)); } @MageTabCheck( ref = "AN05", value = "'Technology Type' attribute must be equal to 'array assay' in micro-array submissions", application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void assayNodeTechnologyTypeIsArrayAssay(SdrfAssayNode assayNode) { setLinePosition(assayNode); assertNotNull(assayNode.getTechnologyType()); setCellPosition(assayNode.getTechnologyType()); assertThat(assayNode.getTechnologyType().getValue().trim(), equalToIgnoringCase("array assay")); } @MageTabCheck( ref = "AN06", value = "For an array assay (microarray experiment) the incoming nodes must be 'Labeled Extract' nodes only", application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void assayNodeMustBeDerivedFromLabeledExtracts(SdrfAssayNode assayNode) { setLinePosition(assayNode); Collection<SdrfGraphNode> parents = getParentNodes(assayNode); Collection<SdrfGraphNode> filtered = filter(parents, new Predicate<SdrfGraphNode>() { @Override public boolean apply(@Nullable SdrfGraphNode input) { return null != input && input instanceof SdrfLabeledExtractNode; } }); assertThat(parents.size(), equalTo(filtered.size())); } @MageTabCheck( ref = "TT01", value = "Technology type attribute must have name specified") @SuppressWarnings("unused") public void technologyTypeMustHaveName(SdrfTechnologyTypeAttribute technologyTypeAttribute) { assertNotEmptyName(technologyTypeAttribute); } @MageTabCheck( ref = "TT02", value = "Technology type attribute should have term source specified", modality = WARNING) @SuppressWarnings("unused") public void technologyTypeShouldHaveTermSource(SdrfTechnologyTypeAttribute technologyTypeAttribute) { setCellPosition(technologyTypeAttribute); assertNotEmptyString(technologyTypeAttribute.getTermSourceRef()); } @MageTabCheck( ref = "TT03", value = "Term source of a technology type attribute must be defined in IDF") @SuppressWarnings("unused") public void termSourceOfTechnologyTypeMustBeValied(SdrfTechnologyTypeAttribute technologyTypeAttribute) { setCellPosition(technologyTypeAttribute); assertTermSourceIsValid(technologyTypeAttribute); } @MageTabCheck( ref = "PV01", value = "A parameter value attribute (of a protocol) should have a name specified", modality = WARNING) @SuppressWarnings("unused") public void parameterValueAttributeShouldHaveName(SdrfParameterValueAttribute parameterValueAttribute) { setCellPosition(parameterValueAttribute); assertNotEmptyString(parameterValueAttribute.getType()); } @MageTabCheck( ref = "PV02", value = "A parameter value attribute (of a protocol) should have a unit specified", modality = WARNING) @SuppressWarnings("unused") public void parameterValueAttributeShouldHaveUnit(SdrfParameterValueAttribute parameterValueAttribute) { setCellPosition(parameterValueAttribute); assertNotNull(parameterValueAttribute.getUnit()); } @MageTabCheck( ref = "UA01", value = "A unit attribute should have name specified", modality = WARNING) @SuppressWarnings("unused") public void unitAttributeShouldHaveName(SdrfUnitAttribute unitAttribute) { setCellPosition(unitAttribute); assertNotEmptyString(unitAttribute.getType()); } @MageTabCheck( ref = "UA02", value = "A unit attribute should have term source specified", modality = WARNING) @SuppressWarnings("unused") public void unitAttributeShouldHaveTermSource(SdrfUnitAttribute unitAttribute) { setCellPosition(unitAttribute); assertNotEmptyString(unitAttribute.getTermSourceRef()); } @MageTabCheck( ref = "UA03", value = "Term source of a unit attribute must be declared in IDF") @SuppressWarnings("unused") public void termSourceOfUnitAttributeMustBeValid(SdrfUnitAttribute unitAttribute) { setCellPosition(unitAttribute); assertTermSourceIsValid(unitAttribute); } @MageTabCheck( ref = "LC01", value = "Library source, layout, selection and strategy must be specified for the ENA library info", application = HTS_ONLY) @SuppressWarnings("unused") public void extractNodeMustHaveFourLibraryComments(SdrfExtractNode extractNode) { setLinePosition(extractNode); Collection<String> requiredComments = ImmutableSet.of( "LIBRARY_LAYOUT", "LIBRARY_SELECTION", "LIBRARY_SOURCE", "LIBRARY_STRATEGY" ); int count = 0; for (SdrfComment comment : extractNode.getComments()) { if (requiredComments.contains(comment.getName())) { count++; } } assertThat(count, is(requiredComments.size())); } @MageTabCheck( ref = "LC02", value = "NOMINAL_LENGTH must be a positive integer and NOMINAL_SDEV must be a positive number for paired-end sequencing samples in the ENA library info", application = HTS_ONLY) @SuppressWarnings("unused") public void extractNodeMustHaveNominalLengthAndSDevSpecifiedForPairedExtracts(SdrfExtractNode extractNode) { setLinePosition(extractNode); boolean isPaired = false; int count = 0; for (SdrfComment comment : extractNode.getComments()) { if ("LIBRARY_LAYOUT".equals(comment.getName()) && comment.getValues().contains("PAIRED")) { isPaired = true; } if ("NOMINAL_LENGTH".contains(comment.getName()) && isValidPositiveInteger(comment.getValues())) { count++; } if ("NOMINAL_SDEV".contains(comment.getName()) && isValidPositiveDouble(comment.getValues())) { count++; } } if (isPaired) { assertThat(count, is(2)); } } @MageTabCheck( ref = "CA01", value = "A characteristic attribute should have name specified", modality = WARNING) @SuppressWarnings("unused") public void characteristicAttributeShouldHaveName(SdrfCharacteristicAttribute attribute) { setCellPosition(attribute); assertNotEmptyString(attribute.getType()); } @MageTabCheck( ref = "CA02", value = "A characteristic attribute should have a term source specified", modality = WARNING) @SuppressWarnings("unused") public void characteristicAttributeShouldHaveTermSource(SdrfCharacteristicAttribute attribute) { setCellPosition(attribute); assertNotEmptyString(attribute.getTermSourceRef()); } @MageTabCheck( ref = "CA03", value = "Term source of a characteristic attribute must be declared in IDF") @SuppressWarnings("unused") public void termSourceOfCharacteristicAttributeMustBeValid(SdrfCharacteristicAttribute attribute) { setCellPosition(attribute); assertTermSourceIsValid(attribute); } @MageTabCheck( ref = "FV01", value = "An experimental variable attribute should have a name specified", modality = WARNING) @SuppressWarnings("unused") public void factorValueAttributeShouldHaveName(SdrfFactorValueAttribute fvAttribute) { setCellPosition(fvAttribute); assertNotEmptyString(fvAttribute.getType()); } @MageTabCheck( ref = "FV02", value = "An experimental variable attribute should have a term source specified", modality = WARNING) @SuppressWarnings("unused") public void factorValueAttributeShouldHaveTermSource(SdrfFactorValueAttribute fvAttribute) { setCellPosition(fvAttribute); assertNotEmptyString(fvAttribute.getTermSourceRef()); } @MageTabCheck( ref = "FV03", value = "Term source of an experimental variable attribute must be declared in IDF") @SuppressWarnings("unused") public void termSourceOfFactorValueAttributeMustBeValid(SdrfFactorValueAttribute fvAttribute) { setCellPosition(fvAttribute); assertTermSourceIsValid(fvAttribute); } @MageTabCheck( ref = "AD01", value = "An array design attribute must have a name specified", application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void arrayDesignAttributeMustHaveName(SdrfArrayDesignAttribute adAttribute) { assertNotEmptyName(adAttribute); } @MageTabCheck( ref = "AD02", value = "An array design should have a term source specified", modality = WARNING, application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void arrayDesignAttributeShouldHaveTermSource(SdrfArrayDesignAttribute adAttribute) { setCellPosition(adAttribute); assertNotEmptyString(adAttribute.getTermSourceRef()); } @MageTabCheck( ref = "AD03", value = "Term source of an array design attribute must be declared in IDF", application = MICRO_ARRAY_ONLY) @SuppressWarnings("unused") public void termSourceOfArrayDesignAttributeMustBeValid(SdrfArrayDesignAttribute adAttribute) { setCellPosition(adAttribute); assertTermSourceIsValid(adAttribute); } @MageTabCheck( ref = "NN01", value = "A normalization node should have a name", modality = WARNING) @SuppressWarnings("unused") public void normalizationNodeShouldHaveName(SdrfNormalizationNode normalizationNode) { assertNotEmptyName(normalizationNode); } @MageTabCheck( ref = "SC01", value = "A scan should have a name specified", modality = WARNING) @SuppressWarnings("unused") public void scanNodeShouldHaveName(SdrfScanNode scanNode) { assertNotEmptyName(scanNode); } @MageTabCheck( ref = "ADN01", value = "An array data node (raw data file) must have a name") @SuppressWarnings("unused") public void arrayDataNodeMustHaveName(SdrfArrayDataNode arrayDataNode) { assertNotEmptyName(arrayDataNode); } @MageTabCheck( ref = "ADN02", value = "A raw data file name must only contain alphanumeric characters, underscores and dots") @SuppressWarnings("unused") public void arrayDataNodeMustHaveFormattedName(SdrfArrayDataNode arrayDataNode) { setCellPosition(arrayDataNode); assertThat(checkFileName(arrayDataNode), is(true)); } @MageTabCheck( ref = "ADN03", value = "Name of an array data node must be a valid file location") @SuppressWarnings("unused") public void nameOfArrayDataNodeMustBeValidFileLocation(SdrfArrayDataNode arrayDataNode) { assertFileLocationIsValid(arrayDataNode); } @MageTabCheck( ref = "ADN04", value = "An array data node (raw data file) should be described by a protocol", modality = WARNING) @SuppressWarnings("unused") public void arrayDataNodeShouldBeDescribedByProtocol(SdrfArrayDataNode arrayDataNode) { setLinePosition(arrayDataNode); assertNodeIsDescribedByProtocol(arrayDataNode); } @MageTabCheck( ref = "DADN01", value = "A derived array data node (processed data file) must have name specified") @SuppressWarnings("unused") public void derivedArrayDataNodeMustHaveName(SdrfDerivedArrayDataNode derivedArrayDataNode) { assertNotEmptyName(derivedArrayDataNode); } @MageTabCheck( ref = "DADN02", value = "A processed data file name must only contain alphanumeric characters, underscores and dots") @SuppressWarnings("unused") public void derivedArrayDataNodeMustHaveFormattedName(SdrfDerivedArrayDataNode derivedArrayDataNode) { setCellPosition(derivedArrayDataNode); assertThat(checkFileName(derivedArrayDataNode), is(true)); } @MageTabCheck( ref = "DADN03", value = "Name of a derived array data node must be a valid file location") @SuppressWarnings("unused") public void nameOfDerivedArrayDataNodeMustBeValidFileLocation(SdrfDerivedArrayDataNode derivedArrayDataNode) { assertFileLocationIsValid(derivedArrayDataNode); } @MageTabCheck( ref = "DADN04", value = "A normalization data transformation protocol that describes the analysis methods used to generate the processed data file(s) must be included") @SuppressWarnings("unused") public void derivedArrayDataNodeShouldBeDescribedByProtocol(SdrfDerivedArrayDataNode derivedArrayDataNode) { setLinePosition(derivedArrayDataNode); assertThat( isProtocolTypeMatching( getParentProtocolNodes(derivedArrayDataNode), DATA_TRANSOFRMATION_PROTOCOL), is(Boolean.TRUE)); } @MageTabCheck( ref = "ADMN01", value = "An array data matrix file must have name specified") @SuppressWarnings("unused") public void arrayDataMatrixNodeMustHaveName(SdrfArrayDataMatrixNode arrayDataMatrixNode) { assertNotEmptyName(arrayDataMatrixNode); } @MageTabCheck( ref = "ADMN02", value = "An array data matrix file name must only contain alphanumeric characters, underscores and dots") @SuppressWarnings("unused") public void arrayDataMatrixNodeMustHaveFormattedName(SdrfArrayDataMatrixNode arrayDataMatrixNode) { setCellPosition(arrayDataMatrixNode); assertThat(checkFileName(arrayDataMatrixNode), is(true)); } @MageTabCheck( ref = "ADMN03", value = "Name of an array data matrix node must be valid file location") @SuppressWarnings("unused") public void nameOfArrayDataMatrixNodeMustBeValidFileLocation(SdrfArrayDataMatrixNode arrayDataMatrixNode) { assertFileLocationIsValid(arrayDataMatrixNode); } @MageTabCheck( ref = "ADMN04", value = "An array data matrix file should be described by a protocol", modality = WARNING) @SuppressWarnings("unused") public void arrayDataMatrixNodeShouldBeDescribedByProtocol(SdrfArrayDataMatrixNode arrayDataMatrixNode) { assertNodeIsDescribedByProtocol(arrayDataMatrixNode); } @MageTabCheck( ref = "DADMN01", value = "A derived array data matrix file must have a name specified") @SuppressWarnings("unused") public void derivedArrayDataMatrixNodeMustHaveName(SdrfDerivedArrayDataMatrixNode derivedArrayDataMatrixNode) { assertNotEmptyName(derivedArrayDataMatrixNode); } @MageTabCheck( ref = "DADMN02", value = "A derived array data matrix file name must only contain alphanumeric characters, underscores and dots") @SuppressWarnings("unused") public void derivedArrayDataMatrixNodeMustHaveFormattedName(SdrfDerivedArrayDataMatrixNode derivedArrayDataMatrixNode) { setCellPosition(derivedArrayDataMatrixNode); assertThat(checkFileName(derivedArrayDataMatrixNode), is(true)); } @MageTabCheck( ref = "DADMN03", value = "Name of derived data matrix node must be valid file location") @SuppressWarnings("unused") public void nameOfDerivedArrayDataMatrixNodeMustBeValidFileLocation( SdrfDerivedArrayDataMatrixNode derivedArrayDataMatrixNode) { assertFileLocationIsValid(derivedArrayDataMatrixNode); } @MageTabCheck( ref = "DADMN04", value = "A normalization data transformation protocol that describes the analysis methods used to generate the processed data matrix file must be included") @SuppressWarnings("unused") public void derivedArrayDataMatrixNodeShouldBeDescribedByProtocol( SdrfDerivedArrayDataMatrixNode derivedArrayDataMatrixNode) { setLinePosition(derivedArrayDataMatrixNode); assertThat( isProtocolTypeMatching( getParentProtocolNodes(derivedArrayDataMatrixNode), DATA_TRANSOFRMATION_PROTOCOL), is(Boolean.TRUE)); } private static boolean checkFileName(SdrfDataNode dataNode){ // We only want to accept files with alphanumeric characters, no spaces, symbols etc. String filename = dataNode.getName(); return null != filename && filename.matches("^[_a-zA-Z0-9\\-\\.]+$"); } private static boolean isValidPositiveInteger(Collection<String> values) { for (String value : values) { try { if (null == value || Integer.valueOf(value) <= 0) { return false; } } catch (NumberFormatException x) { return false; } } return true; } private static boolean isValidPositiveDouble(Collection<String> values) { for (String value : values) { try { if (null == value || Double.valueOf(value) < 0) { return false; } } catch (NumberFormatException x) { return false; } } return true; } private static <T> void assertNotNull(T obj) { assertThat(obj, notNullValue()); } private static void assertNotEmptyString(String str) { assertThat(str, notNullValue()); assertThat(str.trim(), not(isEmptyString())); } private static void assertTermSourceIsValid(HasTermSource t) { if (isNullOrEmpty(t.getTermSourceRef())) { return; } assertNotNull(t.getTermSource()); } private static void assertNotEmptyName(SdrfGraphEntity node) { setCellPosition(node); String name = node.getName(); assertNotEmptyString(name); } private static void assertNodeIsDescribedByProtocol(SdrfGraphNode node) { setLinePosition(node); assertThat(getParentProtocolNodes(node), is(not(empty()))); } private static void assertFileLocationIsValid(SdrfDataNode dataNode) { FileLocation location = dataNode.getLocation(); if (!location.isEmpty()) { setCellPosition(dataNode); assertThat(location, isValidFileLocation()); } } private static Collection<SdrfProtocolNode> getFollowingProtocolNodes(SdrfGraphNode node) { List<SdrfProtocolNode> protocolNodes = newArrayList(); if (node instanceof SdrfProtocolNode) { protocolNodes.add((SdrfProtocolNode)node); } for (SdrfGraphNode child : node.getChildNodes()) { protocolNodes.addAll(getFollowingProtocolNodes(child)); } return protocolNodes; } private static Collection<SdrfProtocolNode> getParentProtocolNodes(SdrfGraphNode node) { List<SdrfProtocolNode> protocols = newArrayList(); Queue<SdrfGraphNode> queue = new ArrayDeque<SdrfGraphNode>(); queue.addAll(node.getParentNodes()); while (!queue.isEmpty()) { SdrfGraphNode parent = queue.poll(); if (parent instanceof SdrfProtocolNode) { protocols.add((SdrfProtocolNode) parent); queue.addAll(parent.getParentNodes()); } } return protocols; } private static Collection<SdrfGraphNode> getParentNodes(SdrfGraphNode node) { List<SdrfGraphNode> parents = newArrayList(); for (SdrfGraphNode parent : node.getParentNodes()) { if (parent instanceof SdrfProtocolNode) { parents.addAll(getParentNodes(parent)); } else { parents.add(parent); } } return parents; } private static <T extends HasLocation> void setLinePosition(T t) { setCheckPosition(t.getFileName(), t.getLine(), -1); } private static <T extends HasLocation> void setCellPosition(T t) { setCheckPosition(t.getFileName(), t.getLine(), t.getColumn()); } }