branch develop updated (6b64d24 -> afab4f6)
This is an automated email from the git hooks/post-receive script. New change to branch develop in repository echobase. See https://gitlab.nuiton.org/codelutin/echobase.git from 6b64d24 #8173 Add vocabulary table new afab4f6 Export biotic export for atlantos The 1 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit afab4f6fb127dace9cb0b97c892d185a12c23a5d Author: Julien Ruchaud <julien.ruchaud@debux.org> Date: Mon Oct 24 18:05:16 2016 +0200 Export biotic export for atlantos Summary of changes: .../migration/workingDb/h2/3.911-0-atlantos.sql | 3 +- .../migration/workingDb/pg/3.911-0-atlantos.sql | 1 + echobase-domain/src/main/xmi/echobase.zargo | Bin 100253 -> 100339 bytes .../service/atlantos/xml/VocabularyExport.java | 39 ++- .../service/atlantos/xml/XmlAccousticExport.java | 4 +- .../service/atlantos/xml/XmlBioticExport.java | 306 ++++++++++++++------- .../services/service/atlantos/xml/XmlWriter.java | 2 + 7 files changed, 243 insertions(+), 112 deletions(-) -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository echobase. See https://gitlab.nuiton.org/codelutin/echobase.git commit afab4f6fb127dace9cb0b97c892d185a12c23a5d Author: Julien Ruchaud <julien.ruchaud@debux.org> Date: Mon Oct 24 18:05:16 2016 +0200 Export biotic export for atlantos --- .../migration/workingDb/h2/3.911-0-atlantos.sql | 3 +- .../migration/workingDb/pg/3.911-0-atlantos.sql | 1 + echobase-domain/src/main/xmi/echobase.zargo | Bin 100253 -> 100339 bytes .../service/atlantos/xml/VocabularyExport.java | 39 ++- .../service/atlantos/xml/XmlAccousticExport.java | 4 +- .../service/atlantos/xml/XmlBioticExport.java | 306 ++++++++++++++------- .../services/service/atlantos/xml/XmlWriter.java | 2 + 7 files changed, 243 insertions(+), 112 deletions(-) diff --git a/echobase-domain/src/main/resources/migration/workingDb/h2/3.911-0-atlantos.sql b/echobase-domain/src/main/resources/migration/workingDb/h2/3.911-0-atlantos.sql index 41595e2..f7c1d6c 100644 --- a/echobase-domain/src/main/resources/migration/workingDb/h2/3.911-0-atlantos.sql +++ b/echobase-domain/src/main/resources/migration/workingDb/h2/3.911-0-atlantos.sql @@ -23,4 +23,5 @@ create table vocabularyciem (topiaId varchar(255) not null, topiaVersion bigint alter table vocabularyciem add constraint PK_VOCA primary key (topiaId); alter table vocabularyciem add constraint UK_VOCA_LABEL unique (label); -alter table mission add column country varchar(255); \ No newline at end of file +alter table mission add column country varchar(255); +alter table species add column wormscode varchar(255); \ No newline at end of file diff --git a/echobase-domain/src/main/resources/migration/workingDb/pg/3.911-0-atlantos.sql b/echobase-domain/src/main/resources/migration/workingDb/pg/3.911-0-atlantos.sql index 6abcc27..ffb7a2b 100644 --- a/echobase-domain/src/main/resources/migration/workingDb/pg/3.911-0-atlantos.sql +++ b/echobase-domain/src/main/resources/migration/workingDb/pg/3.911-0-atlantos.sql @@ -24,3 +24,4 @@ alter table vocabularyciem add constraint PK_VOCA primary key (topiaId); alter table vocabularyciem add constraint UK_VOCA_LABEL unique (label); alter table mission add column country character varying(255); +alter table species add column wormscode character varying(255); diff --git a/echobase-domain/src/main/xmi/echobase.zargo b/echobase-domain/src/main/xmi/echobase.zargo index fbdca85..d9f8c64 100644 Binary files a/echobase-domain/src/main/xmi/echobase.zargo and b/echobase-domain/src/main/xmi/echobase.zargo differ diff --git a/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/VocabularyExport.java b/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/VocabularyExport.java index 711a6d7..5fe9231 100644 --- a/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/VocabularyExport.java +++ b/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/VocabularyExport.java @@ -23,23 +23,32 @@ public class VocabularyExport implements EchoBaseService { vocabulary.put("Hull", "AC_TransducerLocation_AA"); vocabulary.put("Split", "AC_TransducerBeamType_S2"); vocabulary.put(".hac and .raw formats", "AC_StoredDataFormat_HAC"); - vocabulary.put("ER60", "AC_DataAcquisitionSoftwareName_ER60"); // À ajouter dans le voca - vocabulary.put("Movies3D", "AC_DataProcessingSoftwareName_Movies3D"); // À ajouter dans le voca - vocabulary.put("PELGAS", "AC_Survey_PELGAS"); // À ajouter dans le voca + vocabulary.put("ER60", "AC_DataAcquisitionSoftwareName_ER60"); + vocabulary.put("Movies3D", "AC_DataProcessingSoftwareName_Movies3D"); + vocabulary.put("PELGAS", "AC_Survey_PELGAS"); vocabulary.put("France", "ISO_3166_FR"); vocabulary.put("35HT", "SHIPC_35HT"); - vocabulary.put("D1", "AC_SaCategory_D1"); // À ajouter dans le voca - vocabulary.put("D2", "AC_SaCategory_D2"); // À ajouter dans le voca - vocabulary.put("D3", "AC_SaCategory_D3"); // À ajouter dans le voca - vocabulary.put("D4", "AC_SaCategory_D4"); // À ajouter dans le voca - vocabulary.put("D5", "AC_SaCategory_D5"); // À ajouter dans le voca - vocabulary.put("D6", "AC_SaCategory_D6"); // À ajouter dans le voca - vocabulary.put("D7", "AC_SaCategory_D7"); // À ajouter dans le voca - vocabulary.put("D8", "AC_SaCategory_D8"); // À ajouter dans le voca - vocabulary.put("D9", "AC_SaCategory_D9"); // À ajouter dans le voca - vocabulary.put("D10", "AC_SaCategory_D10"); // À ajouter dans le voca - vocabulary.put("D11", "AC_SaCategory_D11"); // À ajouter dans le voca - vocabulary.put("D12", "AC_SaCategory_D12"); // À ajouter dans le voca + vocabulary.put("D1", "AC_SaCategory_D1"); + vocabulary.put("D2", "AC_SaCategory_D2"); + vocabulary.put("D3", "AC_SaCategory_D3"); + vocabulary.put("D4", "AC_SaCategory_D4"); + vocabulary.put("D5", "AC_SaCategory_D5"); + vocabulary.put("D6", "AC_SaCategory_D6"); + vocabulary.put("D7", "AC_SaCategory_D7"); + vocabulary.put("D8", "AC_SaCategory_D8"); + vocabulary.put("D9", "AC_SaCategory_D9"); + vocabulary.put("D10", "AC_SaCategory_D10"); + vocabulary.put("D11", "AC_SaCategory_D11"); + vocabulary.put("D12", "AC_SaCategory_D12"); + vocabulary.put("Standard sphere, in-situ", "AC_AcquisitionMethod_SS"); + vocabulary.put("ER60", "AC_ProcessingMethod_ER60"); // À vérifier dans le voca + vocabulary.put("57x52", "Gear_57x52"); // À vérifier dans le voca + vocabulary.put("76x70", "Gear_76x70"); // À vérifier dans le voca + vocabulary.put("942OBS", "Gear_PAR"); // À vérifier dans le voca + vocabulary.put("0", "AC_CatchCategory_1"); + vocabulary.put("G", "AC_CatchCategory_2"); + vocabulary.put("P", "AC_CatchCategory_3"); + vocabulary.put("TP", "AC_CatchCategory_4"); Map<String, String> fromDB = persistenceService.getVocabulary(); vocabulary.putAll(fromDB); diff --git a/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlAccousticExport.java b/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlAccousticExport.java index 62ff4f4..66b229b 100644 --- a/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlAccousticExport.java +++ b/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlAccousticExport.java @@ -202,9 +202,9 @@ public class XmlAccousticExport implements EchoBaseService { xml.create("Date", EchoBaseCsvUtil.ISO8611_DATE_FORMATTER.format(calibration.getDate())); xml.create("AcquisitionMethod", - "IDREF", calibration.getAquisitionMethod()); + "IDREF", vocabulary.getVocabularyCode(calibration.getAquisitionMethod(), "AC_AcquisitionMethod_SS")); xml.create("ProcessingMethod", - "IDREF", calibration.getProcessingMethod()); + "IDREF", vocabulary.getVocabularyCode(calibration.getProcessingMethod(), "AC_ProcessingMethod_pmethod1")); xml.create("AccuracyEstimate", calibration.getAccuracyEstimate()); xml.create("Report", diff --git a/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlBioticExport.java b/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlBioticExport.java index 4d8ce25..d35f359 100644 --- a/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlBioticExport.java +++ b/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlBioticExport.java @@ -8,13 +8,18 @@ import fr.ifremer.echobase.entities.data.Operation; import fr.ifremer.echobase.entities.data.OperationMetadataValue; import fr.ifremer.echobase.entities.data.Sample; import fr.ifremer.echobase.entities.data.SampleData; +import fr.ifremer.echobase.entities.data.Transect; +import fr.ifremer.echobase.entities.data.Transit; import fr.ifremer.echobase.entities.data.Voyage; -import fr.ifremer.echobase.entities.references.Species; +import fr.ifremer.echobase.entities.references.SampleDataTypeImpl; import fr.ifremer.echobase.entities.references.SpeciesCategory; import fr.ifremer.echobase.services.EchoBaseService; import fr.ifremer.echobase.services.csv.EchoBaseCsvUtil; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import javax.inject.Inject; /* @@ -55,65 +60,108 @@ public class XmlBioticExport implements EchoBaseService { "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance", "xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); - exportCruise(voyage, xml); + Collection<Transit> transits = voyage.getTransit(); + Transit transit = transits.iterator().next(); + Collection<Transect> transects = transit.getTransect(); + Transect transect = transects.iterator().next(); + + exportCruise(voyage, transect, xml); + + int index = 1; Collection<Operation> operations = voyage.getAllOperations(); for (Operation operation : operations) { - + // EXPORT HAUL - exportHaul(operation, xml); + exportHaul(operation, index++, xml); + + Map<String, Float> totalWeight = new HashMap<String, Float>(); + Map<String, Integer> totalNumber = new HashMap<String, Integer>(); + Collection<Sample> subSamples = new ArrayList<Sample>(); Collection<Sample> samples = operation.getSample(); for (Sample sample : samples) { - // EXPORT CATCH - exportCatch(sample, xml); + String name = sample.getSampleType().getName(); - Collection<SampleData> datas = sample.getSampleData(); - for (SampleData data : datas) { + if ("Total".equals(name)) { + SpeciesCategory category = sample.getSpeciesCategory(); + String code = category.getSpecies().getBaracoudaCode(); + + Float weight = totalWeight.get(code); + if (weight == null) { + weight = 0f; + } - // EXPORT BIOLOGY - exportBiology(data, xml); + Float sampleWeight = sample.getSampleWeight(); + if (sampleWeight != null) { + weight += sampleWeight; + } + totalWeight.put(code, weight); + + Integer number = totalNumber.get(code); + if (number == null) { + number = 0; + } + + Integer numberSampled = sample.getNumberSampled(); + if (numberSampled != null) { + number += numberSampled; + } + totalNumber.put(code, number); + + subSamples.add(sample); } + + if ("Subsample".equals(name)) { + subSamples.add(sample); + } + } + + for (Sample sample : subSamples) { + SpeciesCategory category = sample.getSpeciesCategory(); + String code = category.getSpecies().getBaracoudaCode(); + + Float weight = totalWeight.get(code); + Integer number = totalNumber.get(code); + + // EXPORT CATCH + exportCatch(sample, weight, number, xml); + + // EXPORT BIOLOGY: nothing we don't have the data for the moment + xml.close("Catch"); } + xml.close("Haul"); } - + xml.close("Cruise"); xml.close("Biotic"); } - public void exportCruise(Voyage voyage, XmlWriter xml) throws IOException { + public void exportCruise(Voyage voyage, Transect transect, XmlWriter xml) throws IOException { xml.open("Cruise"); xml.create("Survey", - "IDREF", "AC_Survey_HERAS"); + "IDREF", vocabulary.getVocabularyCode(voyage.getMission().getName(), "AC_Survey_PELGAS")); xml.create("Country", - "IDREF", "ISO_3166_DK"); + "IDREF", vocabulary.getVocabularyCode(voyage.getMission().getCountry(), "ISO_3166_FR")); xml.create("Platform", - "IDREF", "SHIPC_26D4"); + "IDREF", vocabulary.getVocabularyCode(transect.getVessel().getCode(), "SHIPC_35HT")); xml.create("StartDate", EchoBaseCsvUtil.ISO8611_DATE_FORMATTER.format(voyage.getStartDate())); xml.create("EndDate", EchoBaseCsvUtil.ISO8611_DATE_FORMATTER.format(voyage.getEndDate())); xml.create("Organisation", - "IDREF", "EDMO_2195"); + "IDREF", vocabulary.getVocabularyCode(voyage.getMission().getInstitution(), "EDMO_541")); xml.create("LocalID", voyage.getTopiaId()); } - public void exportHaul(Operation operation, XmlWriter xml) throws IOException { + public void exportHaul(Operation operation, int number, XmlWriter xml) throws IOException { xml.open("Haul"); - Collection<GearMetadataValue> gearMetadataValues = operation.getGearMetadataValue(); - ImmutableMap<String, GearMetadataValue> gearMetadatas = Maps.uniqueIndex(gearMetadataValues, new Function<GearMetadataValue, String>() { - @Override - public String apply(GearMetadataValue value) { - return value.getGearMetadata().getName(); - } - }); - Collection<OperationMetadataValue> operationMetadataValues = operation.getOperationMetadataValue(); ImmutableMap<String, OperationMetadataValue> operationMetadatas = Maps.uniqueIndex(operationMetadataValues, new Function<OperationMetadataValue, String>() { @Override @@ -122,100 +170,170 @@ public class XmlBioticExport implements EchoBaseService { } }); + String gearCode = operation.getGear().getGearCode(); + OperationMetadataValue meanWaterDepthMeta = operationMetadatas.get("MeanWaterDepth"); + float meanWaterDepth = Float.parseFloat(meanWaterDepthMeta.getDataValue()); + + float minTrawlDepth; + float maxTrawlDepth; + + String depthStratum = operation.getDepthStratum().getId(); + if (depthStratum.equals("SURF")) { + minTrawlDepth = 0; + maxTrawlDepth = 30; + + } else { + minTrawlDepth = meanWaterDepth; + maxTrawlDepth = minTrawlDepth; + + switch (gearCode) { + case "76x70": + minTrawlDepth -= 20; + break; + case "57x52": + minTrawlDepth -= 15; + break; + case "942OBS": + minTrawlDepth -= 30; + break; + } + } + + Float startLatitude = operation.getGearShootingStartLatitude(); + Float startLongitude = operation.getGearShootingStartLongitude(); + Float endLatitude = operation.getGearShootingEndLatitude(); + Float endLongitude = operation.getGearShootingEndLongitude(); + + int distance = (int) (Math.sqrt(Math.pow(startLatitude - startLatitude, 2) + Math.pow(endLongitude - startLongitude, 2)) * 60 * 1852); + + int netopening = 0; + switch (gearCode) { + case "76x70": + netopening = 20; + break; + case "57x52": + netopening = 15; + break; + case "942OBS": + netopening = 30; + break; + } + xml.create("Gear", - "IDREF", operation.getTopiaId()); - xml.create("Number"); - xml.create("StationName"); + "IDREF", vocabulary.getVocabularyCode(gearCode, "Gear_PAR")); + xml.create("Number", + number); + xml.create("StationName", + operation.getId()); xml.create("StartTime", EchoBaseCsvUtil.ISO8611_DATE_FORMATTER.format(operation.getGearShootingStartTime())); xml.create("Duration", (int)((operation.getGearShootingEndTime().getTime() - operation.getGearShootingStartTime().getTime()) / (1000 * 60))); xml.create("Validity", - "IDREF", ""); - xml.create("StartLatitude", - operation.getGearShootingStartLatitude()); - xml.create("StartLongitude", - operation.getGearShootingStartLongitude()); - xml.create("StopLatitude", - operation.getGearShootingEndLatitude()); - xml.create("StopLongitude", - operation.getGearShootingEndLongitude()); - xml.create("StatisticalRectangle"); - xml.create("MinTrawlDepth"); - xml.create("MaxTrawlDepth"); - xml.create("BottomDepth"); - xml.create("Distance"); - xml.create("Netopening"); - xml.create("CodendMesh"); - xml.create("SweepLength"); - xml.create("GearExceptions", - "IDREF", ""); - xml.create("DoorType", - "IDREF", ""); - xml.create("WarpLength"); - xml.create("WarpDiameter"); - xml.create("WarpDensity"); - xml.create("DoorSurface"); - xml.create("DoorWeight"); - xml.create("DoorSpread"); - xml.create("WingSpread"); - xml.create("Buoyancy"); - xml.create("KiteArea"); - xml.create("GroundRopeWeight"); - xml.create("Rigging"); - xml.create("Tickler"); - xml.create("HydrographicStationID"); - xml.create("TowDirection"); - xml.create("SpeedGround"); - xml.create("SpeedWater"); - xml.create("WindDirection"); - xml.create("WindSpeed"); - xml.create("SwellDirection"); - xml.create("SwellHeight"); - xml.create("LogDistance"); + "IDREF", "AC_HaulValidity_V"); + xml.create("StartLatitude", startLatitude); + xml.create("StartLongitude", startLongitude); + xml.create("StopLatitude", endLatitude); + xml.create("StopLongitude", endLongitude); +// xml.create("StatisticalRectangle"); + xml.create("MinTrawlDepth", + minTrawlDepth); + xml.create("MaxTrawlDepth", + maxTrawlDepth); + xml.create("BottomDepth", + meanWaterDepth); + xml.create("Distance", + distance); + xml.create("Netopening", + netopening); +// xml.create("CodendMesh"); +// xml.create("SweepLength"); +// xml.create("GearExceptions", +// "IDREF", ""); +// xml.create("DoorType", +// "IDREF", ""); +// xml.create("WarpLength"); +// xml.create("WarpDiameter"); +// xml.create("WarpDensity"); +// xml.create("DoorSurface"); +// xml.create("DoorWeight"); +// xml.create("DoorSpread"); +// xml.create("WingSpread"); +// xml.create("Buoyancy"); +// xml.create("KiteArea"); +// xml.create("GroundRopeWeight"); +// xml.create("Rigging"); +// xml.create("Tickler"); +// xml.create("HydrographicStationID"); +// xml.create("TowDirection"); +// xml.create("SpeedGround"); +// xml.create("SpeedWater"); +// xml.create("WindDirection"); +// xml.create("WindSpeed"); +// xml.create("SwellDirection"); +// xml.create("SwellHeight"); +// xml.create("LogDistance"); } - public void exportCatch(Sample sample, XmlWriter xml) throws IOException { + public void exportCatch(Sample sample, Float weight, Integer number, XmlWriter xml) throws IOException { xml.open("Catch"); - SpeciesCategory category = sample.getSpeciesCategory(); - boolean hasCategory = category != null; - - boolean hasSpecies = false; - Species species = null; - if (hasCategory) { - species = category.getSpecies(); - hasSpecies = species != null; + Map<String, String> sampleDataValues = new HashMap<String, String>(); + Collection<SampleData> datas = sample.getSampleData(); + for (SampleData data : datas) { + + String name = data.getSampleDataType().getName(); + Float value = data.getDataValue(); + String label = data.getDataLabel(); + + if (SampleDataTypeImpl.LTCM0_5.equals(name) + || SampleDataTypeImpl.L_TCM_1.equals(name)) { + + sampleDataValues.put(SampleDataTypeImpl.NUMBER_AT_LENGTH, String.valueOf(value)); + sampleDataValues.put(name, label); + sampleDataValues.put("LengthClass", label); + + } else { + sampleDataValues.put(name, String.valueOf(value)); + } } + SpeciesCategory category = sample.getSpeciesCategory(); + xml.create("DataType", "IDREF", "AC_CatchDataType_R"); xml.create("SpeciesCode", - "IDREF", hasSpecies ? species.getBaracoudaCode() : null); + "IDREF", "SpecWoRMS_" + category.getSpecies().getWormsCode()); xml.create("SpeciesValidity", - "IDREF", ""); + "IDREF", "AC_SpeciesValidity_1"); xml.create("SpeciesTotalNumber", - sample.getNumberSampled()); + number); xml.create("WeightUnit", "IDREF", "AC_WeightUnit_kg"); xml.create("SpeciesTotalWeight", - sample.getSampleWeight()); + weight.intValue()); + xml.create("SpeciesCategory", - "IDREF", hasSpecies ? species.getTaxonCode() : null); - xml.create("SpeciesSex", - "IDREF", hasCategory ? category.getSexCategoryLabel() : null); - xml.create("CategoryWeight"); - xml.create("SubsampledNumber"); - xml.create("SubsamplingFactor"); - xml.create("SubsampleWeight"); + "IDREF", vocabulary.getVocabularyCode(category.getSizeCategoryLabel(), "AC_CatchCategory_1")); +// xml.create("SpeciesSex"); +// xml.create("CategoryWeight"); + xml.create("SubsampledNumber", + sample.getNumberSampled()); + xml.create("SubsamplingFactor", + weight / sample.getSampleWeight()); + xml.create("SubsampleWeight", + sample.getSampleWeight()); + xml.create("LengthCode", - "IDREF", "AC_LengthCode_mm"); + "IDREF", sampleDataValues.containsKey(SampleDataTypeImpl.LTCM0_5) ? "AC_LengthCode_halfcm" : "AC_LengthCode_cm"); xml.create("LengthClass", - hasCategory ? category.getLengthClass() : null); + sampleDataValues.get("LengthClass")); xml.create("LengthType", "IDREF", "AC_LengthMeasurementType_1"); - xml.create("NumberAtLength"); - xml.create("WeightAtLength"); + xml.create("NumberAtLength", + sampleDataValues.get(SampleDataTypeImpl.NUMBER_AT_LENGTH)); + xml.create("WeightAtLength", + sampleDataValues.get(SampleDataTypeImpl.WEIGHT_AT_LENGTHKG)); } public void exportBiology(SampleData data, XmlWriter xml) throws IOException { diff --git a/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlWriter.java b/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlWriter.java index b368b0d..6ce3845 100644 --- a/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlWriter.java +++ b/echobase-services/src/main/java/fr/ifremer/echobase/services/service/atlantos/xml/XmlWriter.java @@ -63,6 +63,8 @@ public class XmlWriter { Object innerValue = attributes[attributes.length - 1]; if (innerValue != null) { this.writer.append(">" + innerValue); + } else { + this.writer.append(">"); } this.writer.append("</" + tag + ">\n"); } else { -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
participants (1)
-
codelutin.com scm