/*
* Copyright 2015-2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* 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.hawkular.inventory.api.filters;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Stream;
import org.hawkular.inventory.api.model.AbstractElement;
import org.hawkular.inventory.api.model.Entity;
import org.hawkular.inventory.api.model.Relationship;
import org.hawkular.inventory.api.model.StructuredData;
import org.hawkular.inventory.paths.CanonicalPath;
import org.hawkular.inventory.paths.RelativePath;
import org.hawkular.inventory.paths.SegmentType;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* @author Lukas Krejci
* @since 0.0.1
*/
public final class With {
private With() {
}
public static Ids id(String id) {
return new Ids(id);
}
public static Ids ids(String... ids) {
return new Ids(ids);
}
@SafeVarargs
public static Types types(Class<? extends Entity<?, ?>>... types) {
return new Types(types);
}
public static Types type(Class<? extends Entity<?, ?>> type) {
return new Types(type);
}
public static Types types(SegmentType... types) {
@SuppressWarnings("unchecked")
Class<? extends Entity<?, ?>>[] clss = Stream.of(types).map(With::convertAsEntityType)
.toArray(Class[]::new);
return new Types(clss);
}
public static Types type(SegmentType type) {
return new Types(convertAsEntityType(type));
}
@SuppressWarnings("unchecked")
private static Class<? extends Entity<?, ?>> convertAsEntityType(SegmentType type) {
Class<? extends AbstractElement<?, ?>> cls = AbstractElement.toElementClass(type);
if (Relationship.class.isAssignableFrom(cls)) {
throw new IllegalArgumentException("Type filter not applicable to relationships.");
}
return (Class<? extends Entity<?, ?>>) cls;
}
public static CanonicalPaths path(CanonicalPath path) {
return new CanonicalPaths(path);
}
public static CanonicalPaths paths(CanonicalPath... paths) {
return new CanonicalPaths(paths);
}
/**
* Constructs a new filter to only contain elements at the current position in the graph traversal that
* can also be reached using the provided relative path.
*
* <p>If the label is null, the relative path is applied directly to the current position in the traversal.
*
* @param markerLabel the filter chain this filter is being added to can contain a {@link Marker} with this
* label that marks the position against which the relative path would be resolved against
* @param path the relative path of the elements.
* @return a new filter
*/
public static RelativePaths relativePath(String markerLabel, RelativePath path) {
return new RelativePaths(markerLabel, path);
}
/**
* Constructs a new filter to only contain elements at the current position in the graph traversal that
* can also be reached using at least one of the provided relative paths.
*
* <p>If the label is null, the relative path is applied directly to the current position in the traversal.
*
* @param markerLabel the filter chain this filter is being added to can contain a {@link Marker} with this
* label that marks the position against which the relative path would be resolved against
* @param paths the relative paths of the elements.
* @return a new filter
* @see #relativePath(String, RelativePath)
*/
public static RelativePaths relativePaths(String markerLabel, RelativePath... paths) {
return new RelativePaths(markerLabel, paths);
}
/**
* Filters for entities that have a property of given name regardless of its value.
*
* @param name the name of the property
* @return the filter
*/
public static PropertyValues property(String name) {
return new PropertyValues(name);
}
/**
* Filters for entities that have a property of given name equal to given value
*
* @param name the name of the property
* @param value the desired value
* @return the filter
*/
public static PropertyValues propertyValue(String name, Object value) {
return new PropertyValues(name, value);
}
/**
* Filters for entities that have a property of given name equal to one of the provided values.
*
* @param name the name of the property
* @param values the possible values
* @return the filter
*/
public static PropertyValues propertyValues(String name, Object... values) {
return new PropertyValues(name, values);
}
/**
* Checks whether there is data on the provided relative path. This filter is only really applicable
* on the {@link org.hawkular.inventory.api.model.DataEntity}. I.e. the relative path is always resolved
* against the current position in the traversal, which is assumed to resolve to a data entity.
*
* @param dataPath the relative path to the data
* @return the filter
*/
public static DataAt dataAt(RelativePath dataPath) {
return new DataAt(dataPath);
}
/**
* Filters for structured data with exactly the specified value.
*
* @param value the value to look for
* @return the filter
*/
public static DataValued dataValue(Serializable value) {
return new DataValued(value);
}
/**
* Filters for structured data with one of the provided types.
*
* @param types the types to filter the structured data with
* @return the filter
* @see StructuredData#getType()
*/
public static DataOfTypes dataOfTypes(StructuredData.Type... types) {
return new DataOfTypes(types);
}
/**
* Looks for resource or metric types that have the same identity hash as the entity/ies on the current position
* in the filter chain.
*
* @return the filter
*/
public static SameIdentityHash sameIdentityHash() {
return SameIdentityHash.INSTANCE;
}
public static Names name(String name) {
return names(name);
}
public static Names names(String... names) {
return new Names(names);
}
public static final class Ids extends Filter {
private final String[] ids;
public Ids(String... ids) {
this.ids = ids;
}
public String[] getIds() {
return ids;
}
@Override
public String toString() {
return "Ids" + Arrays.asList(ids).toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Ids)) return false;
Ids other = (Ids) o;
return Arrays.equals(ids, other.ids);
}
@Override
public int hashCode() {
return Arrays.hashCode(ids);
}
}
public static final class Types extends Filter {
private final Class<? extends Entity<?, ?>>[] types;
@SafeVarargs
public Types(Class<? extends Entity<?, ?>>... types) {
this.types = types;
}
public Class<? extends Entity<?, ?>>[] getTypes() {
return types;
}
@JsonIgnore
public SegmentType[] getSegmentTypes() {
return Arrays.stream(types).map(AbstractElement::segmentTypeFromType).toArray(SegmentType[]::new);
}
@Override
public String toString() {
StringBuilder ret = new StringBuilder("Types[");
if (types.length > 0) {
ret.append(types[0].getSimpleName());
for(int i = 1; i < types.length; ++i) {
ret.append(", ").append(types[i].getSimpleName());
}
}
ret.append("]");
return ret.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Types)) return false;
Types other = (Types) o;
return Arrays.equals(types, other.types);
}
@Override
public int hashCode() {
return Arrays.hashCode(types);
}
}
public static final class CanonicalPaths extends Filter {
private final CanonicalPath[] paths;
public CanonicalPaths(CanonicalPath... paths) {
this.paths = paths;
}
public CanonicalPath[] getPaths() {
return paths;
}
@Override
public String toString() {
return "CanonicalPaths" + Arrays.asList(paths).toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CanonicalPaths)) return false;
CanonicalPaths other = (CanonicalPaths) o;
return Arrays.equals(paths, other.paths);
}
@Override
public int hashCode() {
return Arrays.hashCode(paths);
}
}
public static final class RelativePaths extends Filter {
private final String markerLabel;
private final RelativePath[] paths;
public RelativePaths(String markerLabel, RelativePath... paths) {
this.markerLabel = markerLabel;
this.paths = paths;
}
public String getMarkerLabel() {
return markerLabel;
}
public RelativePath[] getPaths() {
return paths;
}
@Override
public String toString() {
return "RelativePaths" + Arrays.asList(paths).toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof RelativePaths)) return false;
RelativePaths other = (RelativePaths) o;
return Arrays.equals(paths, other.paths);
}
@Override
public int hashCode() {
return Arrays.hashCode(paths);
}
}
public static final class PropertyValues extends Filter {
private final String name;
private final Object[] values;
public PropertyValues(String name, Object... values) {
this.name = name;
this.values = values;
}
public String getName() {
return name;
}
public Object[] getValues() {
return values;
}
@Override
public String toString() {
return "PropertyValues[" + "name='" + name + '\'' + ", values=" + Arrays.toString(values) + ']';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PropertyValues)) return false;
PropertyValues that = (PropertyValues) o;
return name.equals(that.name) && Arrays.equals(values, that.values);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + Arrays.hashCode(values);
return result;
}
}
public static final class DataValued extends Filter {
private final Serializable value;
public DataValued(Serializable value) {
this.value = value;
}
public Serializable getValue() {
return value;
}
@Override
public String toString() {
return "DataValued[" + "value=" + value + ']';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DataValued)) return false;
DataValued that = (DataValued) o;
return Objects.equals(value, that.value);
}
@Override
public int hashCode() {
return value != null ? value.hashCode() : 0;
}
}
public static final class DataAt extends Filter {
private final RelativePath dataPath;
public DataAt(RelativePath dataPath) {
this.dataPath = dataPath;
}
public RelativePath getDataPath() {
return dataPath;
}
@Override
public String toString() {
return "DataAt[" + "dataPath=" + dataPath + ']';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DataAt)) return false;
DataAt dataAt = (DataAt) o;
return dataPath.equals(dataAt.dataPath);
}
@Override
public int hashCode() {
return dataPath.hashCode();
}
}
public static final class DataOfTypes extends Filter {
private final StructuredData.Type[] types;
public DataOfTypes(StructuredData.Type... types) {
this.types = types;
}
public StructuredData.Type[] getTypes() {
return types;
}
@Override
public String toString() {
return "DataOfTypes[" + "types=" + Arrays.toString(types) + ']';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DataOfTypes)) return false;
DataOfTypes that = (DataOfTypes) o;
return Arrays.equals(types, that.types);
}
@Override
public int hashCode() {
return Arrays.hashCode(types);
}
}
public static final class SameIdentityHash extends Filter {
public static final SameIdentityHash INSTANCE = new SameIdentityHash();
public SameIdentityHash() {
}
@Override
public boolean equals(Object obj) {
return this == obj || (obj instanceof SameIdentityHash);
}
@Override
public int hashCode() {
return 0;
}
@Override
public String toString() {
return "SameIdentityHash";
}
}
public static final class Names extends Filter {
private final String[] names;
public Names(String... names) {
this.names = names;
}
public String[] getNames() {
return names;
}
@Override
public String toString() {
return "Names[names=" + Arrays.toString(names) + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Names)) return false;
Names that = (Names) o;
return Arrays.equals(names, that.names);
}
@Override
public int hashCode() {
return Arrays.hashCode(names);
}
}
}