001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.structure.align.multiple;
022
023import java.io.Serializable;
024import java.util.ArrayList;
025import java.util.List;
026
027import org.biojava.nbio.structure.align.multiple.util.MultipleAlignmentTools;
028
029/**
030 * General implementation of a {@link Block} that supports any type of
031 * sequential alignment with gaps.
032 *
033 * @author Aleix Lafita
034 * @since 4.1.0
035 *
036 */
037public class BlockImpl extends AbstractScoresCache implements Serializable,
038                Block, Cloneable {
039
040        private static final long serialVersionUID = -5804042669466177641L;
041
042        private BlockSet parent;
043        private List<List<Integer>> alignRes;
044
045        // CACHE
046        private int coreLength;
047        private List<Integer> alignResCounts;
048
049        /**
050         * Constructor. Links also the parent to this instance, by adding the Block
051         * to the parent's list.
052         *
053         * @param blockSet
054         *            the parent BlockSet of the BlockImpl instance.
055         */
056        public BlockImpl(BlockSet blockSet) {
057
058                parent = blockSet;
059                if (parent != null)
060                        parent.getBlocks().add(this);
061                alignRes = null;
062                coreLength = -1; // Value -1 indicates not yet calculated.
063                alignResCounts = null; // Value null not yet calculated
064        }
065
066        /**
067         * Copy constructor.
068         *
069         * @param b
070         *            BlockImpl object to be copied.
071         */
072        public BlockImpl(BlockImpl b) {
073
074                super(b); // This copies the cached scores
075                this.parent = b.parent;
076                this.coreLength = b.coreLength;
077
078                this.alignRes = null;
079                if (b.alignRes != null) {
080                        // Make a deep copy of everything
081                        alignRes = new ArrayList<>();
082                        for (int k = 0; k < b.size(); k++) {
083                                alignRes.add(new ArrayList<Integer>(b.alignRes.get(k)));
084                        }
085                }
086        }
087
088        @Override
089        public Block clone() {
090                return new BlockImpl(this);
091        }
092
093        @Override
094        public void clear() {
095                super.clear();
096                coreLength = -1;
097                alignResCounts = null;
098        }
099
100        @Override
101        public String toString() {
102                return "BlockImpl [alignRes=" + alignRes + ", coreLength=" + coreLength
103                                + "]";
104        }
105
106        @Override
107        public void setBlockSet(BlockSet parent) {
108                this.parent = parent;
109        }
110
111        @Override
112        public BlockSet getBlockSet() {
113                return parent;
114        }
115
116        @Override
117        public List<List<Integer>> getAlignRes() {
118                return alignRes;
119        }
120
121        @Override
122        public void setAlignRes(List<List<Integer>> alignRes) {
123                this.alignRes = alignRes;
124        }
125
126        @Override
127        public int length() {
128                if (alignRes == null)
129                        return 0;
130                if (alignRes.size() == 0)
131                        return 0;
132                return alignRes.get(0).size();
133        }
134
135        @Override
136        public int size() {
137                return alignRes.size();
138        }
139
140        @Override
141        public int getCoreLength() {
142                if (coreLength == -1)
143                        updateCoreLength();
144                return coreLength;
145        }
146
147        protected void updateCoreLength() {
148                coreLength = MultipleAlignmentTools.getCorePositions(this).size();
149        }
150
151        @Override
152        public int getStartIndex(int str) {
153                int index = -1;
154                Integer start = null;
155                while (start == null && index < alignRes.get(str).size()) {
156                        index++;
157                        start = alignRes.get(str).get(index);
158                }
159                return index;
160        }
161
162        @Override
163        public int getStartResidue(int str) {
164                return alignRes.get(str).get(getStartIndex(str));
165        }
166
167        @Override
168        public int getFinalIndex(int str) {
169                int index = alignRes.get(str).size();
170                Integer end = null;
171                while (end == null && index >= 0) {
172                        index--;
173                        end = alignRes.get(str).get(index);
174                }
175                return index;
176        }
177
178        @Override
179        public int getFinalResidue(int str) {
180                return alignRes.get(str).get(getFinalIndex(str));
181        }
182
183        @Override
184        public List<Integer> getAlignResCounts() {
185
186                if (alignResCounts != null)
187                        return alignResCounts;
188
189                alignResCounts = new ArrayList<>(size());
190                for (int s = 0; s < size(); s++) {
191                        int count = 0;
192                        for (int r = 0; r < length(); r++) {
193                                if (alignRes.get(s).get(r) != null)
194                                        count++;
195                        }
196                        alignResCounts.add(count);
197                }
198                return alignResCounts;
199        }
200
201}