001    /**
002     * Copyright (c) 2010, SIB. All rights reserved.
003     * 
004     * SIB (Swiss Institute of Bioinformatics) - http://www.isb-sib.ch Host -
005     * https://sourceforge.net/projects/javaprotlib/
006     * 
007     * Redistribution and use in source and binary forms, with or without
008     * modification, are permitted provided that the following conditions are met:
009     * Redistributions of source code must retain the above copyright notice, this
010     * list of conditions and the following disclaimer. Redistributions in binary
011     * form must reproduce the above copyright notice, this list of conditions and
012     * the following disclaimer in the documentation and/or other materials provided
013     * with the distribution. Neither the name of the SIB/GENEBIO nor the names of
014     * its contributors may be used to endorse or promote products derived from this
015     * software without specific prior written permission.
016     * 
017     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
020     * ARE DISCLAIMED. IN NO EVENT SHALL SIB/GENEBIO BE LIABLE FOR ANY DIRECT,
021     * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
024     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027     */
028    package org.expasy.jpl.commons.collection;
029    
030    
031    import java.util.ArrayList;
032    import java.util.Arrays;
033    import java.util.List;
034    
035    
036    /**
037     * This object is {@code IntegerSequenceWithGap} with gaps defining a sequence
038     * of integers with missing integers at some intervals.
039     * 
040     * @author nikitin
041     * 
042     * @version 1.0
043     * 
044     */
045    public final class IntegerSequenceWithGap {
046            
047            /** the sequence of intervals */
048            private final List<IntegerSequence> sequence;
049            
050            /** the number of integers in all intervals */
051            private int numOfInts;
052            
053            /** construct an empty interval */
054            private IntegerSequenceWithGap() {
055                    sequence = new ArrayList<IntegerSequence>();
056            }
057            
058            public static IntegerSequenceWithGap newInstance() {
059                    return new IntegerSequenceWithGap();
060            }
061            
062            /**
063             * Build integer intervals
064             * 
065             * @param ints the integers to place in intervals.
066             * @param by the increment of the sequence.
067             * @return an instance of {@code JPLIntervalSequence}
068             */
069            public static IntegerSequenceWithGap fromIntegers(final int[] ints,
070                final int by) {
071                    final IntegerSequenceWithGap seq = new IntegerSequenceWithGap();
072                    
073                    if ((ints != null) && (ints.length > 0)) {
074                            int previousValue = ints[0];
075                            int from = previousValue;
076                            IntegerSequence interval = null;
077                            
078                            for (final int currentValue : ints) {
079                                    
080                                    // have to be sorted !!
081                                    if ((by > 0) && (currentValue < previousValue)) {
082                                            throw new IllegalStateException("integers have to be well"
083                                                + " sorted.");
084                                    } else if ((by < 0) && (currentValue > previousValue)) {
085                                            throw new IllegalStateException("integers have to be well"
086                                                + " sorted.");
087                                    }
088                                    // end of current interval
089                                    if ((by > 0) ? currentValue > previousValue + by
090                                        : currentValue < previousValue + by) {
091                                            
092                                            if (by > 0) {
093                                                    previousValue++;
094                                            } else {
095                                                    from++;
096                                            }
097                                            
098                                            interval =
099                                                new IntegerSequence.Builder(from, previousValue).by(by)
100                                                    .build();
101                                            
102                                            seq.add(interval);
103                                            from = currentValue;
104                                    }
105                                    previousValue = currentValue;
106                            }
107                            
108                            if (by > 0) {
109                                    previousValue++;
110                            } else {
111                                    from++;
112                            }
113                            
114                            interval =
115                                new IntegerSequence.Builder(from, previousValue).by(by).build();
116                            seq.add(interval);
117                    }
118                    
119                    return seq;
120            }
121            
122            public void add(final IntegerSequence interval) {
123                    sequence.add(interval);
124                    numOfInts += interval.size();
125            }
126            
127            public final int getNumOfInts() {
128                    return numOfInts;
129            }
130            
131            public final IntegerSequence get(final int i) {
132                    return sequence.get(i);
133            }
134            
135            public final int size() {
136                    return sequence.size();
137            }
138            
139            public final int getLowerBound() {
140                    if (sequence.size() == 0) {
141                            throw new IllegalStateException("no existing intervals");
142                    }
143                    return sequence.get(0).getFrom();
144            }
145            
146            public final int getUpperBound() {
147                    if (sequence.size() == 0) {
148                            throw new IllegalStateException("no existing intervals");
149                    }
150                    return sequence.get(sequence.size() - 1).getTo();
151            }
152            
153            public int[] toInts() {
154                    final int[] ints = new int[numOfInts];
155                    int from = 0;
156                    for (final IntegerSequence interval : sequence) {
157                            System.arraycopy(interval.toInts(), 0, ints, from, interval.size());
158                            from += interval.size();
159                    }
160                    return ints;
161            }
162            
163            @Override
164            public String toString() {
165                    final StringBuilder sb = new StringBuilder();
166                    
167                    sb.append("Interval# = " + sequence.size() + "\n");
168                    sb.append(Arrays.toString(toInts()));
169                    return sb.toString();
170            }
171    }