ObservableContext.java
001 /*
002  * SPDX-License-Identifier: Apache-2.0
003  *
004  * Copyright 2008-2017 the original author or authors.
005  *
006  * Licensed under the Apache License, Version 2.0 (the "License");
007  * you may not use this file except in compliance with the License.
008  * You may obtain a copy of the License at
009  *
010  *     http://www.apache.org/licenses/LICENSE-2.0
011  *
012  * Unless required by applicable law or agreed to in writing, software
013  * distributed under the License is distributed on an "AS IS" BASIS,
014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015  * See the License for the specific language governing permissions and
016  * limitations under the License.
017  */
018 package griffon.core;
019 
020 import javax.annotation.Nonnull;
021 import javax.annotation.Nullable;
022 
023 import static griffon.util.GriffonNameUtils.requireNonBlank;
024 import static java.util.Objects.requireNonNull;
025 
026 /**
027  @author Andres Almiray
028  @since 2.5.0
029  */
030 public interface ObservableContext extends Context {
031     void addContextEventListener(@Nonnull ContextEventListener listener);
032 
033     void removeContextEventListener(@Nonnull ContextEventListener listener);
034 
035     @Nonnull
036     ContextEventListener[] getContextEventListeners();
037 
038     interface ContextEventListener {
039         void contextChanged(@Nonnull ContextEvent contextEvent);
040     }
041 
042     class ContextEvent {
043         private final Type type;
044         private final String key;
045         private final Object oldValue;
046         private final Object newValue;
047 
048         public ContextEvent(@Nonnull Type type, @Nonnull String key, @Nullable Object oldValue, @Nullable Object newValue) {
049             this.type = requireNonNull(type, "Argument 'type' must not be null");
050             this.key = requireNonBlank(key, "Argument 'key' must not be null");
051             this.oldValue = oldValue;
052             this.newValue = newValue;
053         }
054 
055         @Nonnull
056         public Type getType() {
057             return type;
058         }
059 
060         @Nonnull
061         public String getKey() {
062             return key;
063         }
064 
065         @Nullable
066         public Object getOldValue() {
067             return oldValue;
068         }
069 
070         @Nullable
071         public Object getNewValue() {
072             return newValue;
073         }
074 
075         @Override
076         public boolean equals(Object o) {
077             if (this == oreturn true;
078             if (o == null || getClass() != o.getClass()) return false;
079 
080             ContextEvent that = (ContextEvento;
081 
082             if (!key.equals(that.key)) return false;
083             if (newValue != null ? !newValue.equals(that.newValue: that.newValue != nullreturn false;
084             if (oldValue != null ? !oldValue.equals(that.oldValue: that.oldValue != nullreturn false;
085             if (type != that.typereturn false;
086 
087             return true;
088         }
089 
090         @Override
091         public int hashCode() {
092             int result = type.hashCode();
093             result = 31 * result + key.hashCode();
094             result = 31 * result + (oldValue != null ? oldValue.hashCode() 0);
095             result = 31 * result + (newValue != null ? newValue.hashCode() 0);
096             return result;
097         }
098 
099         @Override
100         public String toString() {
101             final StringBuilder sb = new StringBuilder("ContextEvent{");
102             sb.append("type=").append(type);
103             sb.append(", key='").append(key).append('\'');
104             sb.append(", oldValue=").append(oldValue);
105             sb.append(", newValue=").append(newValue);
106             sb.append('}');
107             return sb.toString();
108         }
109 
110         public enum Type {
111             ADD, REMOVE, UPDATE
112         }
113     }
114 }