001/*
002 * This file is part of OCaml-Java runtime.
003 * Copyright (C) 2007-2013 Xavier Clerc.
004 *
005 * OCaml-Java runtime is free software; you can redistribute it and/or modify
006 * it under the terms of the GNU Lesser General Public License as published by
007 * the Free Software Foundation; either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * OCaml-Java runtime is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Lesser General Public License for more details.
014 *
015 * You should have received a copy of the GNU Lesser General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.ocamljava.runtime.wrappers;
020
021import org.ocamljava.runtime.values.Value;
022
023/**
024 * The {@code OCamlOption} class is the wrapper class for OCaml values of
025 * type {@code 'a * 'b * 'c}.
026 *
027 * @author <a href="mailto:xclerc@ocamljava.org">Xavier Clerc</a>
028 * @version 2.0
029 * @since 2.0
030 */
031public final class OCamlTuple3<T0 extends OCamlValue,
032                               T1 extends OCamlValue,
033                               T2 extends OCamlValue> extends OCamlValue {
034
035    /** Wrapper for nested value. */
036    private final Wrapper<T0> wrapper0;
037
038    /** Wrapper for nested value. */
039    private final Wrapper<T1> wrapper1;
040
041    /** Wrapper for nested value. */
042    private final Wrapper<T2> wrapper2;
043
044    /**
045     * Constructs a new instance wrapping the passed value.
046     * @param w0 wrapper for nested value - should not be {@code null}
047     * @param w1 wrapper for nested value - should not be {@code null}
048     * @param w2 wrapper for nested value - should not be {@code null}
049     * @param v value to wrap - should not be {@code null}
050     */
051    private OCamlTuple3(final Wrapper<T0> w0,
052                        final Wrapper<T1> w1,
053                        final Wrapper<T2> w2,
054                        final Value v) {
055        super(v);
056        assert w0 != null : "null w0";
057        assert w1 != null : "null w1";
058        assert w2 != null : "null w2";
059        this.wrapper0 = w0;
060        this.wrapper1 = w1;
061        this.wrapper2 = w2;
062    } // end constructor(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Value)
063
064    /**
065     * {@inheritDoc}
066     */
067    @Override
068    public Wrapper<? extends OCamlTuple3<T0, T1, T2>> getWrapper() {
069        return OCamlTuple3.wrapper(this.wrapper0,
070                                   this.wrapper1,
071                                   this.wrapper2);
072    } // end method 'getWrapper()'
073
074    /**
075     * {@inheritDoc}
076     */
077    @Override
078    public Wrapper<? extends OCamlValue> getWrapper(final int idx) {
079        switch (idx) {
080        case 0: return this.wrapper0;
081        case 1: return this.wrapper1;
082        case 2: return this.wrapper2;
083        default: return OCamlUnit.WRAPPER;
084        } // end switch
085    } // end method 'getWrapper(int)'
086
087    /**
088     * Returns the first element of the wrapped value.
089     * @return the first element of the wrapped value
090     */
091    public T0 get0() {
092        return this.wrapper0.wrap(this.value.get0());
093    } // end method 'get0()'
094
095    /**
096     * Returns the second element of the wrapped value.
097     * @return the second element of the wrapped value
098     */
099    public T1 get1() {
100        return this.wrapper1.wrap(this.value.get1());
101    } // end method 'get1()'
102
103    /**
104     * Returns the third element of the wrapped value.
105     * @return the third element of the wrapped value
106     */
107    public T2 get2() {
108        return this.wrapper2.wrap(this.value.get2());
109    } // end method 'get2()'
110
111    /**
112     * {@inheritDoc}
113     */
114    @Override
115    public int hashCode() {
116        return this.value.get0().hashCode()
117            + this.value.get1().hashCode()
118            + this.value.get2().hashCode();
119    } // end method 'hashCode()'
120
121    /**
122     * {@inheritDoc}
123     */
124    @Override
125    public boolean equals(final Object obj) {
126        if (obj instanceof OCamlTuple3) {
127            final OCamlTuple3<?, ?, ?> that = (OCamlTuple3) obj;
128            return this.value.get0().equals(that.value.get0())
129                && this.value.get1().equals(that.value.get1())
130                && this.value.get2().equals(that.value.get2());
131        } else {
132            return false;
133        } // end if/else
134    } // end method 'equals(Object)'
135
136    /**
137     * {@inheritDoc}
138     */
139    @Override
140    public String toString() {
141        final StringBuilder sb = new StringBuilder();
142        sb.append("OCamlTuple3(");
143        sb.append(this.wrapper0.wrap(this.value.get0()).toString());
144        sb.append(", ");
145        sb.append(this.wrapper1.wrap(this.value.get1()).toString());
146        sb.append(", ");
147        sb.append(this.wrapper2.wrap(this.value.get2()).toString());
148        sb.append(")");
149        return sb.toString();
150    } // end method 'toString()'
151
152    /**
153     * Constructs a new {@code 'a * 'b * 'c} value, and wraps it.
154     * @param v0 first element of value to wrap
155     * @param v1 second element of value to wrap
156     * @param v2 third element of value to wrap
157     * @return a new {@code OCamlTuple3} instance wrapping the passed values
158     */
159    @SuppressWarnings("unchecked")
160    public static <T0 extends OCamlValue,
161                   T1 extends OCamlValue,
162                   T2 extends OCamlValue>
163        OCamlTuple3<T0, T1, T2> create(final T0 v0,
164                                       final T1 v1,
165                                       final T2 v2) {
166        assert v0 != null : "null v0";
167        assert v1 != null : "null v1";
168        assert v2 != null : "null v2";
169        return new OCamlTuple3<T0, T1, T2>((Wrapper<T0>) v0.getWrapper(),
170                                           (Wrapper<T1>) v1.getWrapper(),
171                                           (Wrapper<T2>) v2.getWrapper(),
172                                           Value.createBlock(0,
173                                                             v0.value(),
174                                                             v1.value(),
175                                                             v2.value()));
176    } // end method 'create(T0, T1, T2)'
177
178    /**
179     * Wraps the passed value.
180     * @param w0 wrapper for nested value - should not be {@code null}
181     * @param w1 wrapper for nested value - should not be {@code null}
182     * @param w2 wrapper for nested value - should not be {@code null}
183     * @param v value to wrap - should not be {@code null}
184     * @return a new {@code OCamlTuple3} instance wrapping the passed value
185     */
186    public static <T0 extends OCamlValue,
187                   T1 extends OCamlValue,
188                   T2 extends OCamlValue>
189        OCamlTuple3<T0, T1, T2> wrap(final Wrapper<T0> w0,
190                                     final Wrapper<T1> w1,
191                                     final Wrapper<T2> w2,
192                                     final Value v) {
193        assert w0 != null : "null w0";
194        assert w1 != null : "null w1";
195        assert w2 != null : "null w2";
196        assert v != null : "null v";
197        return new OCamlTuple3<T0, T1, T2>(w0, w1, w2, v);
198    } // end method 'wrap(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>, Value)'
199
200    /**
201     * Returns a wrapper for {@code OCamlOption} values.
202     * @param w0 wrapper for nested value - should not be {@code null}
203     * @param w1 wrapper for nested value - should not be {@code null}
204     * @param w2 wrapper for nested value - should not be {@code null}
205     * @return a wrapper for {@code OCamlOption} values
206     */
207    @SuppressWarnings("unchecked")
208    public static <T0 extends OCamlValue,
209                   T1 extends OCamlValue,
210                   T2 extends OCamlValue>
211        Wrapper<? extends OCamlTuple3<T0, T1, T2>> wrapper(final Wrapper<T0> w0,
212                                                           final Wrapper<T1> w1,
213                                                           final Wrapper<T2> w2) {
214        return new ComposedWrapper<OCamlTuple3<T0, T1, T2>>(w0, w1, w2) {
215            /**
216             * {@inheritDoc}
217             */
218            @Override
219                public OCamlTuple3<T0, T1, T2> wrap(final Value v) {
220                return new OCamlTuple3<T0, T1, T2>(w0, w1, w2, v);
221            } // end method 'wrap(Value)'
222        }; // end anonymous inner-class
223    } // end method 'wrapper(Wrapper<T0>, Wrapper<T1>, Wrapper<T2>)'
224
225} // end class 'OCamlTuple3'