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