1 /*
2 * Copyright 2007, 2008, 2009 Ange Optimization ApS
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package eu.simuline.octave.type;
17
18 import java.util.Map;
19 import java.util.TreeMap;
20
21 import eu.simuline.octave.exception.OctaveClassCastException;
22 import eu.simuline.octave.type.cast.Cast;
23
24 /**
25 * 1x1 struct. JavaOctave does not support the multidimensional structs
26 * that octave has.
27 */
28 public final class OctaveStruct implements OctaveObject {
29
30
31 private static final int PRIME = 31;
32
33 // **** ER: I really have doubts that data can be null.
34 private final Map<String, OctaveObject> data;
35
36 /**
37 * Create empty struct.
38 */
39 public OctaveStruct() {
40 // Use a TreeMap in order to get a stable serialization
41 // (I might want to use HashMap here and sort in OctaveIO.toText())
42 this.data = new TreeMap<String, OctaveObject>();
43 }
44
45 /**
46 * Create struct from data.
47 *
48 * @param data
49 * this data will be referenced, not copied
50 */
51 public OctaveStruct(final Map<String, OctaveObject> data) {
52 this.data = data;
53 }
54
55 /**
56 * @param name
57 * @param value
58 */
59 @SuppressWarnings("PMD.AvoidThrowingNullPointerException")
60 public void set(final String name, final OctaveObject value) {
61 if (value == null) {
62 throw new NullPointerException
63 ("Cannot set field with null-name in octave struct. ");
64 }
65 this.data.put(name, value);
66 }
67
68 /**
69 * Get object from struct as plain OctaveObject.
70 * If you want to cast the object to a special type use
71 * {@link OctaveStruct#get(Class, String)}.
72 *
73 * @param key
74 * @return
75 * shallow copy of value for this key, or null if key isn't there.
76 */
77 public OctaveObject get(final String key) {
78 final OctaveObject value = this.data.get(key);
79 return (value == null) ? null : value.shallowCopy();
80 }
81
82 /**
83 * @param castClass
84 * Class to cast to
85 * @param key
86 * @param <T>
87 * @return shallow copy of value for this key, or null if key isn't there.
88 * @throws OctaveClassCastException
89 * if the object can not be cast to a castClass
90 */
91 public <T extends OctaveObject> T get(final Class<T> castClass,
92 final String key) {
93 return Cast.cast(castClass, get(key));
94 }
95
96 /**
97 * @return reference to internal map
98 */
99 public Map<String, OctaveObject> getData() {
100 return this.data;
101 }
102
103 @Override
104 public OctaveStruct shallowCopy() {
105 return new OctaveStruct(this.data);
106 }
107
108 @Override
109 public int hashCode() {
110 int result = 1;
111 result = PRIME * result + ((this.data == null) ? 0 : data.hashCode());
112 return result;
113 }
114
115 @Override
116 public boolean equals(final Object obj) {
117 if (this == obj) {
118 return true;
119 }
120 if (obj == null) {
121 return false;
122 }
123 if (getClass() != obj.getClass()) {
124 return false;
125 }
126 final OctaveStruct/../../eu/simuline/octave/type/OctaveStruct.html#OctaveStruct">OctaveStruct other = (OctaveStruct) obj;
127 if (this.data == null) {
128 return other.data == null;
129 // if (other.data != null) {
130 // return false;
131 // }
132 } else {
133 return this.data.equals(other.data);
134 // if (!this.data.equals(other.data)) {
135 // return false;
136 // }
137 }
138 // return true;
139 }
140
141 }