/*
* 2012-3 Red Hat Inc. and/or its affiliates and other contributors.
*
* 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.
*/
package org.overlord.rtgov.analytics.service;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.overlord.rtgov.activity.model.Context;
import org.overlord.rtgov.analytics.util.ServiceDefinitionUtil;
/**
* This class represents the service contract details associated
* with a service type.
*
*/
public class ServiceDefinition implements java.io.Externalizable {
private static final Logger LOG=Logger.getLogger(ServiceDefinition.class.getName());
private static final int VERSION = 2;
private String _serviceType=null;
private boolean _internal=false;
private java.util.List<InterfaceDefinition> _interfaces=
new java.util.ArrayList<InterfaceDefinition>();
private java.util.List<Context> _contexts=new java.util.ArrayList<Context>();
private java.util.List<InvocationMetric> _history=new java.util.ArrayList<InvocationMetric>();
/**
* Default constructor.
*/
public ServiceDefinition() {
}
/**
* This method creates a shallow copy.
*
* @return The shallow copy
*/
public ServiceDefinition shallowCopy() {
ServiceDefinition ret=new ServiceDefinition();
ret.setServiceType(_serviceType);
ret.setInternal(_internal);
// Copy contexts
for (Context c : _contexts) {
ret.getContext().add(new Context(c));
}
return (ret);
}
/**
* This method sets the service type.
*
* @param st The service type
*/
public void setServiceType(String st) {
_serviceType = st;
}
/**
* This method gets the service type.
*
* @return The service type
*/
public String getServiceType() {
return (_serviceType);
}
/**
* This method sets whether the service is internal (i.e. not publicly
* available).
*
* @param b Whether the service is internal
*/
public void setInternal(boolean b) {
_internal = b;
}
/**
* This method identifies whether the service is internal.
*
* @return Whether the service is internal
*/
public boolean getInternal() {
return (_internal);
}
/**
* This method sets the list of interfaces associated
* with the service.
*
* @param interfaces The interfaces
*/
public void setInterfaces(java.util.List<InterfaceDefinition> interfaces) {
_interfaces = interfaces;
}
/**
* This method returns the list of interfaces associated
* with the service.
*
* @return The interfaces
*/
public java.util.List<InterfaceDefinition> getInterfaces() {
return (_interfaces);
}
/**
* This method returns the interface associated with the supplied
* name, if defined within the service definition.
*
* @param name The interface name
* @return The interface, or null if not found
*/
public InterfaceDefinition getInterface(String name) {
InterfaceDefinition ret=null;
for (int i=0; i < _interfaces.size(); i++) {
if (_interfaces.get(i).getInterface().equals(name)) {
ret = _interfaces.get(i);
break;
}
}
return (ret);
}
/**
* This method sets the context.
*
* @param context The context
*/
public void setContext(java.util.List<Context> context) {
_contexts = context;
}
/**
* This method gets the context.
*
* @return The context
*/
public java.util.List<Context> getContext() {
return (_contexts);
}
/**
* This method returns the aggregated invocation metric information
* from the interfaces.
*
* @return The invocation metric
*/
public InvocationMetric getMetrics() {
java.util.List<InvocationMetric> metrics=
new java.util.ArrayList<InvocationMetric>();
for (InterfaceDefinition id : getInterfaces()) {
metrics.add(id.getMetrics());
}
return (new InvocationMetric(metrics));
}
/**
* This method returns the historic list of invocation
* metrics merged into the current service definition.
*
* @return The invocation metrics history
*/
public java.util.List<InvocationMetric> getHistory() {
return (Collections.unmodifiableList(_history));
}
/**
* This method merges the supplied definition with this
* service definition.
*
* @param sd The service definition to merge
* @throws Exception Failed to merge
*/
public void merge(ServiceDefinition sd) throws Exception {
merge(sd, false);
}
/**
* This method merges the supplied definition with this
* service definition.
*
* @param sd The service definition to merge
* @param retainContexts Whether to merge context information
* @throws Exception Failed to merge
*/
public void merge(ServiceDefinition sd, boolean retainContexts) throws Exception {
if (sd == null || !sd.getServiceType().equals(getServiceType())) {
throw new IllegalArgumentException("Invalid service definition");
}
if (LOG.isLoggable(Level.FINER)) {
LOG.finer("Pre-merge this=["+this+"] with=["+sd+"]");
}
// If one instance indicates the service is internal, then set the internal flag
if (sd.getInternal()) {
sd.setInternal(true);
}
// Examine operation definitions - merge existing and
// transfer undefined
for (int i=0; i < sd.getInterfaces().size(); i++) {
InterfaceDefinition idef=sd.getInterfaces().get(i);
InterfaceDefinition cur=getInterface(idef.getInterface());
if (cur == null) {
cur = idef.shallowCopy();
getInterfaces().add(cur);
}
cur.merge(idef);
}
if (retainContexts) {
for (Context c : sd.getContext()) {
if (!_contexts.contains(c)) {
_contexts.add(c);
}
}
}
_history.add(sd.getMetrics());
if (LOG.isLoggable(Level.FINER)) {
LOG.finer("Post-merge this=["+this+"]");
}
}
/**
* {@inheritDoc}
*/
public int hashCode() {
return (_serviceType.hashCode());
}
/**
* {@inheritDoc}
*/
public boolean equals(Object obj) {
if (obj instanceof ServiceDefinition
&& ((ServiceDefinition)obj).getServiceType().equals(_serviceType)) {
return (true);
}
return (false);
}
/**
* {@inheritDoc}
*/
public String toString() {
String ret=null;
try {
ret = new String(ServiceDefinitionUtil.serializeServiceDefinition(this));
} catch (Exception e) {
e.printStackTrace();
}
return (ret);
}
/**
* {@inheritDoc}
*/
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(VERSION);
out.writeObject(_serviceType);
out.writeInt(_interfaces.size());
for (int i=0; i < _interfaces.size(); i++) {
out.writeObject(_interfaces.get(i));
}
out.writeInt(_contexts.size());
for (int i=0; i < _contexts.size(); i++) {
out.writeObject(_contexts.get(i));
}
out.writeInt(_history.size());
for (int i=0; i < _history.size(); i++) {
out.writeObject(_history.get(i));
}
// Serialize version 2 additional elements
out.writeBoolean(_internal);
}
/**
* {@inheritDoc}
*/
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
int version=in.readInt();
_serviceType = (String)in.readObject();
int len=in.readInt();
for (int i=0; i < len; i++) {
_interfaces.add((InterfaceDefinition)in.readObject());
}
len = in.readInt();
for (int i=0; i < len; i++) {
_contexts.add((Context)in.readObject());
}
len = in.readInt();
for (int i=0; i < len; i++) {
_history.add((InvocationMetric)in.readObject());
}
// Deserialize version 2 additional elements
if (version >= 2) {
_internal = in.readBoolean();
}
}
}