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 option}. 026 * 027 * @author <a href="mailto:xclerc@ocamljava.org">Xavier Clerc</a> 028 * @version 2.0 029 * @since 2.0 030 */ 031public final class OCamlOption<T extends OCamlValue> extends OCamlValue { 032 033 /** Wrapper for nested value. */ 034 private final Wrapper<T> wrapper; 035 036 /** 037 * Constructs a new instance wrapping the passed value. 038 * @param w wrapper for nested value - may be {@code null} for {@code None} values 039 * @param v value to wrap - should not be {@code null} 040 */ 041 private OCamlOption(final Wrapper<T> w, final Value v) { 042 super(v); 043 assert w != null : "null w"; 044 this.wrapper = w; 045 } // end constructor(Wrapper<T>, Value) 046 047 /** 048 * {@inheritDoc} 049 */ 050 @Override 051 public Wrapper<? extends OCamlOption<T>> getWrapper() { 052 return OCamlOption.wrapper(this.wrapper); 053 } // end method 'getWrapper()' 054 055 /** 056 * {@inheritDoc} 057 */ 058 @Override 059 public Wrapper<? extends OCamlValue> getWrapper(final int idx) { 060 switch (idx) { 061 case 0: return this.wrapper; 062 default: return OCamlUnit.WRAPPER; 063 } // end switch 064 } // end method 'getWrapper(int)' 065 066 /** 067 * Returns the wrapped value. 068 * @return the wrapped value if some, or {@code null} if none 069 */ 070 public T get() { 071 if (this.value.isLong()) { 072 return null; 073 } else { 074 return this.wrapper.wrap(this.value.get0()); 075 } // end if/else 076 } // end method 'get()' 077 078 /** 079 * {@inheritDoc} 080 */ 081 @Override 082 public int hashCode() { 083 return this.value.hashCode(); 084 } // end method 'hashCode()' 085 086 /** 087 * {@inheritDoc} 088 */ 089 @Override 090 public boolean equals(final Object obj) { 091 if (obj instanceof OCamlOption) { 092 final OCamlOption<?> that = (OCamlOption) obj; 093 if (this.value.isLong()) { 094 if (that.value.isLong()) { 095 return this.value.asLong() == that.value.asLong(); 096 } else { 097 return false; 098 } // end if/else 099 } else { 100 if (that.value.isLong()) { 101 return false; 102 } else { 103 return this.value.get0() == that.value.get0(); 104 } // end if/else 105 } // end if/else 106 } else { 107 return false; 108 } // end if/else 109 } // end method 'equals(Object)' 110 111 /** 112 * {@inheritDoc} 113 */ 114 @Override 115 public String toString() { 116 final StringBuilder sb = new StringBuilder(); 117 sb.append("OCamlOption("); 118 if (this.value.isLong()) { 119 sb.append("None"); 120 } else { 121 sb.append("Some("); 122 sb.append(this.wrapper.wrap(this.value.get0()).toString()); 123 sb.append(")"); 124 } // end if/else 125 sb.append(")"); 126 return sb.toString(); 127 } // end method 'toString()' 128 129 /** 130 * Constructs a new {@code 'a option} value, and wraps it. 131 * @param v value to wrap 132 * @return a new {@code OCamlOption} instance wrapping the passed value 133 * as {@code Some v} 134 */ 135 @SuppressWarnings("unchecked") 136 public static <T extends OCamlValue> OCamlOption<T> create(final T v) { 137 return new OCamlOption<T>((Wrapper<T>) v.getWrapper(), 138 Value.createBlock(0, v.value())); 139 } // end method 'create(T)' 140 141 /** 142 * Constructs a new {@code 'a option} value, and wraps it. 143 * @return a new {@code OCamlOption} instance wrapping the passed value 144 * as {@code None} 145 */ 146 @SuppressWarnings("unchecked") 147 public static <T extends OCamlValue> OCamlOption<T> create() { 148 return new OCamlOption<T>((Wrapper<T>) OCamlUnit.WRAPPER, Value.ZERO); 149 } // end method 'create(T)' 150 151 /** 152 * Wraps the passed value. 153 * @param w wrapper for nested value - should not be {@code null} 154 * @param v value to wrap - should not be {@code null} 155 * @return a new {@code OCamlOption} instance wrapping the passed value 156 */ 157 public static <T extends OCamlValue> OCamlOption<T> wrap(final Wrapper<T> w, 158 final Value v) { 159 assert v != null : "null v"; 160 return new OCamlOption<T>(w, v); 161 } // end method 'wrap(Wrapper<T>, Value)' 162 163 /** 164 * Returns a wrapper for {@code OCamlOption} values. 165 * @param w wrapper for nested value - should not be {@code null} 166 * @return a wrapper for {@code OCamlOption} values 167 */ 168 @SuppressWarnings("unchecked") 169 public static <T extends OCamlValue> Wrapper<? extends OCamlOption<T>> wrapper(final Wrapper<T> w) { 170 return new ComposedWrapper<OCamlOption<T>>() { 171 /** 172 * {@inheritDoc} 173 */ 174 @Override 175 public OCamlOption<T> wrap(final Value v) { 176 return new OCamlOption<T>(w, v); 177 } // end method 'wrap(Value)' 178 }; // end anonymous inner-class 179 } // end method 'wrapper(Wrapper<T>)' 180 181} // end class 'OCamlOption'