2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-2018 Ericsson. All rights reserved.
4 * Modifications Copyright (C) 2019 Nordix Foundation.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.apex.model.policymodel.concepts;
24 import java.util.List;
25 import java.util.Map.Entry;
27 import java.util.TreeSet;
28 import javax.persistence.CascadeType;
29 import javax.persistence.Entity;
30 import javax.persistence.JoinColumn;
31 import javax.persistence.JoinColumns;
32 import javax.persistence.OneToOne;
33 import javax.persistence.Table;
34 import javax.xml.bind.Marshaller;
35 import javax.xml.bind.Unmarshaller;
36 import javax.xml.bind.annotation.XmlAccessType;
37 import javax.xml.bind.annotation.XmlAccessorType;
38 import javax.xml.bind.annotation.XmlElement;
39 import javax.xml.bind.annotation.XmlRootElement;
40 import javax.xml.bind.annotation.XmlType;
41 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
42 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
43 import org.onap.policy.apex.model.basicmodel.concepts.AxConcept;
44 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
45 import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInformation;
46 import org.onap.policy.apex.model.basicmodel.concepts.AxModel;
47 import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
48 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage;
49 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
50 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult;
51 import org.onap.policy.apex.model.basicmodel.handling.KeyInfoMarshalFilter;
52 import org.onap.policy.apex.model.basicmodel.service.ModelService;
53 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
54 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbums;
55 import org.onap.policy.apex.model.contextmodel.concepts.AxContextModel;
56 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
57 import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
58 import org.onap.policy.apex.model.eventmodel.concepts.AxEvents;
59 import org.onap.policy.apex.model.eventmodel.concepts.AxField;
60 import org.onap.policy.apex.model.policymodel.handling.EmptyAlbumsAdapter;
61 import org.onap.policy.common.utils.validation.Assertions;
64 * A container class for an Apex policy model. This class is a container class that allows an Apex
65 * model to be constructed that contains definitions of all the context, event, and policy concepts
66 * required to run policies in Apex. The model contains schema definitions, definitions of events
67 * and context albums that use those schemas, definitions of tasks for policies and definitions of
68 * the policies themselves.
70 * <p>An Apex policy model is an important artifact in Apex. At editing time, an Apex editor creates
71 * and edits a policy model and a policy model is loaded into and is executed by an Apex engine.
72 * Therefore, an Apex model and the set of policies that it holds is the way that the policy domain
73 * that an Apex engine or a group of Apex engines executes across is expressed, both at design time
74 * and run time. The Apex deployment system is responsible for deploying Apex models to and the
75 * context they need the appropriate engines for execution.
77 * <p>Model registration is carried out by calling the {@code register()} method, which registers the
78 * policy model and all its constituent containers with the model service. The containers for
79 * context schemas, events, context albums, tasks, policies, and key information are all registered.
81 * <p>Once a policy model is composed, the overall structure of the policy model and all its references
82 * can be validated. During validation of a policy model, the validation checks listed below are
85 * <li>The policy model is validated as an Apex model, which validates the existence, correctness,
86 * and duplication of all keys in the model as well as validating the key information of the keys,
87 * see validation in {@link AxModel}
88 * <li>The schemas in the model must be valid, see validation in {@link AxContextSchemas}
89 * <li>The context albums in the model must be valid, see validation in {@link AxContextAlbums}
90 * <li>The tasks in the model must be valid, see validation in {@link AxTasks}
91 * <li>The policies in the model must be valid, see validation in {@link AxPolicies}
92 * <li>The events in the model must be valid, see validation in {@link AxEvents}
93 * <li>The context schemas referred to in each field in every event must exist
94 * <li>The context schemas referred to in every context album must exist
95 * <li>The context schemas referred to in every task input field and output field must exist
96 * <li>The context albums referred to in every task must exist
97 * <li>The context albums referred to in every state must exist
98 * <li>The trigger event referred to in every state must exist
99 * <li>The default task referred to in every state must exist
100 * <li>In a state, an event that triggers a task must contain all the input fields required by that
102 * <li>In a state, an event that is emitted by a task must contain all the output fields produced by
104 * <li>All tasks referred to by a state must exist
105 * <li>All events referred to on direct state outputs must exist
109 @Table(name = "AxPolicyModel")
111 @XmlRootElement(name = "apexPolicyModel", namespace = "http://www.onap.org/policy/apex-pdp")
112 @XmlAccessorType(XmlAccessType.FIELD)
113 @XmlType(name = "AxPolicyModel", namespace = "http://www.onap.org/policy/apex-pdp",
114 propOrder = {"policies", "tasks", "events", "albums", "schemas"})
116 public class AxPolicyModel extends AxModel {
117 private static final String DOES_NOT_EXIST = " does not exist";
119 private static final long serialVersionUID = 8800599637708309945L;
122 @OneToOne(cascade = CascadeType.ALL)
123 @JoinColumns({@JoinColumn(name = "policiesName", referencedColumnName = "name"),
124 @JoinColumn(name = "policiesVersion", referencedColumnName = "version")})
125 @XmlElement(name = "policies", required = true)
126 private AxPolicies policies;
128 @OneToOne(cascade = CascadeType.ALL)
129 @JoinColumns({@JoinColumn(name = "tasksName", referencedColumnName = "name"),
130 @JoinColumn(name = "tasksVersion", referencedColumnName = "version")})
131 @XmlElement(name = "tasks", required = true)
132 private AxTasks tasks;
134 @OneToOne(cascade = CascadeType.ALL)
135 @JoinColumns({@JoinColumn(name = "eventsName", referencedColumnName = "name"),
136 @JoinColumn(name = "eventsVersion", referencedColumnName = "version")})
137 @XmlElement(name = "events", required = true)
138 private AxEvents events;
140 @OneToOne(cascade = CascadeType.ALL)
141 @JoinColumns({@JoinColumn(name = "albumsName", referencedColumnName = "name"),
142 @JoinColumn(name = "albumsVersion", referencedColumnName = "version")})
143 @XmlElement(name = "albums", required = false)
144 @XmlJavaTypeAdapter(EmptyAlbumsAdapter.class)
145 private AxContextAlbums albums;
147 @OneToOne(cascade = CascadeType.ALL)
148 @JoinColumns({@JoinColumn(name = "schemasName", referencedColumnName = "name"),
149 @JoinColumn(name = "schemasVersion", referencedColumnName = "version")})
150 @XmlElement(name = "schemas", required = true)
151 private AxContextSchemas schemas;
155 * The Default Constructor creates a policy model with a null key and empty containers for
156 * schemas, key information, events, context albums, tasks and policies.
158 public AxPolicyModel() {
159 this(new AxArtifactKey());
165 * @param copyConcept the concept to copy from
167 public AxPolicyModel(final AxPolicyModel copyConcept) {
172 * The Keyed Constructor creates a policy model with the given key and empty containers for
173 * schemas, key information, events, context albums, tasks and policies.
177 public AxPolicyModel(final AxArtifactKey key) {
178 this(key, new AxContextSchemas(new AxArtifactKey(key.getName() + "_Schemas", key.getVersion())),
179 new AxKeyInformation(new AxArtifactKey(key.getName() + "_KeyInfo", key.getVersion())),
180 new AxEvents(new AxArtifactKey(key.getName() + "_Events", key.getVersion())),
181 new AxContextAlbums(new AxArtifactKey(key.getName() + "_Albums", key.getVersion())),
182 new AxTasks(new AxArtifactKey(key.getName() + "_Tasks", key.getVersion())),
183 new AxPolicies(new AxArtifactKey(key.getName() + "_Policies", key.getVersion())));
187 * This Constructor creates a policy model with all of its fields specified.
189 * @param key the key of the policy model
190 * @param schemas the context schema container for the policy model
191 * @param keyInformation the key information container for the policy model
192 * @param events the event container for the policy model
193 * @param albums the context album container for the policy model
194 * @param tasks the task container for the policy model
195 * @param policies the policy container for the policy model
197 public AxPolicyModel(final AxArtifactKey key, final AxContextSchemas schemas, final AxKeyInformation keyInformation,
198 final AxEvents events, final AxContextAlbums albums, final AxTasks tasks, final AxPolicies policies) {
199 super(key, keyInformation);
200 Assertions.argumentNotNull(schemas, "schemas may not be null");
201 Assertions.argumentNotNull(events, "events may not be null");
202 Assertions.argumentNotNull(albums, "albums may not be null");
203 Assertions.argumentNotNull(tasks, "tasks may not be null");
204 Assertions.argumentNotNull(policies, "policies may not be null");
206 this.schemas = schemas;
207 this.events = events;
208 this.albums = albums;
210 this.policies = policies;
217 public void register() {
219 ModelService.registerModel(AxContextSchemas.class, getSchemas());
220 ModelService.registerModel(AxEvents.class, getEvents());
221 ModelService.registerModel(AxContextAlbums.class, getAlbums());
222 ModelService.registerModel(AxTasks.class, getTasks());
223 ModelService.registerModel(AxPolicies.class, getPolicies());
224 ModelService.registerModel(AxPolicyModel.class, this);
231 public List<AxKey> getKeys() {
232 final List<AxKey> keyList = super.getKeys();
234 keyList.addAll(schemas.getKeys());
235 keyList.addAll(events.getKeys());
236 keyList.addAll(albums.getKeys());
237 keyList.addAll(tasks.getKeys());
238 keyList.addAll(policies.getKeys());
244 * Gets a context model from the policy model.
246 * @return the context model
248 public AxContextModel getContextModel() {
249 return new AxContextModel(new AxArtifactKey(albums.getKey().getName() + "_Model", albums.getKey().getVersion()),
250 getSchemas(), getAlbums(), getKeyInformation());
254 * Gets the policy container from the policy model.
256 * @return the policy container with all the policies in the model
258 public AxPolicies getPolicies() {
263 * Sets the policy container for the policy model.
265 * @param policies the policy container with all the policies in the model
267 public void setPolicies(final AxPolicies policies) {
268 Assertions.argumentNotNull(policies, "policies may not be null");
269 this.policies = policies;
273 * Gets the task container from the policy model.
275 * @return the task container with all the tasks in the model
277 public AxTasks getTasks() {
282 * Sets the task container from the policy model.
284 * @param tasks the task container with all the tasks in the model
286 public void setTasks(final AxTasks tasks) {
287 Assertions.argumentNotNull(tasks, "tasks may not be null");
292 * Gets the event container from the policy model.
294 * @return the event container with all the events in the model
296 public AxEvents getEvents() {
301 * Sets the event container from the policy model.
303 * @param events the event container with all the events in the model
305 public void setEvents(final AxEvents events) {
306 Assertions.argumentNotNull(events, "events may not be null");
307 this.events = events;
311 * Gets the context album container from the policy model.
313 * @return the context album container with all the context albums in the model
315 public AxContextAlbums getAlbums() {
320 * Sets the context album container from the policy model.
322 * @param albums the context album container with all the context albums in the model
324 public void setAlbums(final AxContextAlbums albums) {
325 Assertions.argumentNotNull(albums, "albums may not be null");
326 this.albums = albums;
330 * Gets the context schema container from the policy model.
332 * @return the context schema container with all the context schemas in the model
334 public AxContextSchemas getSchemas() {
339 * Sets the context schema container from the policy model.
341 * @param schemas the context schema container with all the context schemas in the model
343 public void setSchemas(final AxContextSchemas schemas) {
344 Assertions.argumentNotNull(schemas, "schemas may not be null");
345 this.schemas = schemas;
352 public AxValidationResult validate(final AxValidationResult resultIn) {
353 AxValidationResult result = resultIn;
355 result = super.validate(result);
356 result = schemas.validate(result);
357 result = events.validate(result);
358 result = albums.validate(result);
359 result = tasks.validate(result);
360 result = policies.validate(result);
362 validateEventKeys(result);
363 validateContextAlbumKeys(result);
364 result = validateAllTaskKeys(result);
365 validatePolicyKeys(result);
371 * Validate all fundamental concepts keyed in events exist.
373 * @param result the validation result to return
376 private AxValidationResult validateEventKeys(final AxValidationResult result) {
377 for (final AxEvent event : events.getAll(null)) {
378 for (final AxField field : event.getFields()) {
379 if (getSchemas().get(field.getSchema()) == null) {
380 result.addValidationMessage(
381 new AxValidationMessage(event.getKey(), this.getClass(), ValidationResult.INVALID,
382 "event field data type " + field.getSchema().getId() + DOES_NOT_EXIST));
390 * Validate all fundamental concepts keyed in concept maps exist.
392 * @param result the validation result to return
395 private AxValidationResult validateContextAlbumKeys(final AxValidationResult result) {
396 for (final AxContextAlbum contextAlbum : albums.getAll(null)) {
397 if (getSchemas().get(contextAlbum.getItemSchema()) == null) {
398 result.addValidationMessage(
399 new AxValidationMessage(contextAlbum.getKey(), this.getClass(), ValidationResult.INVALID,
400 "context album schema " + contextAlbum.getItemSchema().getId() + DOES_NOT_EXIST));
407 * Validate all fundamental concepts keyed in tasks exist.
409 * @param result the validation result to return
412 private AxValidationResult validateAllTaskKeys(AxValidationResult result) {
413 for (final AxTask task : tasks.getAll(null)) {
414 result = validateTaskKeys(task, result);
420 * Validate all fundamental concepts keyed in tasks exist.
422 * @param task The task to validate the keys of
423 * @param result the validation result to return
426 private AxValidationResult validateTaskKeys(final AxTask task, AxValidationResult result) {
427 for (final AxField field : task.getInputFieldSet()) {
428 if (getSchemas().get(field.getSchema()) == null) {
429 result.addValidationMessage(new AxValidationMessage(task.getKey(), this.getClass(),
430 ValidationResult.INVALID, "task input field schema " + field.getSchema().getId() + DOES_NOT_EXIST));
433 for (final AxField field : task.getOutputFieldSet()) {
434 if (getSchemas().get(field.getSchema()) == null) {
435 result.addValidationMessage(
436 new AxValidationMessage(task.getKey(), this.getClass(), ValidationResult.INVALID,
437 "task output field schema " + field.getSchema().getId() + DOES_NOT_EXIST));
440 for (final AxArtifactKey contextAlbumKey : task.getContextAlbumReferences()) {
441 if (albums.get(contextAlbumKey) == null) {
442 result.addValidationMessage(new AxValidationMessage(task.getKey(), this.getClass(),
443 ValidationResult.INVALID, "task context album " + contextAlbumKey.getId() + DOES_NOT_EXIST));
450 * Validate all fundamental concepts keyed in policies exist.
452 * @param result the validation result to return
455 private AxValidationResult validatePolicyKeys(final AxValidationResult result) {
456 for (final AxPolicy policy : policies.getAll(null)) {
457 for (final AxState state : policy.getStateMap().values()) {
458 validateStateReferences(state, result);
466 * Validate that the references used on a state are valid.
468 * @param state The state to check
469 * @param result the validation result to append to
471 private void validateStateReferences(AxState state, AxValidationResult result) {
472 for (final AxArtifactKey contextAlbumKey : state.getContextAlbumReferences()) {
473 if (albums.get(contextAlbumKey) == null) {
474 result.addValidationMessage(new AxValidationMessage(state.getKey(), this.getClass(),
475 ValidationResult.INVALID, "state context album " + contextAlbumKey.getId() + DOES_NOT_EXIST));
479 final AxEvent triggerEvent = events.getEventMap().get(state.getTrigger());
480 if (triggerEvent == null) {
481 result.addValidationMessage(new AxValidationMessage(state.getKey(), this.getClass(),
482 ValidationResult.INVALID, "state trigger event " + state.getTrigger().getId() + DOES_NOT_EXIST));
485 final AxTask defaultTask = tasks.getTaskMap().get(state.getDefaultTask());
486 if (defaultTask == null) {
487 result.addValidationMessage(new AxValidationMessage(state.getKey(), this.getClass(),
488 ValidationResult.INVALID, "state default task " + state.getDefaultTask().getId() + DOES_NOT_EXIST));
491 // Check task input fields and event fields are compatible for default tasks with no task
493 if (state.getTaskSelectionLogic().getKey().equals(AxReferenceKey.getNullKey())
494 && triggerEvent != null && defaultTask != null) {
495 final Set<AxField> unhandledTaskInputFields = new TreeSet<>(defaultTask.getInputFieldSet());
496 unhandledTaskInputFields.removeAll(triggerEvent.getFields());
497 for (final AxField unhandledTaskInputField : unhandledTaskInputFields) {
498 result.addValidationMessage(new AxValidationMessage(state.getKey(), this.getClass(),
499 ValidationResult.INVALID, "task input field " + unhandledTaskInputField + " for task "
500 + defaultTask.getId() + " not in trigger event " + triggerEvent.getId()));
504 for (final AxStateOutput stateOutput : state.getStateOutputs().values()) {
505 if (events.getEventMap().get(stateOutput.getOutgingEvent()) == null) {
506 result.addValidationMessage(new AxValidationMessage(stateOutput.getKey(), this.getClass(),
507 ValidationResult.INVALID, "output event " + stateOutput.getOutgingEvent().getId()
508 + " for state output " + stateOutput.getId() + DOES_NOT_EXIST));
512 validateEventTaskFieldCompatibilityOnState(state, result);
516 * Validate that the fields on tasks and events that trigger them and are output by them are
517 * compatible for all tasks used on a state.
519 * @param state The state to check
520 * @param result the validation result to append to
522 private void validateEventTaskFieldCompatibilityOnState(AxState state, AxValidationResult result) {
523 // Check task output fields and event fields are compatible for tasks that directly
524 // reference state outputs
525 for (final Entry<AxArtifactKey, AxStateTaskReference> taskRefEntry : state.getTaskReferences().entrySet()) {
526 if (!taskRefEntry.getValue().getStateTaskOutputType().equals(AxStateTaskOutputType.DIRECT)) {
530 final AxTask usedTask = tasks.getTaskMap().get(taskRefEntry.getKey());
531 if (usedTask == null) {
532 result.addValidationMessage(new AxValidationMessage(state.getKey(), this.getClass(),
533 ValidationResult.INVALID, "state task " + taskRefEntry.getKey().getId() + DOES_NOT_EXIST));
535 AxStateOutput stateOutput =
536 state.getStateOutputs().get(taskRefEntry.getValue().getOutput().getKey().getLocalName());
537 validateEventTaskFieldCompatibilityOnStateOutput(state, usedTask, stateOutput, result);
543 * Validate that the fields on a task of a state output and the events that trigger it are
546 * @param state The state to check
547 * @param task The task to check
548 * @param stateOutput The state output to check
549 * @param result the validation result to append to
551 private void validateEventTaskFieldCompatibilityOnStateOutput(final AxState state, final AxTask task,
552 final AxStateOutput stateOutput, AxValidationResult result) {
553 if (stateOutput == null) {
554 result.addValidationMessage(new AxValidationMessage(state.getKey(), this.getClass(),
555 ValidationResult.INVALID, "state output on task reference for task " + task.getId() + " is null"));
558 final AxEvent usedEvent = events.getEventMap().get(stateOutput.getOutgingEvent());
559 if (usedEvent == null) {
560 result.addValidationMessage(new AxValidationMessage(stateOutput.getKey(), this.getClass(),
561 ValidationResult.INVALID, "output event " + stateOutput.getOutgingEvent().getId()
562 + " for state output " + stateOutput.getId() + DOES_NOT_EXIST));
565 if (task != null && usedEvent != null) {
566 final Set<AxField> unhandledTaskOutputFields = new TreeSet<>(task.getOutputFieldSet());
567 unhandledTaskOutputFields.removeAll(usedEvent.getFields());
568 for (final AxField unhandledTaskOutputField : unhandledTaskOutputFields) {
569 result.addValidationMessage(new AxValidationMessage(state.getKey(), this.getClass(),
570 ValidationResult.INVALID, "task output field " + unhandledTaskOutputField + " for task "
571 + task.getId() + " not in output event " + usedEvent.getId()));
578 * When a model is unmarshalled from disk or from the database, if the albums field was missing a blank
579 * with a null key was added. This method is called by JAXB after unmarshalling and is
580 * used to insert an appropriate key
582 * @param unmarshaller the unmarshaller that is unmarshalling the model
583 * @param parent the parent object of this object in the unmarshaller
585 public void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) {
586 new EmptyAlbumsAdapter().doAfterUnmarshal(this);
590 * When a model is marshalled from disk or database, if the albums field is empty/null, then the albums field
591 * is not emitted. If the (empty) albums field is not emitted then it's keyinfo should also be suppressed
592 * This method is called by JAXB before marshaling and is used to insert the appropriate filters
594 * @param marshaller the marshaller that is marshaller the model
595 * @throws Exception if there is a problem with the marshalling
597 public void beforeMarshal(final Marshaller marshaller) throws Exception {
598 EmptyAlbumsAdapter albumsfilter = new EmptyAlbumsAdapter();
599 marshaller.setAdapter(EmptyAlbumsAdapter.class, albumsfilter);
600 //get/create the keyinfofilter
601 KeyInfoMarshalFilter keyinfoFilter = marshaller.getAdapter(KeyInfoMarshalFilter.class);
602 if (keyinfoFilter == null) {
603 keyinfoFilter = new KeyInfoMarshalFilter();
605 //if the albumsfilter would filter out this model's albums add the album's key to the keyinfofilter
606 if (albumsfilter.marshal(this.albums) == null && this.albums != null) {
607 keyinfoFilter.addFilterKey(this.albums.getKey());
609 marshaller.setAdapter(keyinfoFilter);
616 public void clean() {
629 public String toString() {
630 final StringBuilder builder = new StringBuilder();
631 builder.append(this.getClass().getSimpleName());
632 builder.append(":(");
633 builder.append(super.toString());
634 builder.append(",policies=");
635 builder.append(policies);
636 builder.append(",tasks=");
637 builder.append(tasks);
638 builder.append(",events=");
639 builder.append(events);
640 builder.append(",albums=");
641 builder.append(albums);
642 builder.append(",schemas=");
643 builder.append(schemas);
645 return builder.toString();
652 public AxConcept copyTo(final AxConcept targetObject) {
653 Assertions.argumentNotNull(targetObject, "target may not be null");
655 final Object copyObject = targetObject;
656 Assertions.instanceOf(copyObject, AxPolicyModel.class);
658 final AxPolicyModel copy = ((AxPolicyModel) copyObject);
659 super.copyTo(targetObject);
660 copy.setPolicies(new AxPolicies(policies));
661 copy.setTasks(new AxTasks(tasks));
662 copy.setEvents(new AxEvents(events));
663 copy.setAlbums(new AxContextAlbums(albums));
664 copy.setSchemas(new AxContextSchemas(schemas));
673 public int hashCode() {
674 final int prime = 31;
676 result = prime * result + super.hashCode();
677 result = prime * result + policies.hashCode();
678 result = prime * result + tasks.hashCode();
679 result = prime * result + events.hashCode();
680 result = prime * result + albums.hashCode();
681 result = prime * result + schemas.hashCode();
689 public boolean equals(final Object obj) {
691 throw new IllegalArgumentException("comparison object may not be null");
697 if (getClass() != obj.getClass()) {
701 final AxPolicyModel other = (AxPolicyModel) obj;
702 if (!super.equals(other)) {
705 if (!policies.equals(other.policies)) {
708 if (!tasks.equals(other.tasks)) {
711 if (!events.equals(other.events)) {
714 if (!albums.equals(other.albums)) {
717 return schemas.equals(other.schemas);
724 public int compareTo(final AxConcept otherObj) {
725 Assertions.argumentNotNull(otherObj, "comparison object may not be null");
727 if (this == otherObj) {
730 if (getClass() != otherObj.getClass()) {
731 return this.hashCode() - otherObj.hashCode();
734 final AxPolicyModel other = (AxPolicyModel) otherObj;
735 if (!super.equals(other)) {
736 return super.compareTo(other);
738 if (!policies.equals(other.policies)) {
739 return policies.compareTo(other.policies);
741 if (!tasks.equals(other.tasks)) {
742 return tasks.compareTo(other.tasks);
744 if (!events.equals(other.events)) {
745 return events.compareTo(other.events);
747 if (!albums.equals(other.albums)) {
748 return albums.compareTo(other.albums);
750 return schemas.compareTo(other.schemas);