001/* 002 * Copyright 2018 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.repository.data.holder; 017 018import java.util.Collection; 019import java.util.Map; 020import java.util.Optional; 021 022import org.xml.sax.ContentHandler; 023import org.xml.sax.SAXException; 024 025import org.ametys.plugins.repository.data.UnknownDataException; 026import org.ametys.plugins.repository.data.external.ExternalizableDataProvider.ExternalizableDataStatus; 027import org.ametys.plugins.repository.data.holder.group.ModelAwareComposite; 028import org.ametys.plugins.repository.data.holder.group.Repeater; 029import org.ametys.plugins.repository.data.holder.impl.DataHolderHelper; 030import org.ametys.plugins.repository.data.holder.values.SynchronizationContext; 031import org.ametys.plugins.repository.data.type.ModelItemTypeExtensionPoint; 032import org.ametys.plugins.repository.model.RepeaterDefinition; 033import org.ametys.runtime.model.ElementDefinition; 034import org.ametys.runtime.model.ModelHelper; 035import org.ametys.runtime.model.ModelItem; 036import org.ametys.runtime.model.ModelItemContainer; 037import org.ametys.runtime.model.ViewHelper; 038import org.ametys.runtime.model.ViewItemAccessor; 039import org.ametys.runtime.model.exception.BadDataPathCardinalityException; 040import org.ametys.runtime.model.exception.BadItemTypeException; 041import org.ametys.runtime.model.exception.NotUniqueTypeException; 042import org.ametys.runtime.model.exception.UndefinedItemPathException; 043import org.ametys.runtime.model.exception.UnknownTypeException; 044import org.ametys.runtime.model.type.DataContext; 045import org.ametys.runtime.model.type.ModelItemType; 046 047/** 048 * Interface for data containers with models 049 */ 050public interface ModelAwareDataHolder extends DataHolder 051{ 052 /** Suffix used for the alternative value */ 053 public static final String ALTERNATIVE_SUFFIX = "__alt"; 054 /** Suffix used for the status value */ 055 public static final String STATUS_SUFFIX = "__status"; 056 057 @Override 058 public ModelAwareComposite getComposite(String compositePath) throws IllegalArgumentException, UnknownTypeException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 059 060 /** 061 * Retrieves the local composite at the given path 062 * @param compositePath path of the externalizable composite to retrieve 063 * @return the composite or <code>null</code> if not exists or is empty 064 * @throws IllegalArgumentException if the given composite path is null or empty 065 * @throws BadItemTypeException if the stored value at the given path is not a composite 066 * @throws UndefinedItemPathException if the given composite path is not defined by the model 067 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 068 */ 069 public ModelAwareComposite getLocalComposite(String compositePath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 070 071 /** 072 * Retrieves the external composite at the given path 073 * @param compositePath path of the externalizable composite to retrieve 074 * @return the composite or <code>null</code> if not exists or is empty 075 * @throws IllegalArgumentException if the given composite path is null or empty 076 * @throws BadItemTypeException if the stored value at the given path is not a composite 077 * @throws UndefinedItemPathException if the given composite path is not defined by the model 078 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 079 */ 080 public ModelAwareComposite getExternalComposite(String compositePath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 081 082 /** 083 * Retrieves the repeater at the given path 084 * @param repeaterPath path of the repeater to retrieve 085 * @return the repeater or <code>null</code> if not exists or is empty 086 * @throws IllegalArgumentException if the given repeater path is null or empty 087 * @throws BadItemTypeException if the stored value at the given path is not a repeater 088 * @throws UndefinedItemPathException if the given repeater path is not defined by the model 089 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 090 */ 091 public Repeater getRepeater(String repeaterPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 092 093 /** 094 * Retrieves the local repeater at the given path 095 * @param repeaterPath path of the externalizable repeater to retrieve 096 * @return the repeater or <code>null</code> if not exists or is empty 097 * @throws IllegalArgumentException if the given repeater path is null or empty 098 * @throws BadItemTypeException if the stored value at the given path is not a repeater 099 * @throws UndefinedItemPathException if the given repeater path is not defined by the model 100 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 101 */ 102 public Repeater getLocalRepeater(String repeaterPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 103 104 /** 105 * Retrieves the external repeater at the given path 106 * @param repeaterPath path of the externalizable repeater to retrieve 107 * @return the repeater or <code>null</code> if not exists or is empty 108 * @throws IllegalArgumentException if the given repeater path is null or empty 109 * @throws BadItemTypeException if the stored value at the given path is not a repeater 110 * @throws UndefinedItemPathException if the given repeater path is not defined by the model 111 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 112 */ 113 public Repeater getExternalRepeater(String repeaterPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 114 115 /** 116 * Checks if there is a non empty local value for the data at the given path 117 * @param dataPath path of the externalizable data 118 * @return <code>true</code> if the data at the given path is defined by the model, if there is a non empty local value for the data and if the type of this value matches the type of the definition. <code>false</code> otherwise 119 * @throws IllegalArgumentException if the given data path is null or empty 120 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 121 */ 122 public boolean hasLocalValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException; 123 124 /** 125 * Checks if there is a non empty external value for the data at the given path 126 * @param dataPath path of the externalizable data 127 * @return <code>true</code> if the data at the given path is defined by the model, if there is a non empty external value for the data and if the type of this value matches the type of the definition. <code>false</code> otherwise 128 * @throws IllegalArgumentException if the given data path is null or empty 129 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 130 */ 131 public boolean hasExternalValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException; 132 133 @Override 134 public default boolean hasValue(String dataPath, String dataTypeId) throws IllegalArgumentException, UnknownTypeException, BadDataPathCardinalityException 135 { 136 return hasValue(dataPath); 137 } 138 139 /** 140 * Checks if there is a local value for the data at the given path 141 * @param dataPath path of the externalizable data 142 * @return <code>true</code> if the data at the given path is defined by the model, if there is a local value for the data, even empty, and if the type of this value matches the type of the definition. <code>false</code> otherwise 143 * @throws IllegalArgumentException if the given data path is null or empty 144 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 145 */ 146 public boolean hasLocalValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException; 147 148 /** 149 * Checks if there is an external value for the data at the given path 150 * @param dataPath path of the externalizable data 151 * @return <code>true</code> if the data at the given path is defined by the model, if there is an external value for the data, even empty, and if the type of this value matches the type of the definition. <code>false</code> otherwise 152 * @throws IllegalArgumentException if the given data path is null or empty 153 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 154 */ 155 public boolean hasExternalValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException; 156 157 /** 158 * {@inheritDoc} 159 * @return the names of the data contained by this data holder and that are defined by the model 160 */ 161 @Override 162 public Collection<String> getDataNames(); 163 164 /** 165 * Retrieves the local value of the data at the given path 166 * @param <T> type of the value to retrieve. The type of the value is defined by the model. 167 * @param dataPath path of the externalizable data 168 * @return the local value of the data or <code>null</code> if not exists or is empty. A typed array is returned for multiple empty data, and an empty string is returned for single empty string data 169 * @throws IllegalArgumentException if the given data path is null or empty 170 * @throws BadItemTypeException if the type defined by the model doesn't match the type of the stored value 171 * @throws UndefinedItemPathException if the given data path is not defined by the model 172 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 173 */ 174 public <T> T getLocalValue(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 175 176 /** 177 * Retrieves the external value of the data at the given path 178 * @param <T> type of the value to retrieve. The type of the value is defined by the model. 179 * @param dataPath path of the externalizable data 180 * @return the external value of the data or <code>null</code> if not exists or is empty. A typed array is returned for multiple empty data, and an empty string is returned for single empty string data 181 * @throws IllegalArgumentException if the given data path is null or empty 182 * @throws BadItemTypeException if the type defined by the model doesn't match the type of the stored value 183 * @throws UndefinedItemPathException if the given data path is not defined by the model 184 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 185 */ 186 public <T> T getExternalValue(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 187 188 /** 189 * Retrieves the value of the data at the given path if exists and is not empty, or the default value from the model 190 * @param <T> type of the value to retrieve. The type of the value is defined by the model. 191 * @param dataPath path of the data 192 * @return the value of the data, or the default value from the model if the value does not exist or is empty 193 * @throws IllegalArgumentException if the given data path is null or empty 194 * @throws BadItemTypeException if the type defined by the model doesn't match the type of the stored value 195 * @throws UndefinedItemPathException if the given data path is not defined by the model 196 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 197 */ 198 public <T> T getValueOrDefault(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 199 200 /** 201 * {@inheritDoc} 202 * @param <T> type of the value to retrieve. The type of the value is defined by the model. 203 */ 204 @Override 205 public default <T> T getValueOfType(String dataPath, String dataTypeId) throws IllegalArgumentException, UnknownTypeException, NotUniqueTypeException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException 206 { 207 return getValue(dataPath); 208 } 209 210 /** 211 * {@inheritDoc} 212 * @param <T> type of the value to retrieve. The type of the value is defined by the model. 213 */ 214 @Override 215 public default <T> T getValueOfTypeOrDefault(String dataPath, String dataTypeId, T defaultValue) throws IllegalArgumentException, UnknownTypeException, NotUniqueTypeException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException 216 { 217 return getValueOrDefault(dataPath, defaultValue); 218 } 219 220 /** 221 * Retrieves the value of the data at the given path, allowing multi-valued segments in the path (not necessarily at the last segment) 222 * if there is no indicated entry for a repeater, the values of all the entries are retrieved 223 * if there are multiple values, all data are retrieved in one array 224 * @param <T> type of the value to retrieve 225 * @param dataPath path of the data 226 * @return the value of the data 227 * @throws IllegalArgumentException if the given data path is null or empty 228 * @throws BadItemTypeException if the type defined by the model doesn't match the type of the stored value 229 * @throws UndefinedItemPathException if the given data path is not defined by the model 230 * @throws BadDataPathCardinalityException if the managesMultiples boolean is <code>false</code> and the definition of a part of the data path is multiple. Only the last part can be multiple 231 */ 232 public <T> T getValueWithMultiValuedPathSegments(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 233 234 /** 235 * Retrieves the status of the externalizable data at the given path 236 * Warning: This method won't check that your data is externalizable. But there is no sense to call it with a non externalizable data 237 * @param dataPath path of the externalizable data 238 * @return the status of the externalizable data at the given path 239 * @throws IllegalArgumentException if the given data path is null or empty 240 * @throws BadItemTypeException if the given data path is composed of an item with type defined by the model that doesn't match the type of the stored value 241 * @throws UndefinedItemPathException if the given data path is not defined by the model 242 * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 243 */ 244 public ExternalizableDataStatus getStatus(String dataPath) throws IllegalArgumentException, BadItemTypeException, UndefinedItemPathException, BadDataPathCardinalityException; 245 246 /** 247 * Checks if the definition of the element at the given path is multiple<br/> 248 * {@inheritDoc} 249 * @param dataPath path of the element. No matter if it is a definition or data path (with repeater entry positions) 250 * @return <code>true</code> if the element is multiple, <code>false</code> otherwise 251 */ 252 @Override 253 public default boolean isMultiple(String dataPath) throws IllegalArgumentException, UnknownDataException, UnknownTypeException, NotUniqueTypeException, BadItemTypeException, UndefinedItemPathException 254 { 255 ModelItem item = getDefinition(dataPath); 256 if (item instanceof ElementDefinition) 257 { 258 return ((ElementDefinition) item).isMultiple(); 259 } 260 else if (item instanceof RepeaterDefinition) 261 { 262 // If the given path represents a repeater , but with no specified entry, consider the data as multiple 263 return !DataHolderHelper.isRepeaterEntryPath(dataPath); 264 } 265 else 266 { 267 // Composites are not multiples 268 return false; 269 } 270 } 271 272 /** 273 * Checks if the definition of the element at the given path is multiple<br/> 274 * {@inheritDoc} 275 * @param dataPath path of the element. No matter if it is a definition or data path (with repeater entry positions) 276 * @return <code>true</code> if the element is multiple, <code>false</code> otherwise 277 */ 278 @Override 279 public default boolean isMultiple(String dataPath, String dataTypeId) throws IllegalArgumentException, UnknownDataException, UnknownTypeException, BadItemTypeException, UndefinedItemPathException 280 { 281 return isMultiple(dataPath); 282 } 283 284 /** 285 * {@inheritDoc} 286 * @param dataPath path of the data. No matter if it is a definition or data path (with repeater entry positions) 287 */ 288 @SuppressWarnings("unchecked") 289 @Override 290 public default <X extends ModelItemType> X getType(String dataPath) throws IllegalArgumentException, UnknownDataException, UnknownTypeException, NotUniqueTypeException, UndefinedItemPathException 291 { 292 return (X) getDefinition(dataPath).getType(); 293 } 294 295 @Override 296 public default ModelItemTypeExtensionPoint getModelItemTypeExtensionPoint() 297 { 298 throw new UnsupportedOperationException("ModelAwareDataHolder does not need an extension point for managed types. The model itself defines the types of the data."); 299 } 300 301 /** 302 * Retrieves the data holder's model 303 * @return the data holder's model 304 */ 305 public Collection<? extends ModelItemContainer> getModel(); 306 307 /** 308 * Retrieves the definition of the data at the given path 309 * @param path path of the data. No matter if it is a definition or data path (with repeater entry positions) 310 * @return the definition of the data 311 * @throws IllegalArgumentException if the given path is null or empty 312 * @throws UndefinedItemPathException if the given path is not defined by the model 313 */ 314 public default ModelItem getDefinition(String path) throws IllegalArgumentException, UndefinedItemPathException 315 { 316 return ModelHelper.getModelItem(path, getModel()); 317 } 318 319 /** 320 * Checks if there is a definition at the given path 321 * @param path path of the data. No matter if it is a definition or data path (with repeater entry positions) 322 * @return <code>true</code> if there is definition at the given path, <code>false</code> otherwise 323 * @throws IllegalArgumentException if the given path is null or empty 324 */ 325 public default boolean hasDefinition(String path) throws IllegalArgumentException 326 { 327 try 328 { 329 getDefinition(path); 330 return true; 331 } 332 catch (UndefinedItemPathException e) 333 { 334 return false; 335 } 336 } 337 338 /** 339 * {@inheritDoc} 340 * <br />Generates SAX events only for the data in the model 341 */ 342 @Override 343 public default void dataToSAX(ContentHandler contentHandler) throws SAXException, UnknownTypeException, NotUniqueTypeException, BadItemTypeException 344 { 345 DataHolder.super.dataToSAX(contentHandler); 346 } 347 348 /** 349 * {@inheritDoc} 350 * <br />Generates SAX events only for the data in the model 351 */ 352 @Override 353 public default void dataToSAX(ContentHandler contentHandler, DataContext context) throws SAXException, UnknownTypeException, NotUniqueTypeException, BadItemTypeException 354 { 355 ViewItemAccessor viewItemAccessor = ViewHelper.createViewItemAccessor(getModel()); 356 dataToSAX(contentHandler, viewItemAccessor, context); 357 } 358 359 /** 360 * Generates SAX events for the data in the given view in the current {@link DataHolder} 361 * @param contentHandler the {@link ContentHandler} that will receive the SAX events 362 * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items for which generate SAX events 363 * @throws SAXException if an error occurs during the SAX events generation 364 * @throws BadItemTypeException if the saxed value's type does not matches the stored data 365 */ 366 public default void dataToSAX(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor) throws SAXException, BadItemTypeException 367 { 368 dataToSAX(contentHandler, viewItemAccessor, DataContext.newInstance()); 369 } 370 371 /** 372 * Generates SAX events for the data in the given view in the current {@link DataHolder} 373 * @param contentHandler the {@link ContentHandler} that will receive the SAX events 374 * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items for which generate SAX events 375 * @param context The context of the data to SAX 376 * @throws SAXException if an error occurs during the SAX events generation 377 * @throws BadItemTypeException if the saxed value's type does not matches the stored data 378 */ 379 public void dataToSAX(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor, DataContext context) throws SAXException, BadItemTypeException; 380 381 /** 382 * Generates SAX events for the data in the given view in edition mode in the current {@link DataHolder} 383 * @param contentHandler the {@link ContentHandler} that will receive the SAX events 384 * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items for which generate SAX events 385 * @param context The context of the data to SAX 386 * @throws SAXException if an error occurs during the SAX events generation 387 * @throws BadItemTypeException if the saxed value's type does not matches the stored data 388 */ 389 public void dataToSAXForEdition(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor, DataContext context) throws SAXException, BadItemTypeException; 390 391 /** 392 * Convert the data in the model of the current {@link DataHolder} 393 * @return The data of the current {@link DataHolder} as JSON 394 * @throws BadItemTypeException if the value's type does not matches the stored data 395 */ 396 397 /** 398 * {@inheritDoc} 399 * <br />Only converts the data in the model 400 */ 401 public default Map<String, Object> dataToJSON() throws BadItemTypeException 402 { 403 return DataHolder.super.dataToJSON(); 404 } 405 406 /** 407 * {@inheritDoc} 408 * <br />Only converts the data in the model 409 */ 410 public default Map<String, Object> dataToJSON(DataContext context) throws BadItemTypeException 411 { 412 ViewItemAccessor viewItemAccessor = ViewHelper.createViewItemAccessor(getModel()); 413 return dataToJSON(viewItemAccessor, context); 414 } 415 416 /** 417 * Convert the data in the given view of the current {@link DataHolder} 418 * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items to convert 419 * @return The data of the given view as JSON 420 * @throws BadItemTypeException if the value's type does not matches the stored data 421 */ 422 public default Map<String, Object> dataToJSON(ViewItemAccessor viewItemAccessor) throws BadItemTypeException 423 { 424 return dataToJSON(viewItemAccessor, DataContext.newInstance()); 425 } 426 427 /** 428 * Convert the data in the given view of the current {@link DataHolder} 429 * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items to convert 430 * @param context The context of the data to convert 431 * @return The data of the given view as JSON 432 * @throws BadItemTypeException if the value's type does not matches the stored data 433 */ 434 public Map<String, Object> dataToJSON(ViewItemAccessor viewItemAccessor, DataContext context) throws BadItemTypeException; 435 436 /** 437 * Convert the data in the given view in edition mode in the current {@link DataHolder} 438 * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items to convert 439 * @param context The context of the data to convert 440 * @return The data of the given view as JSON 441 * @throws BadItemTypeException if the value's type does not matches the stored data 442 */ 443 public Map<String, Object> dataToJSONForEdition(ViewItemAccessor viewItemAccessor, DataContext context) throws BadItemTypeException; 444 445 /** 446 * Retrieves all data of this DataHolder as a typed-values Map. 447 * @return a Map containing all data. 448 * @throws BadItemTypeException if the value's type does not matches the stored data 449 */ 450 public default Map<String, Object> dataToMap() throws BadItemTypeException 451 { 452 return dataToMap(DataContext.newInstance()); 453 } 454 455 /** 456 * Retrieves all data of this DataHolder as a typed-values Map. 457 * @param context The context of the data 458 * @return a Map containing all data. 459 * @throws BadItemTypeException if the value's type does not matches the stored data 460 */ 461 public default Map<String, Object> dataToMap(DataContext context) throws BadItemTypeException 462 { 463 ViewItemAccessor viewItemAccessor = ViewHelper.createViewItemAccessor(getModel()); 464 return dataToMap(viewItemAccessor, context); 465 } 466 467 /** 468 * Retrieves data of this DataHolder as a typed-values Map. 469 * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items to include in the resulting Map 470 * @return a Map containing all data. 471 * @throws BadItemTypeException if the value's type does not matches the stored data 472 */ 473 public default Map<String, Object> dataToMap(ViewItemAccessor viewItemAccessor) throws BadItemTypeException 474 { 475 return dataToMap(viewItemAccessor, DataContext.newInstance()); 476 } 477 478 /** 479 * Retrieves data of this DataHolder as a typed-values Map. 480 * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items to include in the resulting Map 481 * @param context The context of the data 482 * @return a Map containing all data. 483 * @throws BadItemTypeException if the value's type does not matches the stored data 484 */ 485 public Map<String, Object> dataToMap(ViewItemAccessor viewItemAccessor, DataContext context) throws BadItemTypeException; 486 487 /** 488 * {@inheritDoc} 489 * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value 490 */ 491 @Override 492 public default boolean hasDifferences(Map<String, Object> values) throws UnknownTypeException, NotUniqueTypeException, BadItemTypeException 493 { 494 ViewItemAccessor viewItemAccessor = DataHolderHelper.createViewItemAccessorFromValues(getModel(), values); 495 return hasDifferences(viewItemAccessor, values); 496 } 497 498 /** 499 * Check if there are differences between the given values and the current ones 500 * @param values the values to check 501 * @param context the context of the synchronization 502 * @return <code>true</code> if there are differences, <code>false</code> otherwise 503 * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value 504 */ 505 public default boolean hasDifferences(Map<String, Object> values, SynchronizationContext context) throws BadItemTypeException 506 { 507 ViewItemAccessor viewItemAccessor = DataHolderHelper.createViewItemAccessorFromValues(getModel(), values); 508 return hasDifferences(viewItemAccessor, values, context); 509 } 510 511 /** 512 * Check if there are differences between the given values and the current ones 513 * @param viewItemAccessor The {@link ViewItemAccessor} for all items to check 514 * @param values the values to check 515 * @return <code>true</code> if there are differences, <code>false</code> otherwise 516 * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value 517 */ 518 public boolean hasDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values) throws BadItemTypeException; 519 520 /** 521 * Check if there are differences between the given values and the current ones 522 * @param viewItemAccessor The {@link ViewItemAccessor} for all items to check 523 * @param values the values to check 524 * @param context the context of the synchronization 525 * @return <code>true</code> if there are differences, <code>false</code> otherwise 526 * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value 527 */ 528 public boolean hasDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values, SynchronizationContext context) throws BadItemTypeException; 529 530 /** 531 * Get the collection of model items where there are differences between the given values and the current ones 532 * @param values the values to check 533 * @return a collection of model items with differences 534 * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value 535 */ 536 public default Collection<ModelItem> getDifferences(Map<String, Object> values) throws BadItemTypeException 537 { 538 ViewItemAccessor viewItemAccessor = DataHolderHelper.createViewItemAccessorFromValues(getModel(), values); 539 return getDifferences(viewItemAccessor, values); 540 } 541 542 /** 543 * Get the collection of model items where there are differences between the given values and the current ones 544 * @param values the values to check 545 * @param context the context of the synchronization 546 * @return a collection of model items with differences 547 * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value 548 */ 549 public default Collection<ModelItem> getDifferences(Map<String, Object> values, SynchronizationContext context) throws BadItemTypeException 550 { 551 ViewItemAccessor viewItemAccessor = DataHolderHelper.createViewItemAccessorFromValues(getModel(), values); 552 return getDifferences(viewItemAccessor, values, context); 553 } 554 555 /** 556 * Get the collection of model items where there are differences between the given values and the current ones 557 * @param viewItemAccessor The {@link ViewItemAccessor} for all items to check 558 * @param values the values to check 559 * @return a collection of model items with differences 560 * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value 561 */ 562 public Collection<ModelItem> getDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values) throws BadItemTypeException; 563 564 /** 565 * Get the collection of model items where there are differences between the given values and the current ones 566 * @param viewItemAccessor The {@link ViewItemAccessor} for all items to check 567 * @param values the values to check 568 * @param context the context of the synchronization 569 * @return a collection of model items with differences 570 * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value 571 */ 572 public Collection<ModelItem> getDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values, SynchronizationContext context) throws BadItemTypeException; 573 574 @Override 575 public Optional<? extends ModelAwareDataHolder> getParentDataHolder(); 576 577 @Override 578 public ModelAwareDataHolder getRootDataHolder(); 579}