Java tutorial
/* * #%L * Protempa Framework * %% * Copyright (C) 2012 - 2013 Emory University * %% * 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% */ package org.protempa.query; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.Serializable; import java.util.HashSet; import java.util.Set; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.builder.ToStringBuilder; import org.protempa.*; import org.protempa.backend.dsb.filter.Filter; /** * * @author Andrew Post */ public class DefaultQueryBuilder implements QueryBuilder, Serializable { private static final long serialVersionUID = -3920993703423486485L; private static final PropositionDefinition[] EMPTY_PROP_DEF_ARRAY = new PropositionDefinition[0]; // Flag to control validation of proposition IDs. Should only be turned off // for testing. private static boolean validatePropositionIds = true; private String[] keyIds; private Filter filters; private String[] propIds; @SuppressWarnings("unchecked") private And<String>[] termIds; private PropositionDefinition[] propDefs; private String name; private String username; private final PropertyChangeSupport changes; private QueryMode queryMode; public DefaultQueryBuilder() { this.changes = new PropertyChangeSupport(this); this.propDefs = EMPTY_PROP_DEF_ARRAY; this.keyIds = ArrayUtils.EMPTY_STRING_ARRAY; this.propIds = ArrayUtils.EMPTY_STRING_ARRAY; this.termIds = new And[0]; this.queryMode = Query.DEFAULT_QUERY_MODE; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public QueryMode getQueryMode() { return queryMode; } public void setQueryMode(QueryMode queryMode) { QueryMode old = this.queryMode; if (queryMode == null) { this.queryMode = Query.DEFAULT_QUERY_MODE; } else { this.queryMode = queryMode; } this.changes.firePropertyChange("queryMode", old, this.queryMode); } /** * Gets the filters to be applied to this query. * * @return a {@link Filter}. */ public final Filter getFilters() { return this.filters; } /** * Sets the filters to apply to this query. * * Note that in order to serialize this query, the supplied filters must * also implement {@link Serializable}. * * @param filters a {@link Filter}. */ public final void setFilters(Filter filters) { Filter old = this.filters; this.filters = filters; this.changes.firePropertyChange("filters", old, this.filters); } /** * Returns the key ids to be queried. An array of length 0 means that all * key ids will be queried. * * @return a {@link String[]}. Never returns <code>null</code>. */ public final String[] getKeyIds() { return this.keyIds.clone(); } /** * Sets the key ids to be queried. An array of length 0 or * <code>null</code> means that all key ids will be queried. * * @param keyIds a {@link String[]} of key ids. If <code>null</code>, an * empty {@link String[]} will be stored. */ public final void setKeyIds(String[] keyIds) { if (keyIds == null) { keyIds = ArrayUtils.EMPTY_STRING_ARRAY; } String[] old = this.keyIds; this.keyIds = keyIds.clone(); this.changes.firePropertyChange("keyIds", old, this.keyIds); } /** * Returns the proposition ids to be queried. An array of length 0 means * that all proposition ids will be queried. * * @param propIds a {@link String[]}. Never returns <code>null</code>. */ public final String[] getPropositionIds() { return this.propIds.clone(); } /** * Sets the proposition ids to be queried. An array of length 0 or * <code>null</code> means that all proposition ids will be queried. * * @param propIds a {@link String[]} of proposition ids. If * <code>null</code>, an empty {@link String[]} will be stored. */ public final void setPropositionIds(String[] propIds) { String[] old = this.propIds; if (propIds == null) { this.propIds = ArrayUtils.EMPTY_STRING_ARRAY; } else { this.propIds = propIds.clone(); ProtempaUtil.internAll(this.propIds); } this.changes.firePropertyChange("propIds", old, this.propIds); } /** * Gets the term ids to be queried in disjunctive normal form. PROTEMPA will * navigate these terms' subsumption hierarchy, find proposition definitions * that have been annotated with each term, and add those to the query. * <code>And</code>'d term ids will only match a proposition definition if * it is annotated with all of the specified term ids (or terms in their * subsumption hierarchies). * * @return a {@link String[]} of term ids representing disjunctive normal * form. */ public final And<String>[] getTermIds() { return this.termIds.clone(); } /** * Sets the term ids to be queried in disjunctive normal form. If any terms * are specified, PROTEMPA will navigate the term's subsumption hierarchy, * find proposition definitions that have been annotated with each term, and * add those to the query. If * <code>and</code>'d term ids are specified, proposition definitions will * only match if they are annotated with all of the specified term ids (or * terms in their subsumption hierarchies). * * @param termIds a {@link And[]} term ids representing disjunctive normal * form. */ @SuppressWarnings("unchecked") public final void setTermIds(And<String>[] termIds) { if (termIds == null) { termIds = new And[0]; } And<String>[] old = this.termIds; this.termIds = (And<String>[]) termIds.clone(); this.changes.firePropertyChange("termIds", old, this.termIds); } /** * Returns an optional set of user-specified proposition definitions. * * @return an array of {@link PropositionDefinition}s. */ public final PropositionDefinition[] getPropositionDefinitions() { return this.propDefs.clone(); } /** * Returns an optional set of user-specified proposition definitions. * * @param propDefs an array of {@link PropositionDefinition}s. */ public final void setPropositionDefinitions(PropositionDefinition[] propDefs) { if (propDefs == null) { propDefs = EMPTY_PROP_DEF_ARRAY; } PropositionDefinition[] old = this.propDefs; this.propDefs = propDefs.clone(); this.changes.firePropertyChange("propositionDefinitions", old, this.propDefs); } /** * Adds listeners for changes to this Query's properties. * * @param listener a {@link PropertyChangeListener}. */ public final void addPropertyChangeListener(PropertyChangeListener listener) { this.changes.addPropertyChangeListener(listener); } /** * Removes listeners for changes to this Query's properties. * * @param listener a {@link PropertyChangeListener}. */ public final void removePropertyChangeListener(PropertyChangeListener listener) { this.changes.removePropertyChangeListener(listener); } /** * Adds listeners for changes to the specified property. * * @param propertyName the name {@link String} of the property of interest. * @param listener a {@link PropertyChangeListener}. */ public final void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { this.changes.addPropertyChangeListener(propertyName, listener); } /** * Removes listeners for changes to the specified property. * * @param propertyName the name {@link String} of the property that is no * longer of interest. * @param listener a {@link PropertyChangeListener}. */ public final void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { this.changes.removePropertyChangeListener(propertyName, listener); } @Override public Query build(KnowledgeSource knowledgeSource, AlgorithmSource algorithmSource) throws QueryBuildException { if (validatePropositionIds) { Set<String> userSpecifiedPropIds = new HashSet<>(); for (PropositionDefinition propDef : this.propDefs) { userSpecifiedPropIds.add(propDef.getId()); } for (PropositionDefinition propDef : this.propDefs) { for (String propId : propDef.getChildren()) { try { if (!userSpecifiedPropIds.contains(propId) && !knowledgeSource.hasPropositionDefinition(propId)) { throw new QueryBuildException("Invalid proposition id: " + propId); } } catch (KnowledgeSourceReadException ex) { throw new QueryBuildException("Could not build query", ex); } } } for (String propId : propIds) { try { boolean isUserSpecified = false; if (userSpecifiedPropIds.contains(propId)) { isUserSpecified = true; } if (!isUserSpecified && !knowledgeSource.hasPropositionDefinition(propId)) { throw new QueryBuildException("Invalid proposition id: " + propId); } } catch (KnowledgeSourceReadException ex) { throw new QueryBuildException("Could not build query", ex); } } } return new Query(this.name, this.username, this.keyIds, this.filters, this.propIds, this.termIds, this.propDefs, this.queryMode); } @Override public String toString() { return ToStringBuilder.reflectionToString(this); } /** * Set the value of the flag that determined whether the build method * validates proposition IDs. * * @param validatePropositionIds Proposition IDs are validated if, and only * if, this is true. The default value for this is true. */ public static void setValidatePropositionIds(boolean validatePropositionIdsFlag) { validatePropositionIds = validatePropositionIdsFlag; } public static boolean isValidatePropositionIds() { return validatePropositionIds; } }