/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sling.discovery.commons.providers;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.sling.discovery.ClusterView;
import org.apache.sling.discovery.InstanceDescription;
import org.apache.sling.discovery.commons.providers.util.PropertyNameHelper;
/**
* Base implementation for the InstanceDescription interface.
* <p>
* Allows creation of the object with clusterview and/or properties null - to be
* set later but before usage!
* <p>
*/
public class DefaultInstanceDescription implements InstanceDescription {
/** the cluster view of which this instance is part of **/
private ClusterView clusterView;
/** whether this instance is the leader in the cluster **/
private boolean isLeader;
/** whether this instance is the local/own one **/
private boolean isLocal;
/** the sling id of this instance **/
private String slingId;
/** the properties of this instance **/
private Map<String, String> properties;
public DefaultInstanceDescription(final DefaultClusterView clusterView,
final boolean isLeader, final boolean isOwn, final String slingId,
final Map<String, String> properties) {
// slingId must not be null - clusterView and properties can be null though
if (slingId == null || slingId.length() == 0) {
throw new IllegalArgumentException("slingId must not be null");
}
this.isLeader = isLeader;
this.isLocal = isOwn;
this.slingId = slingId;
this.properties = filterValidProperties(properties);
if (clusterView != null) {
clusterView.addInstanceDescription(this);
if (this.clusterView == null) {
throw new IllegalStateException(
"clusterView should have been set by now");
}
}
}
@Override
public String toString() {
final String clusterInfo;
if (clusterView==null) {
clusterInfo = "";
} else {
clusterInfo = ", clusterViewId="+clusterView.getId();
}
return "an InstanceDescription[slindId=" + slingId + ", isLeader="
+ isLeader + ", isOwn=" + isLocal + clusterInfo + ", properties=" + this.properties + "]";
}
@Override
public int hashCode() {
return slingId.hashCode();
}
@Override
public boolean equals(final Object obj) {
if (obj == null || !(obj instanceof DefaultInstanceDescription)) {
return false;
}
final DefaultInstanceDescription other = (DefaultInstanceDescription) obj;
if (!this.slingId.equals(other.slingId)) {
return false;
}
if (!this.slingId.equals(other.slingId)) {
return false;
}
if (!properties.equals(other.properties)) {
return false;
}
if (!this.getClusterView().getId()
.equals(other.getClusterView().getId())) {
return false;
}
return true;
}
public ClusterView getClusterView() {
if (clusterView == null) {
throw new IllegalStateException("clusterView was never set");
}
return clusterView;
}
/**
* Sets the cluster on this instance
* @param clusterView
*/
void setClusterView(ClusterView clusterView) {
if (this.clusterView != null) {
throw new IllegalStateException("can only set clusterView once");
}
if (clusterView == null) {
throw new IllegalArgumentException("clusterView must not be null");
}
this.clusterView = clusterView;
}
public boolean isLeader() {
return isLeader;
}
public boolean isLocal() {
return isLocal;
}
public String getSlingId() {
return slingId;
}
public String getProperty(final String name) {
if (properties == null) {
throw new IllegalStateException("properties were never set");
}
return properties.get(name);
}
public Map<String, String> getProperties() {
if (properties == null) {
throw new IllegalStateException("properties were never set");
}
return Collections.unmodifiableMap(properties);
}
/**
* Sets the properties of this instance
* @param properties
*/
protected void setProperties(final Map<String, String> properties) {
if (properties == null) {
throw new IllegalArgumentException("properties must not be null");
}
this.properties = filterValidProperties(properties);
}
/** SLING-2883 : filter (pass-through) valid properties only **/
private Map<String, String> filterValidProperties(
Map<String, String> rawProps) {
if (rawProps==null) {
return null;
}
final HashMap<String, String> filteredProps = new HashMap<String, String>();
final Set<Entry<String, String>> entries = rawProps.entrySet();
final Iterator<Entry<String, String>> it = entries.iterator();
while(it.hasNext()) {
final Entry<String, String> anEntry = it.next();
if (PropertyNameHelper.isValidPropertyName(anEntry.getKey())) {
filteredProps.put(anEntry.getKey(), anEntry.getValue());
}
}
return filteredProps;
}
/** for testing only! **/
public void setProperty(String key, String value) {
if (!PropertyNameHelper.isValidPropertyName(key)) {
throw new IllegalArgumentException("key is not a valid property name: "+key);
}
if (properties == null) {
properties = new HashMap<String, String>();
}
properties.put(key, value);
}
}