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; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.Date; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; /** * Abstract base class for all knowledge definition classes. * * FIXME We support event, abstraction, and primitive parameter definitions with * the same name, yet <code>Protempa</code>'s public API assumes that they all * share the same namespace. This needs to be fixed. I'm leaning toward having * all knowledge definitions share the same namespace, in which case, no changes * to Protempa's API would be required, and the duplicate id checking could all * occur in this class in a concrete implementation of <code>setId0()</code>. * * @author Andrew Post */ public abstract class AbstractPropositionDefinition implements PropositionDefinition { private static final long serialVersionUID = -2754387751719003721L; private static final PropertyDefinition[] EMPTY_PROPERTIES = new PropertyDefinition[0]; private static final ReferenceDefinition[] EMPTY_REFERENCES = new ReferenceDefinition[0]; private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0]; protected static final String CHILDREN_PROPERTY = "children"; /** * The id of propositions created by this definition. */ private final String id; private String propositionId; /** * The display name of this knowledge definition. */ private String displayName; /** * The abbreviated display name of this knowledge definition. */ private String abbrevDisplayName; /** * An array of proposition definition id {@link String}s. */ private String[] inverseIsA; protected String[] children; private String[] termIds; private String description; private PropertyDefinition[] propertyDefinitions; private ReferenceDefinition[] referenceDefinitions; private boolean inDataSource; protected PropertyChangeSupport changes; private SourceId sourceId; private Date accessed; private Date created; private Date updated; private Date downloaded; private String version; private Attribute[] attributes; /** * Creates a new knowledge definition. * * @param id the requested {@link String} id of propositions created by this * definition. If <code>null</code> or already taken by another knowledge * definition, another id will be assigned (check with * <code>getId()</code>). */ AbstractPropositionDefinition(String id) { if (id == null) { throw new IllegalArgumentException("id cannot be null"); } this.id = id.intern(); this.propositionId = this.id; this.children = ArrayUtils.EMPTY_STRING_ARRAY; this.inverseIsA = ArrayUtils.EMPTY_STRING_ARRAY; this.termIds = ArrayUtils.EMPTY_STRING_ARRAY; this.displayName = ""; this.abbrevDisplayName = ""; this.description = ""; this.propertyDefinitions = EMPTY_PROPERTIES; this.referenceDefinitions = EMPTY_REFERENCES; this.sourceId = NotRecordedSourceId.getInstance(); this.attributes = EMPTY_ATTRIBUTES; } @Override public final String getId() { return this.id; } @Override public final String getPropositionId() { return this.propositionId; } /** * Sets the proposition id of propositions derived by this proposition * definition. * * @param propId a proposition id. Pass in <code>null</code> to set the * value of this field to the value of this proposition definition's * <code>id</code> field. */ public final void setPropositionId(String propId) { if (propId == null) { this.propositionId = this.id; } else { this.propositionId = propId; } } @Override public final String getAbbreviatedDisplayName() { return this.abbrevDisplayName; } /** * Sets this knowledge definition's abbreviated display name. * * @param abbrev an abbreviated display name {@link String}. */ public final void setAbbreviatedDisplayName(String abbrev) { if (abbrev == null) { abbrev = ""; } String old = this.abbrevDisplayName; this.abbrevDisplayName = abbrev; if (this.changes != null) { this.changes.firePropertyChange("abbreviatedDisplayName", old, abbrev); } } @Override public final String getDisplayName() { return this.displayName; } /** * Sets this proposition definition's human-readable display name. * * @param displayName a display name {@link String}. */ public final void setDisplayName(String displayName) { if (displayName == null) { displayName = ""; } String old = this.displayName; this.displayName = displayName; if (this.changes != null) { this.changes.firePropertyChange("displayName", old, displayName); } } @Override public String getDescription() { return this.description; } public void setDescription(String description) { if (description == null) { description = ""; } String old = this.description; this.description = description; if (this.changes != null) { this.changes.firePropertyChange("description", old, this.description); } } @Override public String[] getInverseIsA() { return inverseIsA.clone(); } /** * Sets the children of this proposition definition. * * @param inverseIsA a {@link String[]} of proposition definition ids. No * <code>null</code> or duplicate elements allowed. */ public void setInverseIsA(String... inverseIsA) { String[] old = this.inverseIsA; ProtempaUtil.checkArrayForNullElement(inverseIsA, "inverseIsA"); ProtempaUtil.checkArrayForDuplicates(inverseIsA, "inverseIsA"); this.inverseIsA = inverseIsA.clone(); if (this.changes != null) { this.changes.firePropertyChange("inverseIsA", old, getInverseIsA()); } recalculateChildren(); } @Override public String[] getChildren() { return this.children.clone(); } @Override public final String[] getTermIds() { return this.termIds.clone(); } /** * Assigns this proposition with associated {@link TermDefinition} ids. * * @param termId a term definition id {@link String}. No <code>null</code> * or duplicate elements allowed. */ public final void setTermIds(String... termIds) { String[] old = this.termIds; ProtempaUtil.checkArrayForNullElement(termIds, "termIds"); ProtempaUtil.checkArrayForDuplicates(termIds, "termIds"); this.termIds = termIds.clone(); if (this.changes != null) { this.changes.firePropertyChange("termIds", old, getTermIds()); } } @Override public final PropertyDefinition[] getPropertyDefinitions() { return this.propertyDefinitions.clone(); } @Override public final PropertyDefinition propertyDefinition(String id) { for (PropertyDefinition propertyDefinition : this.propertyDefinitions) { if (propertyDefinition.getId().equals(id)) { return propertyDefinition; } } return null; } public final void setPropertyDefinitions(PropertyDefinition... propertyDefinitions) { PropertyDefinition[] old = this.propertyDefinitions; ProtempaUtil.checkArrayForNullElement(propertyDefinitions, "propertyDefinitions"); ProtempaUtil.checkArrayForDuplicates(propertyDefinitions, "propertyDefinitions"); this.propertyDefinitions = propertyDefinitions.clone(); if (this.changes != null) { this.changes.firePropertyChange("propertyDefinitions", old, this.propertyDefinitions); } } @Override public final ReferenceDefinition[] getReferenceDefinitions() { return this.referenceDefinitions.clone(); } @Override public final ReferenceDefinition referenceDefinition(String name) { for (ReferenceDefinition referenceDefinition : this.referenceDefinitions) { if (referenceDefinition.getId().equals(name)) { return referenceDefinition; } } return null; } public final void setReferenceDefinitions(ReferenceDefinition... referenceDefinitions) { ReferenceDefinition[] old = this.referenceDefinitions; ProtempaUtil.checkArrayForNullElement(referenceDefinitions, "referenceDefinitions"); ProtempaUtil.checkArrayForDuplicates(referenceDefinitions, "referenceDefinitions"); this.referenceDefinitions = referenceDefinitions.clone(); if (this.changes != null) { this.changes.firePropertyChange("referenceDefinitions", old, this.referenceDefinitions); } } @Override public boolean getInDataSource() { return this.inDataSource; } public void setInDataSource(boolean inDataSource) { boolean old = this.inDataSource; this.inDataSource = inDataSource; if (this.changes != null) { this.changes.firePropertyChange("inDataSource", old, this.inDataSource); } } @Override public SourceId getSourceId() { return this.sourceId; } public void setSourceId(SourceId sourceId) { if (sourceId == null) { this.sourceId = NotRecordedSourceId.getInstance(); } else { this.sourceId = sourceId; } } @Override public Date getAccessed() { return this.accessed; } @Override public Date getCreated() { return this.created; } @Override public Date getUpdated() { return this.updated; } public void setAccessed(Date accessed) { this.accessed = accessed; } public void setCreated(Date created) { this.created = created; } public void setUpdated(Date updated) { this.updated = updated; } @Override public String getVersion() { return this.version; } public void setVersion(String version) { this.version = version; } @Override public Date getDownloaded() { return this.downloaded; } public void setDownloaded(Date downloaded) { this.downloaded = downloaded; } @Override public Attribute[] getAttributes() { return attributes.clone(); } public void setAttributes(Attribute[] attributes) { if (attributes == null) { this.attributes = EMPTY_ATTRIBUTES; } else { this.attributes = attributes.clone(); } } @Override public Attribute attribute(String name) { for (Attribute attribute : this.attributes) { if (attribute.getName().equals(name)) { return attribute; } } return null; } @Override public void addPropertyChangeListener(PropertyChangeListener listener) { if (this.changes == null) { this.changes = new PropertyChangeSupport(this); } if (this.changes != null) { this.changes.addPropertyChangeListener(listener); } } @Override public void removePropertyChangeListener(PropertyChangeListener listener) { if (this.changes != null) { this.changes.removePropertyChangeListener(listener); } } @Override public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { if (this.changes == null) { this.changes = new PropertyChangeSupport(this); } this.changes.addPropertyChangeListener(propertyName, listener); } @Override public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { if (this.changes != null) { this.changes.removePropertyChangeListener(propertyName, listener); } } /** * Resets this proposition definition to default values. */ public void reset() { setDisplayName(null); setAbbreviatedDisplayName(null); setDescription(null); setInverseIsA(ArrayUtils.EMPTY_STRING_ARRAY); setTermIds(ArrayUtils.EMPTY_STRING_ARRAY); setPropertyDefinitions(new PropertyDefinition[] {}); setReferenceDefinitions(new ReferenceDefinition[] {}); setInDataSource(false); setAccessed(null); setCreated(null); setUpdated(null); } protected abstract void recalculateChildren(); @Override public String toString() { return ReflectionToStringBuilder.reflectionToString(this); } }