1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.healthmarketscience.jackcess.impl;
18
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.IdentityHashMap;
23 import java.util.List;
24 import java.util.Objects;
25 import java.util.Set;
26
27 import com.healthmarketscience.jackcess.PropertyMap;
28 import com.healthmarketscience.jackcess.TableNameMap;
29
30
31
32
33
34
35
36
37 public class TableNameMapImpl extends NameMapImpl implements TableNameMap
38 {
39
40 private final TableImpl _table;
41
42 private TableNameMapImpl(byte[] bytes, TableImpl table) throws IOException {
43 super(bytes);
44 _table = table;
45 }
46
47
48
49
50
51
52
53 public static TableNameMapImpl read(byte[] bytes, TableImpl table)
54 throws IOException
55 {
56 return new TableNameMapImpl(bytes, table);
57 }
58
59 @Override
60 protected boolean isWritable() {
61 return true;
62 }
63
64 @Override
65 public Record getTableRecord() {
66 return findTableRecord();
67 }
68
69 private RecordImpl findTableRecord() {
70 for(RecordImpl rec : _records) {
71 if(rec._type == TABLE_TYPE) {
72 return rec;
73 }
74 }
75 return null;
76 }
77
78 @Override
79 public Record getColumnRecord(String name) {
80 return findColumnRecord(name);
81 }
82
83 private RecordImpl findColumnRecord(String name) {
84 for(RecordImpl rec : _records) {
85 if((rec._type == COLUMN_TYPE) && rec._name.equalsIgnoreCase(name)) {
86 return rec;
87 }
88 }
89 return null;
90 }
91
92 @Override
93 public List<Record> getReferences() {
94 return getRecords(REFERENCE_TYPE);
95 }
96
97 @Override
98 public Record addColumn(String name, String guid) {
99 Objects.requireNonNull(name, "name");
100 Objects.requireNonNull(guid, "guid");
101 RecordImpl tableRec = findTableRecord();
102 if(tableRec == null) {
103 throw new IllegalStateException("Name map has no table record");
104 }
105
106 RecordImpl rec = new RecordImpl(COLUMN_TYPE, toGuidBytes(guid),
107 tableRec._guid.clone(), name);
108 int idx = _records.size();
109 for(int i = 0; i < _records.size(); ++i) {
110 if(_records.get(i)._type == END_TYPE) {
111 idx = i;
112 break;
113 }
114 }
115 _records.add(idx, rec);
116 return rec;
117 }
118
119 @Override
120 public Record removeColumn(String name) {
121 RecordImpl rec = findColumnRecord(name);
122 if(rec != null) {
123 _records.remove(rec);
124 }
125 return rec;
126 }
127
128 @Override
129 public List<Mismatch> findMismatches() throws IOException {
130 TableImpl table = _table;
131 List<Mismatch> mismatches = new ArrayList<>();
132
133 RecordImpl tableRec = findTableRecord();
134 if(tableRec != null) {
135 String guid = getGuid(table.getProperties());
136 if((guid != null) && !guid.equalsIgnoreCase(tableRec.getGuid())) {
137 mismatches.add(new MismatchImpl(MismatchType.GUID_DIFFERS, table,
138 null, tableRec));
139 }
140 if(!tableRec._name.equals(table.getName())) {
141 mismatches.add(new MismatchImpl(MismatchType.NAME_DIFFERS, table,
142 null, tableRec));
143 }
144 }
145
146
147
148 Set<RecordImpl> matched = Collections.newSetFromMap(
149 new IdentityHashMap<>());
150 List<ColumnImpl> unmatchedCols = new ArrayList<>();
151 for(ColumnImpl col : table.getColumns()) {
152 String guid = getGuid(col.getProperties());
153 RecordImpl rec = ((guid != null) ? findRecord(guid) : null);
154 if((rec == null) || (rec._type != COLUMN_TYPE)) {
155 unmatchedCols.add(col);
156 continue;
157 }
158 matched.add(rec);
159 if(!rec._name.equals(col.getName())) {
160 mismatches.add(new MismatchImpl(MismatchType.NAME_DIFFERS, table,
161 col, rec));
162 }
163 }
164
165 for(ColumnImpl col : unmatchedCols) {
166 RecordImpl rec = findUnmatchedColumnRecord(col.getName(), matched);
167 if(rec == null) {
168 mismatches.add(new MismatchImpl(MismatchType.MISSING_RECORD, table,
169 col, null));
170 continue;
171 }
172 matched.add(rec);
173 if(getGuid(col.getProperties()) != null) {
174 mismatches.add(new MismatchImpl(MismatchType.GUID_DIFFERS, table,
175 col, rec));
176 }
177 }
178
179 for(RecordImpl rec : _records) {
180 if((rec._type == COLUMN_TYPE) && !matched.contains(rec)) {
181 mismatches.add(new MismatchImpl(MismatchType.MISSING_OBJECT, table,
182 null, rec));
183 }
184 }
185
186 return mismatches;
187 }
188
189 private RecordImpl findUnmatchedColumnRecord(String name,
190 Set<RecordImpl> matched) {
191 for(RecordImpl rec : _records) {
192 if((rec._type == COLUMN_TYPE) && rec._name.equalsIgnoreCase(name) &&
193 !matched.contains(rec)) {
194 return rec;
195 }
196 }
197 return null;
198 }
199
200 @Override
201 public void save() throws IOException {
202 PropertyMap props = _table.getProperties();
203 props.put(PropertyMap.NAME_MAP_PROP, toBytes());
204 props.save();
205 }
206 }