001/*
002 * Copyright 2018 Leibniz-Institut für Analytische Wissenschaften – ISAS – e.V..
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package uk.ac.ebi.pride.jmztab2.model;
017
018import de.isas.mztab2.model.IndexedElement;
019import de.isas.mztab2.model.OptColumnMapping;
020import de.isas.mztab2.model.Parameter;
021
022/**
023 * Builder for reusable {@link OptColumnMapping} creation for multiple rows.
024 *
025 * @author nilshoffmann
026 */
027public class OptColumnMappingBuilder implements IOptColumnMappingBuilder {
028
029    private OptColumnMappingBuilder() {
030
031    }
032
033    private static class NameParamOptColumnMappingBuilder implements IOptColumnMappingBuilder {
034
035        protected Parameter param;
036        protected String name;
037
038        /**
039         * Configure this builder to create an optional column mapping with the
040         * provided name. Mutually exclusive with {@link #withParameter(de.isas.mztab2.model.Parameter)
041         * }.
042         *
043         * @param name the name of this optional column.
044         * @return the builder instance.
045         */
046        IOptColumnMappingBuilder withName(String name) {
047            if (this.param != null) {
048                throw new IllegalStateException(
049                        "Can not set name for opt column, parameter already has been set!");
050            }
051            this.name = name;
052            return this;
053        }
054
055        /**
056         * Configure this builder to create cv parameter optional columns.
057         *
058         * @param parameter the cv parameter for this mapping.
059         * @return the builder instance.
060         */
061        IOptColumnMappingBuilder withParameter(Parameter parameter) {
062            if (this.name != null) {
063                throw new IllegalStateException(
064                        "Can not set parameter for opt column, name has been set already!");
065            }
066            if (parameter.getCvAccession() == null || parameter.getCvAccession().
067                    isEmpty()) {
068                throw new IllegalArgumentException(
069                        "Parameter must have cvAccession defined!");
070            }
071            if (parameter.getCvLabel() == null || parameter.getCvLabel().
072                    isEmpty()) {
073                throw new IllegalArgumentException(
074                        "Parameter must have cvLabel defined!");
075            }
076            if (parameter.getName() == null || parameter.getName().
077                    isEmpty()) {
078                throw new IllegalArgumentException(
079                        "Parameter must have name defined!");
080            }
081            this.param = parameter;
082            return this;
083        }
084    }
085
086    /**
087     * Create a new {@link OptColumnMappingBuilder} for global optional columns.
088     * Use this to create a global optional column, either with a dedicated
089     * name, or with a parameter. This applies to all replicates.
090     *
091     * {@code
092     *  opt_global_someProperty ... opt_global_cv_MS_MS:113123_parameter_name
093     *  <somePropertyValue> ... <parameter_name_value>
094     * }
095     */
096    public static class GlobalOptColumnMappingBuilder extends NameParamOptColumnMappingBuilder {
097
098        @Override
099        public GlobalOptColumnMappingBuilder withName(String name) {
100            super.withName(name);
101            return this;
102        }
103
104        @Override
105        public GlobalOptColumnMappingBuilder withParameter(Parameter parameter) {
106            super.withParameter(parameter);
107            return this;
108        }
109
110        @Override
111        public OptColumnMapping build(String value) {
112
113            if (this.param != null) {
114                return new OptColumnMapping().param(param).
115                        value(value).
116                        identifier(ParameterOptionColumn.getHeader(null, param));
117            } else {
118                if(name == null) {
119                    throw new IllegalArgumentException("Name must be defined if parameter is not set!");
120                }
121                return new OptColumnMapping().value(value).
122                        identifier(OptionColumn.getHeader(null, name));
123            }
124        }
125    }
126
127    /**
128     * Create a new {@link OptColumnMappingBuilder} for {@link IndexedElement}.
129     * Either referencing an indexed element property with a dedicated name, or
130     * with a parameter. This applies only to the referenced objects.
131     *
132     * {@code
133     *  opt_assay[1]_someProperty ... opt_assay[1]_cv_MS_MS:113123_parameter_name
134     *  <somePropertyValue> ... <parameter_name_value>
135     * }
136     */
137    public static class IndexedElementOptColumnMappingBuilder extends NameParamOptColumnMappingBuilder {
138
139        private final IndexedElement indexedElement;
140
141        @Override
142        public IndexedElementOptColumnMappingBuilder withName(String name) {
143            super.withName(name);
144            return this;
145        }
146
147        @Override
148        public IndexedElementOptColumnMappingBuilder withParameter(Parameter parameter) {
149            super.withParameter(parameter);
150            return this;
151        }
152
153        /**
154         * Configure this builder to create optional column mapping for an
155         * indexed element, such as
156         * {@link de.isas.mztab2.model.Assay}, {@link de.isas.mztab2.model.StudyVariable},
157         * or {@link de.isas.mztab2.model.MsRun}.
158         *
159         * @param indexedElement the indexed element to reference in this
160         * optional column.
161         */
162        public IndexedElementOptColumnMappingBuilder(IndexedElement indexedElement) {
163            this.indexedElement = indexedElement;
164        }
165
166        @Override
167        public OptColumnMapping build(String value) {
168            if (this.indexedElement == null) {
169                throw new IllegalArgumentException("Indexed element must not be null!");
170            }
171            if (this.param != null) {
172                return new OptColumnMapping().param(param).
173                        value(value).
174                        identifier(ParameterOptionColumn.getHeader(indexedElement, param));
175            } else {
176                if(name == null) {
177                    throw new IllegalArgumentException("Name must be defined if parameter is not set!");
178                }
179                return new OptColumnMapping().value(value).
180                        identifier(OptionColumn.getHeader(indexedElement, name));
181            }
182        }
183    }
184
185    /**
186     * Configure the builder for a global type column.
187     *
188     * @return the builder instance for a global opt column.
189     */
190    public static GlobalOptColumnMappingBuilder forGlobal() {
191        return new GlobalOptColumnMappingBuilder();
192    }
193
194    /**
195     * Configure the builder for an object reference (indexed element) type
196     * column.
197     *
198     * @param indexedElement the object to reference.
199     * @return the builder instance for an indexed element opt column.
200     */
201    public static IndexedElementOptColumnMappingBuilder forIndexedElement(IndexedElement indexedElement) {
202        return new IndexedElementOptColumnMappingBuilder(indexedElement);
203    }
204}