jadex.bridge.service.search.ServiceQuery Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jadex-platform-bridge Show documentation
Show all versions of jadex-platform-bridge Show documentation
Jadex bridge is a base package for kernels and platforms, i.e., it is used by both and provides commonly used interfaces and classes for active components and their management.
package jadex.bridge.service.search;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jadex.bridge.ClassInfo;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.IExternalAccess;
import jadex.bridge.IInternalAccess;
import jadex.bridge.sensor.service.TagProperty;
import jadex.bridge.service.IServiceIdentifier;
import jadex.bridge.service.RequiredServiceBinding;
import jadex.bridge.service.RequiredServiceInfo;
import jadex.bridge.service.ServiceScope;
import jadex.bridge.service.component.BasicServiceInvocationHandler;
import jadex.bridge.service.search.ServiceQuery.Multiplicity;
import jadex.commons.SUtil;
import jadex.commons.Tuple3;
/**
* Service query definition. T is the return type for search methods.
*/
public class ServiceQuery
{
/** The raw proxy type (i.e. no proxy). */
public static final String PROXYTYPE_RAW = BasicServiceInvocationHandler.PROXYTYPE_RAW;
/** The direct proxy type (supports custom interceptors, but uses caller thread). */
public static final String PROXYTYPE_DIRECT = BasicServiceInvocationHandler.PROXYTYPE_DIRECT;
/** The (default) decoupled proxy type (decouples from component thread to caller thread). */
public static final String PROXYTYPE_DECOUPLED = BasicServiceInvocationHandler.PROXYTYPE_DECOUPLED;
//-------- constants --------
/** Marker for networks not set. */
//Hack!!! should not be public???
public static final String[] NETWORKS_NOT_SET = new String[]{"__NETWORKS_NOT_SET__"}; // TODO: new String[0] for better performance, but unable to check remotely after marshalling!
/** Default matching modes set the elements with OR semantics. */
public static final Map DEFAULT_MATCHINGMODES = SUtil.createHashMap(
new String[]{ServiceKeyExtractor.KEY_TYPE_TAGS, ServiceKeyExtractor.KEY_TYPE_NETWORKS},
new Boolean[]{Boolean.FALSE, Boolean.FALSE});
//-------- attributes --------
/** The service type. */
protected ClassInfo servicetype;
/** Tags of the service. */
protected String[] servicetags;
/** The service provider. (rename serviceowner?) */
//protected IComponentIdentifier provider;
/** Starting point for the search scoping. */
protected IComponentIdentifier searchstart;
/** The service platform. (Find a service from another known platform, e.g. cms) */
protected IComponentIdentifier platform;
/** The service ID of the target service. Fast lookup of a service by id. */
protected IServiceIdentifier serviceidentifier;
/** The network names. */
protected String[] networknames;
/** Should the service be unrestricted. */
protected Boolean unrestricted;
/** The search scope. */
protected ServiceScope scope;
/** The query owner. (rename queryowner?) */
protected IComponentIdentifier owner;
//-------- influence the result --------
/** Flag, if service by the query owner should be excluded, i.e. do not return my own service. */
protected boolean excludeowner;
/** The multiple flag. Search for multiple services */
protected Multiplicity multiplicity;
/** Flag if event mode is enabled on the query. */
protected boolean eventmode;
/** The matching mode for multivalued terms. True is and and false is or. */
protected Map matchingmodes;
/** Required service proxy type. */
protected String requiredproxytype = PROXYTYPE_DECOUPLED;
//-------- identification of a query --------
/** The query id. Id is used for hashcode and equals and the same is used by servicequeryinfo class.
Allows for hashing queryies and use a queryinfo object for lookup. */
protected String id;
// /** Is the query prepared? Prepared means that the query is ready to be processed by the registry. */
// protected boolean prepared;
/**
* Create a new service query.
*/
protected ServiceQuery()
{
// Not public to not encourage user to use it.
// Here it does NOT set the networknames automatically because used for serialization.
}
// /**
// * Create a new service query.
// */
// public ServiceQuery(ClassInfo servicetype, String scope, IComponentIdentifier owner)
// {
// this(servicetype, scope, (IFilter) null, null, owner);
// }
//
// /**
// * Create a new service query.
// */
// public ServiceQuery(ClassInfo servicetype, String scope, IComponentIdentifier provider, IComponentIdentifier owner)
// {
// this(servicetype, scope, (IFilter) null, provider, owner);
// }
//
/**
* Create a new service query.
*/
public ServiceQuery(Class servicetype)
{
this(servicetype, null);
}
/**
* Create a new service query.
*/
public ServiceQuery(Class servicetype, ServiceScope scope)
{
this(servicetype == null ?(ClassInfo) null : new ClassInfo(servicetype), scope, null);
}
//
// /**
// * Create a new service query.
// */
// public ServiceQuery(Class servicetype, String scope, IFilter filter, IComponentIdentifier provider, IComponentIdentifier owner)
// {
//// this(new ClassInfo(servicetype), scope, filter, provider, owner);this.returntype = servicetype;
// this.servicetype = new ClassInfo(servicetype);
// this.returntype = this.servicetype;
// // todo: what is the best place for this?
// this.scope = scope==null && ServiceIdentifier.isSystemService(servicetype)? ServiceScope.PLATFORM: scope;
// this.filter = filter;
// this.provider = provider;
// this.owner = owner;
//
// }
//
// /**
// * Create a new service query.
// */
// public ServiceQuery(ClassInfo servicetype, String scope, IFilter filter, IComponentIdentifier provider, IComponentIdentifier owner)
// {
// this.returntype = servicetype;
// this.servicetype = servicetype;
// this.scope = scope;
// this.filter = filter;
// this.provider = provider;
// this.owner = owner;
// }
//
// /**
// * Create a new service query.
// */
// public ServiceQuery(Class returntype, Class> servicetype, String scope, IAsyncFilter filter, IComponentIdentifier provider, IComponentIdentifier owner)
// {
// this(new ClassInfo(returntype), new ClassInfo(servicetype), scope, filter, provider, owner);
// }
// /**
// * Create a new service query.
// */
// public ServiceQuery(ClassInfo returntype, ClassInfo servicetype, String scope, IAsyncFilter filter, IComponentIdentifier provider, IComponentIdentifier owner)
// {
// this.returntype = returntype;
// this.servicetype = servicetype;
// this.scope = scope;
// this.filter = filter;
// this.provider = provider;
// this.owner = owner;
// }
//
// /**
// * Create a new service query.
// */
// public ServiceQuery(ClassInfo servicetype, String scope, IAsyncFilter filter, IComponentIdentifier provider, IComponentIdentifier owner)
// {
// this(servicetype, servicetype, scope, filter, provider, owner);
//// this.returntype = servicetype;
//// this.servicetype = servicetype;
//// this.scope = scope;
//// this.filter = filter;
//// this.provider = provider;
//// this.owner = owner;
// }
/**
* Create a new service query.
* owner = startpoint
*/
// public ServiceQuery(Class> servicetype, String scope, IComponentIdentifier provider, IComponentIdentifier owner)
// {
// this(servicetype, scope, provider, owner, null);
// }
/**
* Create a new service query.
*/
public ServiceQuery(Class servicetype, ServiceScope scope, IComponentIdentifier owner)
{
this(servicetype == null ? (ClassInfo) null : new ClassInfo(servicetype), scope, owner);
}
/**
* Create a new service query.
*/
public ServiceQuery(ClassInfo servicetype)
{
this(servicetype, null, null);
}
/**
* Create a new service query.
*/
public ServiceQuery(ClassInfo servicetype, ServiceScope scope, IComponentIdentifier owner)
{
// if(owner==null)
// throw new IllegalArgumentException("Owner must not null");
this.servicetype = servicetype;
this.owner = owner;
this.id = SUtil.createUniqueId();
this.networknames = NETWORKS_NOT_SET;
setScope(scope);
}
/**
* Shallow copy constructor.
* @param original Original query.
*/
public ServiceQuery(ServiceQuery original)
{
this.servicetype = original.servicetype;
this.scope = original.scope;
this.servicetags = original.servicetags;
this.owner = original.owner;
this.id = original.id;
this.networknames = original.networknames;
this.matchingmodes = original.matchingmodes;
this.platform = original.platform;
this.searchstart = original.searchstart;
this.unrestricted = original.unrestricted;
this.requiredproxytype = original.requiredproxytype;
}
/**
* Get the service type.
* @return The service type
*/
public ClassInfo getServiceType()
{
return servicetype;
}
/**
* Set the service type.
* @param type The service type to set
*/
public ServiceQuery setServiceType(ClassInfo servicetype)
{
this.servicetype = servicetype;
return this;
}
/**
* Changes the query to event mode.
*
* @param eventmode the event mode state.
* @deprecated For bean purposes only, use setEventMode().
*/
@Deprecated
public void setEventMode(boolean eventmode)
{
this.eventmode = eventmode;
}
/**
* Changes the query to event mode.
*
* @return The new query.
*/
@SuppressWarnings("unchecked")
public ServiceQuery> setEventMode()
{
this.eventmode = true;
return (ServiceQuery>)this;
}
/**
* Checks if query is in event mode.
* @return True, if in event mode
*/
public boolean isEventMode()
{
return eventmode;
}
/**
* Get the scope.
* @return The scope
*/
public ServiceScope getScope()
{
return scope;
}
/**
* Set the scope.
* @param scope The scope to set
*/
public ServiceQuery setScope(ServiceScope scope)
{
if(ServiceScope.EXPRESSION.equals(scope))
throw new IllegalArgumentException("Cannot use scope 'expression' directly.");
this.scope = scope!=null?scope:ServiceScope.DEFAULT;
return this;
}
/**
* Gets the service tags.
*
* @return The service tags.
*/
public String[] getServiceTags()
{
return servicetags;
}
/**
* Sets the service tags.
* @param servicetags The service tags.
*/
public ServiceQuery setServiceTags(String... servicetags)
{
TagProperty.checkReservedTags(servicetags);
this.servicetags = servicetags;
return this;
}
/**
* Sets the service tags.
* @param servicetags The service tags.
*
* todo: move or refactor to hide complexity!?
*/
public ServiceQuery setServiceTags(String[] servicetags, IExternalAccess component)
{
this.servicetags = TagProperty.createRuntimeTags(servicetags, component).toArray(new String[servicetags!=null ? servicetags.length : 0]);
return this;
}
/**
* Set the provider.
* @param provider The provider to set
*/
public ServiceQuery setProvider(IComponentIdentifier provider)
{
this.searchstart = provider;
this.scope = ServiceScope.COMPONENT_ONLY;
return this;
}
/**
* Get the provider.
* @return The provider
*/
public IComponentIdentifier getSearchStart()
{
return searchstart;
}
/**
* Set the provider.
* @param provider The provider to set
*/
public ServiceQuery setSearchStart(IComponentIdentifier searchstart)
{
this.searchstart = searchstart;
return this;
}
/**
* Get the platform.
* @return The platform
*/
public IComponentIdentifier getPlatform()
{
return platform;
}
/**
* Set the platform.
* @param platform The platform
*/
public ServiceQuery setPlatform(IComponentIdentifier platform)
{
this.platform = platform;
return this;
}
/**
* Gets the service identifier.
*
* @return The service identifier.
*/
public IServiceIdentifier getServiceIdentifier()
{
return serviceidentifier;
}
/**
* Sets the service identifier.
* Also sets the corresponding provider when sid!=null.
*
* @param serviceidentifier The service identifier.
*/
// TODO: looking up sid shouldn't be search/query?
public ServiceQuery setServiceIdentifier(IServiceIdentifier serviceidentifier)
{
this.serviceidentifier = serviceidentifier;
// When setting sid also set provider.
if(serviceidentifier!=null)
setProvider(serviceidentifier.getProviderId());
return this;
}
/**
* Get the owner.
* @return The owner
*/
public IComponentIdentifier getOwner()
{
return owner;
}
/**
* Set the owner.
* @param owner The owner to set
*/
public ServiceQuery setOwner(IComponentIdentifier owner)
{
this.owner = owner;
return this;
}
/**
* Checks if service of the query owner should be excluded.
*
* @return True, if the services should be excluded.
*/
public boolean isExcludeOwner()
{
return excludeowner;
}
/**
* Sets if service of the query owner should be excluded.
*
* @param excludeowner True, if the services should be excluded.
*/
public ServiceQuery setExcludeOwner(boolean excludeowner)
{
this.excludeowner = excludeowner;
return this;
}
/**
* Get the id.
* @return the id
*/
public String getId()
{
return id;
}
/**
* Set the id.
* @param id The id to set
*/
public ServiceQuery setId(String id)
{
this.id = id;
return this;
}
/**
* Get the multiplicity.
* @return the multiplicity
*/
public Multiplicity getMultiplicity()
{
return multiplicity;
}
/**
* Set the multiplicity.
* @param multiplicity The minimum multiplicity to set
*/
public ServiceQuery setMultiplicity(int multiplicity)
{
return setMultiplicity(multiplicity, -1);
}
/**
* Set the multiplicity.
* @param multiplicitystart The minimum multiplicity to set
* @param multiplicityend The max multiplicity to set
*/
public ServiceQuery setMultiplicity(int multiplicitystart, int multiplicityend)
{
return setMultiplicity(new Multiplicity(multiplicitystart, multiplicityend));
}
/**
* Set the multiplicity.
* @param multiplicity The multiplicity to set
*/
public ServiceQuery setMultiplicity(Multiplicity multiplicity)
{
this.multiplicity = multiplicity;
return this;
}
/**
* Gets the specification for the indexer.
* Query needs to be enhanced before calling this method. See RequiredServiceFeature.enhanceQuery()
*
* @return The specification for the indexer.
*/
public List> getIndexerSearchSpec()
{
List> ret = new ArrayList>();
// Problem with normal vs resticted vs. unrestricted queries
// normal: - deliver all services (restr. and unrestr.).
// - unrestricted services do not need networks that fit to those from query (they can always be accessed). Therefore key extractor return MATCH_ALWAYS. important for normal queries
// restricted and unrestricted: use index to find only those. in case of unrestricted query the networks of the query will be omitted (they might have been automatically set)
// normal is both, i.e. unrestricted = null
if(unrestricted != null)
ret.add(new Tuple3(ServiceKeyExtractor.KEY_TYPE_UNRESTRICTED, new String[]{unrestricted.toString()}, getMatchingMode(ServiceKeyExtractor.KEY_TYPE_UNRESTRICTED)));
if(platform != null)
ret.add(new Tuple3(ServiceKeyExtractor.KEY_TYPE_PLATFORM, new String[]{platform.toString()}, getMatchingMode(ServiceKeyExtractor.KEY_TYPE_PLATFORM)));
if(ServiceScope.COMPONENT_ONLY.equals(scope))
{
if(searchstart != null)
ret.add(new Tuple3(ServiceKeyExtractor.KEY_TYPE_PROVIDER, new String[]{searchstart.toString()}, getMatchingMode(ServiceKeyExtractor.KEY_TYPE_PROVIDER)));
else
ret.add(new Tuple3(ServiceKeyExtractor.KEY_TYPE_PROVIDER, new String[]{owner.toString()}, getMatchingMode(ServiceKeyExtractor.KEY_TYPE_PROVIDER)));
}
if(servicetype != null)
ret.add(new Tuple3(ServiceKeyExtractor.KEY_TYPE_INTERFACE, new String[]{servicetype.getGenericTypeName()}, getMatchingMode(ServiceKeyExtractor.KEY_TYPE_INTERFACE)));
if(servicetags != null && servicetags.length > 0)
ret.add(new Tuple3(ServiceKeyExtractor.KEY_TYPE_TAGS, servicetags, getMatchingMode(ServiceKeyExtractor.KEY_TYPE_TAGS)));
if(serviceidentifier != null)
ret.add(new Tuple3(ServiceKeyExtractor.KEY_TYPE_SID, new String[]{serviceidentifier.toString()}, getMatchingMode(ServiceKeyExtractor.KEY_TYPE_SID)));
assert !Arrays.equals(networknames, NETWORKS_NOT_SET) : "Problem: query not enhanced before processing.";
if((unrestricted==null || Boolean.FALSE.equals(unrestricted)) && networknames != null && networknames.length > 0)
ret.add(new Tuple3(ServiceKeyExtractor.KEY_TYPE_NETWORKS, networknames, getMatchingMode(ServiceKeyExtractor.KEY_TYPE_NETWORKS)));
return ret;
}
/**
* Get the matching mode for a key.
* @param key The key name.
* @return True for and, false for or.
*/
public Boolean getMatchingMode(String key)
{
return matchingmodes==null? DEFAULT_MATCHINGMODES.get(key): matchingmodes.get(key);
}
/**
* Set a matching mode.
* @param key The key name.
* @param and True for and.
*/
public ServiceQuery setMatchingMode(String key, Boolean and)
{
if(matchingmodes==null)
matchingmodes = new HashMap(DEFAULT_MATCHINGMODES);
matchingmodes.put(key, and);
return this;
}
/**
* Get the unrestricted mode.
* @return The unrestricted mode.
*/
public Boolean isUnrestricted()
{
return unrestricted;
}
/**
* Set the unrestricted mode.
* @param unrestricted the unrestricted to set
*/
public ServiceQuery setUnrestricted(Boolean unrestricted)
{
this.unrestricted = unrestricted;
return this;
}
/**
* Tests if the query keys matches a service.
*
* @param service The service.
* @return True, if the service matches the keys.
*/
protected boolean matchesKeys(IServiceIdentifier service)
{
if (servicetype != null && !service.getServiceType().getGenericTypeName().equals(servicetype))
return false;
if (servicetags != null)
{
Set tagsset = ServiceKeyExtractor.getKeysStatic(ServiceKeyExtractor.KEY_TYPE_TAGS, service);
if (tagsset == null)
return false;
for (String tag : servicetags)
{
if (!tagsset.contains(tag))
{
return false;
}
}
}
if (ServiceScope.COMPONENT_ONLY.equals(scope) &&
!((searchstart != null && service.getProviderId().equals(searchstart)) ||
service.getProviderId().equals(owner)))
return false;
// if (provider != null && !provider.equals(service.getProviderId()))
// return false;
if (platform != null && !platform.equals(service.getProviderId().getRoot()))
return false;
return true;
}
// /**
// * Get the prepared.
// * @return the prepared
// */
// public boolean isPrepared()
// {
// return prepared;
// }
//
// /**
// * Set the prepared.
// * @param prepared The prepared to set
// */
// public void setPrepared(boolean prepared)
// {
// this.prepared = prepared;
// }
// /**
// * Prepare the query.
// */
// public void prepare(IComponentIdentifier cid)
// {
// if(!prepared)
// {
// networknames = getNetworkNames(cid);
// prepared = true;
// }
// }
/**
* Get the networknames.
* @return the networknames
*/
public String[] getNetworkNames()
{
return networknames;
}
/**
* Set the networknames.
* @param networknames The networknames to set
*/
public ServiceQuery setNetworkNames(String... networknames)
{
this.networknames = networknames;
return this;
}
/**
* Returns the requested required service proxy type.
* @return The requested required service proxy type.
*/
public String getRequiredProxyType()
{
return requiredproxytype;
}
/**
* Sets the requested required service proxy type.
* @param requiredproxytype The requested required service proxy type.
*/
public ServiceQuery setRequiredProxyType(String requiredproxytype)
{
this.requiredproxytype = requiredproxytype;
return this;
}
/**
* Get the hashcode.
*/
public int hashCode()
{
return id.hashCode()*13;
}
/**
* Test if other object equals this one.
*/
public boolean equals(Object obj)
{
boolean ret = false;
if(obj instanceof ServiceQuery)
{
ServiceQuery> other = (ServiceQuery>)obj;
ret = SUtil.equals(getId(), other.getId());
}
return ret;
}
/**
* Get the target platform if specified (using platform and provider).
* @return The target platform.
*/
public IComponentIdentifier getTargetPlatform()
{
if (getPlatform()!=null)
return getPlatform().getRoot();
if (ServiceScope.COMPONENT_ONLY.equals(scope))
return searchstart != null ? searchstart.getRoot() : owner.getRoot();
return null;
}
/**
* When searching for declared service -> map required service declaration to service query.
*/
public static ServiceQuery getServiceQuery(IInternalAccess ia, RequiredServiceInfo info)
{
// TODO??? : no, but hardconstraints should be added, NFR props are not for search
// info.getNFRProperties();
// todo:
// info.getDefaultBinding().getComponentName();
// info.getDefaultBinding().getComponentType();
ServiceQuery ret = new ServiceQuery(info.getType(), info.getDefaultBinding().getScope(), ia.getId());
//ret.setMultiplicity(info.isMultiple() ? Multiplicity.ZERO_MANY : Multiplicity.ONE);
Multiplicity m = new Multiplicity();
if(info.getMin()!=RequiredServiceInfo.UNDEFINED)
m.setFrom(info.getMin());
if(info.getMax()!=RequiredServiceInfo.UNDEFINED)
m.setTo(info.getMax());
if(info.getTags()!=null)
ret.setServiceTags(info.getTags().toArray(new String[info.getTags().size()]), ia.getExternalAccess());
return ret;
}
/**
* When searching with query -> create required service info from service query.
*/
public static RequiredServiceInfo createServiceInfo(ServiceQuery query)
{
// TODO: multiplicity required here for info? should not be needed for proxy creation
RequiredServiceBinding binding = new RequiredServiceBinding(SUtil.createUniqueId(), query.getScope());
binding.setProxytype(query.getRequiredProxyType());
Multiplicity m = query.getMultiplicity();
return new RequiredServiceInfo(null, query.getServiceType(), m==null? RequiredServiceInfo.UNDEFINED: m.getFrom(),
m==null? RequiredServiceInfo.UNDEFINED: m.getTo() , binding, null, query.getServiceTags()==null ? null : Arrays.asList(query.getServiceTags()));
}
/**
* Get the string representation.
*/
public String toString()
{
StringBuffer ret = new StringBuffer("ServiceQuery(");
if(servicetype!=null)
{
ret.append(ret.length()==13?"":", ");
ret.append("servicetype=");
ret.append(servicetype);
}
if(serviceidentifier!=null)
{
ret.append(ret.length()==13?"":", ");
ret.append("serviceidentifier=");
ret.append(serviceidentifier);
}
if(multiplicity!=null)
{
ret.append(ret.length()==13?"":", ");
ret.append("multiplicity=");
ret.append(multiplicity);
}
if(servicetags!=null)
{
ret.append(ret.length()==13?"":", ");
ret.append("servicetags=");
ret.append(Arrays.toString(servicetags));
}
if(searchstart!=null)
{
ret.append(ret.length()==13?"":", ");
ret.append("searchstart=");
ret.append(searchstart);
}
if(platform!=null)
{
ret.append(ret.length()==13?"":", ");
ret.append("platform=");
ret.append(platform);
}
if(networknames!=null)
{
ret.append(ret.length()==13?"":", ");
ret.append("networknames=");
ret.append(Arrays.toString(networknames));
}
if(unrestricted!=null)
{
ret.append(ret.length()==13?"":", ");
ret.append("unrestricted=");
ret.append(unrestricted);
}
if(scope!=null && !ServiceScope.DEFAULT.equals(scope))
{
ret.append(ret.length()==13?"":", ");
ret.append("scope=");
ret.append(scope);
}
if(owner!=null)
{
ret.append(ret.length()==13?"":", ");
ret.append("owner=");
ret.append(owner);
}
ret.append(")");
return ret.toString();
}
//-------- query multiplicity --------
/**
* Define cases for multiplicity.
*/
public static class Multiplicity
{
//-------- constants --------
/** '0..1' multiplicity for single optional service. */
public static Multiplicity ZERO_ONE = new Multiplicity(0, 1);
/** '1' multiplicity for required service (default for searchService methods). */
public static Multiplicity ONE = new Multiplicity(1, 1);
/** '0..*' multiplicity for optional multi service (default for searchServices methods). */
public static Multiplicity ZERO_MANY = new Multiplicity(0, -1);
/** '1..*' multiplicity for required service (default for searchService methods). */
public static Multiplicity ONE_MANY = new Multiplicity(1, -1);
//-------- attributes --------
/** The minimal number of services required. Otherwise search ends with ServiceNotFoundException. */
private int from;
/** The maximal number of services returned. Afterwards search/query will terminate. */
private int to;
//-------- constructors --------
/**
* Bean constructor.
* Not meant for direct use.
* Defaults to invalid multiplicity ('0..0')!
*/
public Multiplicity()
{
this.from = -2; // = UNDEFINED
this.to = -2;
}
/**
* Create a multiplicity.
* @param from The minimal number of services for the search/query being considered successful (positive integer or 0).
* @param to The maximal number of services returned by the search/query (positive integer or -1 for unlimited).
*/
public Multiplicity(int from, int to)
{
setFrom(from);
setTo(to);
}
//-------- methods --------
/**
* Get the 'from' value, i.e. the minimal number of services required.
* Otherwise search ends with ServiceNotFoundException.
*/
public int getFrom()
{
return from;
}
/**
* Set the 'from' value, i.e. the minimal number of services required.
* Otherwise search ends with ServiceNotFoundException.
* @param from Positive integer or 0
*/
public void setFrom(int from)
{
if(from<0)
throw new IllegalArgumentException("'from' must be a positive value or 0.");
this.from = from;
}
/**
* Get the 'to' value, i.e. The maximal number of services returned.
* Afterwards search/query will terminate.
*/
public int getTo()
{
return to;
}
/**
* Get the 'to' value, i.e. The maximal number of services returned.
* Afterwards search/query will terminate.
* @param to Positive integer or -1 for unlimited.
*/
public void setTo(int to)
{
if(to!=-1 && to<1)
throw new IllegalArgumentException("'to' must be a positive value or -1.");
this.to = to;
}
/**
* Get a string representation of the multiplicity.
*/
@Override
public String toString()
{
return from==to ? Integer.toString(from) : from + ".." + (to==-1 ? "*" : Integer.toString(to));
}
}
}