/**
*
*/
package com.thinkbiganalytics.metadata.sla.spi.core;
/*-
* #%L
* thinkbig-sla-core
* %%
* Copyright (C) 2017 ThinkBig Analytics
* %%
* Licensed 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.
* #L%
*/
import com.thinkbiganalytics.metadata.sla.api.DuplicateAgreementNameException;
import com.thinkbiganalytics.metadata.sla.api.Metric;
import com.thinkbiganalytics.metadata.sla.api.Obligation;
import com.thinkbiganalytics.metadata.sla.api.ObligationGroup;
import com.thinkbiganalytics.metadata.sla.api.ObligationGroup.Condition;
import com.thinkbiganalytics.metadata.sla.api.ServiceLevelAgreement;
import com.thinkbiganalytics.metadata.sla.api.ServiceLevelAgreement.ID;
import com.thinkbiganalytics.metadata.sla.api.ServiceLevelAgreementActionConfiguration;
import com.thinkbiganalytics.metadata.sla.spi.ObligationBuilder;
import com.thinkbiganalytics.metadata.sla.spi.ObligationGroupBuilder;
import com.thinkbiganalytics.metadata.sla.spi.ServiceLevelAgreementBuilder;
import com.thinkbiganalytics.metadata.sla.spi.ServiceLevelAgreementCheck;
import com.thinkbiganalytics.metadata.sla.spi.ServiceLevelAgreementCheckBuilder;
import com.thinkbiganalytics.metadata.sla.spi.ServiceLevelAgreementProvider;
import org.joda.time.DateTime;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
/**
*
*/
public class InMemorySLAProvider implements ServiceLevelAgreementProvider {
private Map<SLAID, ServiceLevelAgreement> slas;
private Map<String, ID> nameToSlas;
/**
*
*/
public InMemorySLAProvider() {
this.slas = Collections.synchronizedMap(new HashMap<SLAID, ServiceLevelAgreement>());
this.nameToSlas = Collections.synchronizedMap(new HashMap<String, ID>());
}
@Override
public ID resolve(Serializable ser) {
return resolveImpl(ser);
}
@Override
public List<ServiceLevelAgreement> getAgreements() {
synchronized (this.slas) {
return new ArrayList<ServiceLevelAgreement>(this.slas.values());
}
}
@Override
public ServiceLevelAgreement getAgreement(ID id) {
return this.slas.get(id);
}
@Override
public ServiceLevelAgreement findAgreementByName(String slaName) {
ID id = this.nameToSlas.get(slaName);
if (id != null) {
return this.slas.get(id);
} else {
return null;
}
}
@Override
public boolean removeAgreement(ID id) {
synchronized (this.slas) {
ServiceLevelAgreement sla = this.slas.remove(id);
if (sla != null) {
this.nameToSlas.remove(sla.getName());
return true;
} else {
return false;
}
}
}
@Override
public ServiceLevelAgreementBuilder builder() {
return new SLABuilderImpl();
}
@Override
public ServiceLevelAgreementBuilder builder(ID id) {
return new SLABuilderImpl(resolveImpl(id));
}
private SLAImpl addSLA(SLAImpl sla) {
synchronized (this.slas) {
SLAID id = new SLAID();
if (this.nameToSlas.containsKey(sla.getName())) {
throw new DuplicateAgreementNameException(sla.getName());
} else {
sla.setId(id);
this.slas.put(id, sla);
this.nameToSlas.put(sla.getName(), id);
return sla;
}
}
}
private SLAImpl replaceSLA(SLAID id, SLAImpl sla) {
ServiceLevelAgreement oldSla = this.slas.get(id);
ServiceLevelAgreement.ID namedId = this.nameToSlas.get(sla.getName());
// Make sure the name of the new SLA does not match that of another SLA
// besides the one being replaced.
if (namedId == null || oldSla.getId().equals(namedId)) {
sla.setId(id);
this.slas.put(id, sla);
return sla;
} else {
throw new DuplicateAgreementNameException(sla.getName());
}
}
private SLAID resolveImpl(Serializable ser) {
// TODO: throw unknown ID exception?
if (ser instanceof String) {
return new SLAID((String) ser);
} else if (ser instanceof UUID) {
return new SLAID((UUID) ser);
} else if (ser instanceof SLAID) {
return (SLAID) ser;
} else {
throw new IllegalArgumentException("Invalid ID source format: " + ser.getClass());
}
}
@Override
public ServiceLevelAgreementCheckBuilder slaCheckBuilder(ID slaId) {
return null;
}
private static class ObligationBuilderImpl<B> implements ObligationBuilder<B> {
private SLABuilderImpl slaBuilder;
private ObligationGroupBuilderImpl groupBuilder;
private ObligationGroupImpl group;
private String description;
private Set<Metric> metrics = new HashSet<Metric>();
public ObligationBuilderImpl(ObligationGroupImpl group, SLABuilderImpl bldr) {
this.slaBuilder = bldr;
this.group = group;
}
public ObligationBuilderImpl(ObligationGroupImpl group, ObligationGroupBuilderImpl bldr) {
this.groupBuilder = bldr;
this.group = group;
}
@Override
public ObligationBuilder<B> description(String descr) {
this.description = descr;
return this;
}
@Override
public ObligationBuilder<B> metric(Metric metric, Metric... more) {
this.metrics.add(metric);
for (Metric another : more) {
this.metrics.add(another);
}
return this;
}
@Override
public ObligationBuilder<B> metric(Collection<Metric> metrics) {
this.metrics.addAll(metrics);
return this;
}
@Override
@SuppressWarnings("unchecked")
public B build() {
ObligationImpl ob = new ObligationImpl();
ob.description = this.description;
ob.metrics = this.metrics;
ob.group = this.group;
this.group.getObligations().add(ob);
if (this.groupBuilder != null) {
return (B) this.groupBuilder;
} else {
return (B) this.slaBuilder;
}
}
}
private static class ObligationGroupBuilderImpl implements ObligationGroupBuilder {
private SLABuilderImpl slaBuilder;
private ObligationGroupImpl group;
public ObligationGroupBuilderImpl(SLABuilderImpl slaBuilder, Condition cond) {
this.slaBuilder = slaBuilder;
this.group = new ObligationGroupImpl(this.slaBuilder.sla, cond);
}
@Override
public ObligationGroupBuilder obligation(Obligation obligation) {
this.group.getObligations().add(obligation);
return this;
}
@Override
public ObligationBuilder<ObligationGroupBuilder> obligationBuilder() {
return new ObligationBuilderImpl<ObligationGroupBuilder>(this.group, this);
}
@Override
public ServiceLevelAgreementBuilder build() {
this.slaBuilder.sla.obligationGroups.add(this.group);
return this.slaBuilder;
}
}
private static class SLAID implements ServiceLevelAgreement.ID {
private static final long serialVersionUID = 8914036758972637669L;
private final UUID uuid;
public SLAID() {
this(UUID.randomUUID());
}
public SLAID(String str) {
this(UUID.fromString(str));
}
public SLAID(UUID id) {
this.uuid = id;
}
@Override
public String toString() {
return this.uuid.toString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!this.getClass().equals(obj.getClass())) {
return false;
}
return Objects.equals(this.uuid, ((SLAID) obj).uuid);
}
@Override
public int hashCode() {
return Objects.hash(getClass(), this.uuid);
}
}
private static class SLAImpl implements ServiceLevelAgreement {
boolean enabled = true;
private ServiceLevelAgreement.ID id;
private String name;
private DateTime creationTime = DateTime.now();
private String description;
private ObligationGroupImpl defaultGroup;
private List<ObligationGroup> obligationGroups;
public SLAImpl() {
this.defaultGroup = new ObligationGroupImpl(this, Condition.REQUIRED);
this.obligationGroups = new ArrayList<ObligationGroup>();
}
public ServiceLevelAgreement.ID getId() {
return id;
}
protected void setId(ServiceLevelAgreement.ID id) {
this.id = id;
}
@Override
public String getName() {
return name;
}
protected void setName(String name) {
this.name = name;
}
@Override
public DateTime getCreatedTime() {
return this.creationTime;
}
@Override
public String getDescription() {
return description;
}
protected void setDescription(String description) {
this.description = description;
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public List<ObligationGroup> getObligationGroups() {
if (this.defaultGroup.getObligations().isEmpty()) {
return this.obligationGroups;
} else {
ArrayList<ObligationGroup> list = new ArrayList<>();
list.add(this.defaultGroup);
list.addAll(this.obligationGroups);
return list;
}
}
@Override
public List<Obligation> getObligations() {
List<Obligation> list = new ArrayList<>();
list.addAll(this.defaultGroup.getObligations());
for (ObligationGroup group : this.obligationGroups) {
list.addAll(group.getObligations());
}
return list;
}
@Override
public List<ServiceLevelAgreementCheck> getSlaChecks() {
return null;
}
}
private static class ObligationId implements Obligation.ID {
private static final long serialVersionUID = 8914036758972637669L;
private final UUID uuid;
public ObligationId() {
this(UUID.randomUUID());
}
public ObligationId(String str) {
this(UUID.fromString(str));
}
public ObligationId(UUID id) {
this.uuid = id;
}
@Override
public String toString() {
return this.uuid.toString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!this.getClass().equals(obj.getClass())) {
return false;
}
return Objects.equals(this.uuid, ((SLAID) obj).uuid);
}
@Override
public int hashCode() {
return Objects.hash(getClass(), this.uuid);
}
}
private static class ObligationImpl implements Obligation {
private ObligationGroupImpl group;
private String description;
private Set<Metric> metrics = new HashSet<Metric>();
private Obligation.ID id;
public ObligationImpl() {
this.id = new ObligationId();
}
@Override
public ID getId() {
return id;
}
@Override
public String getDescription() {
return this.description;
}
@Override
public ServiceLevelAgreement getAgreement() {
return this.group.getAgreement();
}
@Override
public ObligationGroup getGroup() {
return this.group;
}
@Override
public Set<Metric> getMetrics() {
return Collections.unmodifiableSet(this.metrics);
}
}
private static class ObligationGroupImpl implements ObligationGroup {
private SLAImpl sla;
private Condition condition;
private List<Obligation> obligations = new ArrayList<>();
public ObligationGroupImpl(SLAImpl sla, Condition condition) {
this.sla = sla;
this.condition = condition;
}
@Override
public ServiceLevelAgreement getAgreement() {
return this.sla;
}
@Override
public Condition getCondition() {
return this.condition;
}
@Override
public List<Obligation> getObligations() {
return this.obligations;
}
}
private class SLABuilderImpl implements ServiceLevelAgreementBuilder {
private SLAID id;
private String name;
private String descrtion;
private SLAImpl sla = new SLAImpl();
public SLABuilderImpl() {
this(null);
}
public SLABuilderImpl(SLAID id) {
this.id = id;
}
@Override
public ServiceLevelAgreementBuilder name(String name) {
this.name = name;
return this;
}
@Override
public ServiceLevelAgreementBuilder description(String description) {
this.descrtion = description;
return this;
}
@Override
public ServiceLevelAgreementBuilder obligation(Obligation obligation) {
this.sla.getObligations().add(obligation);
return this;
}
@Override
public ObligationBuilder<ServiceLevelAgreementBuilder> obligationBuilder() {
return new ObligationBuilderImpl<ServiceLevelAgreementBuilder>(this.sla.defaultGroup, this);
}
@Override
public ObligationBuilder<ServiceLevelAgreementBuilder> obligationBuilder(Condition condition) {
ObligationGroupImpl group = new ObligationGroupImpl(this.sla, condition);
this.sla.obligationGroups.add(group);
return new ObligationBuilderImpl<ServiceLevelAgreementBuilder>(group, this);
}
@Override
public ObligationGroupBuilder obligationGroupBuilder(Condition condition) {
return new ObligationGroupBuilderImpl(this, condition);
}
@Override
public ServiceLevelAgreement build() {
this.sla.setName(this.name);
this.sla.setDescription(this.descrtion);
if (this.id == null) {
return addSLA(sla);
} else {
return replaceSLA(this.id, sla);
}
}
@Override
public ServiceLevelAgreementBuilder actionConfigurations(List<? extends ServiceLevelAgreementActionConfiguration> actionConfigurations) {
return null;
}
}
}