/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.vdb; import static org.teiid.designer.vdb.VdbPlugin.UTIL; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.teiid.core.designer.properties.PropertyDefinition; import org.teiid.core.designer.util.I18nUtil; import org.teiid.core.designer.util.StringUtilities; import org.teiid.designer.core.translators.TranslatorOverrideProperty; import org.teiid.designer.core.translators.TranslatorPropertyDefinition; import org.teiid.designer.vdb.Vdb.Event; import org.teiid.designer.vdb.manifest.PropertyElement; import org.teiid.designer.vdb.manifest.TranslatorElement; /** * A VDB translator override. * * @since 8.0 */ public class TranslatorOverride extends VdbUnit implements Comparable<TranslatorOverride>, PropertyChangeListener { private static final String PREFIX = I18nUtil.getPropertyPrefix(TranslatorOverride.class); /** * An empty array of translators. */ public static final TranslatorOverride[] NO_TRANSLATORS = new TranslatorOverride[0]; /** * @param proposedName the proposed translator name * @return an error message or <code>null</code> if name is valid */ public static String validateName( String proposedName ) { // must have a name if (StringUtilities.isEmpty(proposedName)) { return UTIL.getString(PREFIX + "emptyTranslatorName"); //$NON-NLS-1$ } // make sure only letters, digits, or dash for (char c : proposedName.toCharArray()) { if (!Character.isLetter(c) && !Character.isDigit(c) && (c != '-')) { return UTIL.getString(PREFIX + "invalidTranslatorName", proposedName); //$NON-NLS-1$ } } // first char must be letter if (!Character.isLetter(proposedName.charAt(0))) { return UTIL.getString(PREFIX + "translatorNameMustStartWithLetter"); //$NON-NLS-1$ } // valid name return null; } /** * @param proposedType the proposed translator type * @return an error message or <code>null</code> if type is valid */ public static String validateType( String proposedType ) { // must have a type if (StringUtilities.isEmpty(proposedType)) { return UTIL.getString(PREFIX + "emptyTranslatorType"); //$NON-NLS-1$ } // make sure only letters, digits, or dash for (char c : proposedType.toCharArray()) { if (!Character.isLetterOrDigit(c) && c != '-') { return UTIL.getString(PREFIX + "invalidTranslatorType", proposedType); //$NON-NLS-1$ } } // first char must be letter if (!Character.isLetter(proposedType.charAt(0))) { return UTIL.getString(PREFIX + "translatorTypeMustStartWithLetter"); //$NON-NLS-1$ } // valid type return null; } private final Map<String, TranslatorOverrideProperty> overrideProps = new HashMap<String, TranslatorOverrideProperty>(); private final String type; /** * @param name the name of the overridden translator (may not be <code>null</code>) * @param type the translator type being overridden (may not be <code>null</code>) * @param vdb the VDB this override is contained in * @param description the translator override description (may be <code>null</code> or empty) */ public TranslatorOverride( Vdb vdb, String name, String type, String description ) { assert (name != null); assert (type != null); this.type = type; setVdb(vdb); setName(name == null ? EMPTY_STRING : name); setDescription(description == null ? EMPTY_STRING : description); } /** * @param vdb * @param element */ public TranslatorOverride( Vdb vdb, TranslatorElement element ) { this(vdb, element.getName(), element.getType(), element.getDescription()); for (PropertyElement property : element.getProperties()) { TranslatorPropertyDefinition propDefn = new TranslatorPropertyDefinition(property.getName(), property.getValue()); TranslatorOverrideProperty prop = new TranslatorOverrideProperty(propDefn, property.getValue()); this.overrideProps.put(propDefn.getId(), prop); prop.addListener(this); } } /** * Adds the property and fires a VDB property changed event. * * @param newProperty the property being added (may not be <code>null</code>) */ public void addProperty( TranslatorOverrideProperty newProperty ) { addProperty(newProperty, true); } /** * @param newProperty the property being added (may not be <code>null</code>) * @param firePropertyEvent <code>true</code> if a VDB property changed event should be fired */ public void addProperty( TranslatorOverrideProperty newProperty, boolean firePropertyEvent ) { assert (newProperty != null); Object obj = this.overrideProps.put(newProperty.getDefinition().getId(), newProperty); newProperty.addListener(this); if (firePropertyEvent) { setModified(this, Event.TRANSLATOR_PROPERTY, obj, newProperty); } } /** * {@inheritDoc} * * @see java.lang.Comparable#compareTo(java.lang.Object) */ @Override public int compareTo( TranslatorOverride vdbTranslator ) { return getName().compareTo(vdbTranslator.getName()); } /** * {@inheritDoc} * * @see java.util.AbstractMap#equals(java.lang.Object) */ @Override public boolean equals( Object obj ) { if (this == obj) { return true; } if (obj == null) { return false; } if (!getClass().equals(obj.getClass())) { return false; } // only care if name is the same return getName().equals(((TranslatorOverride)obj).getName()); } /** * Obtains all the properties of the translator even those properties whose values have not been overridden. * * @return all translator properties (never <code>null</code>) */ public TranslatorOverrideProperty[] getOverrideProperties() { TranslatorOverrideProperty[] props = new TranslatorOverrideProperty[this.overrideProps.size()]; int i = 0; for (TranslatorOverrideProperty property : this.overrideProps.values()) { props[i++] = property; } return props; } /** * @return a list of all property names (never <code>null</code> but can be empty) */ public List<String> getPropertyNames() { return Arrays.asList(this.overrideProps.keySet().toArray(new String[this.overrideProps.size()])); } /** * @return the translator type being overridden (never <code>null</code>) */ public String getType() { return this.type; } /** * {@inheritDoc} * * @see java.util.AbstractMap#hashCode() */ @Override public int hashCode() { return getName().hashCode(); } /** * @param property the property being marked as a user-defined or custom property (may not be <code>null</code>) */ public void markAsUserDefined( TranslatorOverrideProperty property ) { property.getDefinition().markAsUserDefined(property.getOverriddenValue()); } /** * {@inheritDoc} * * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) */ @Override public void propertyChange( PropertyChangeEvent event ) { TranslatorOverrideProperty property = (TranslatorOverrideProperty)event.getSource(); setModified(this, Event.TRANSLATOR_PROPERTY, event.getOldValue(), property); } /** * Removes the property and fires a VDB property changed event * * @param propName the name of the property being removed (may not be <code>null</code> or empty) * @return <code>true</code> if the property was removed */ public boolean removeOverrideProperty( String propName ) { return removeOverrideProperty(propName, true); } /** * @param propName the name of the property being removed (may not be <code>null</code> or empty) * @param firePropertyEvent <code>true</code> if a VDB property changed event should be fired * @return <code>true</code> if the property was removed */ public boolean removeOverrideProperty( String propName, boolean firePropertyEvent ) { assert (propName != null); assert (this.overrideProps.containsKey(propName)); TranslatorOverrideProperty prop = this.overrideProps.remove(propName); prop.removeListener(this); if (prop.getDefinition().isUserDefined()) { setModified(this, Event.TRANSLATOR_PROPERTY, prop, null); } return false; } /** * Updates the overridden value and fires a VDB property changed event. * * @param propDefn the property definition whose overridden value is being changed (may not be <code>null</code>) * @param newValue the new value (may be <code>null</code> or empty) */ public void setOverrideValue( TranslatorPropertyDefinition propDefn, String newValue ) { setOverrideValue(propDefn, newValue, true); } /** * @param propDefn the property definition whose overridden value is being changed (may not be <code>null</code>) * @param newValue the new value (may be <code>null</code> or empty) * @param firePropertyEvent <code>true</code> if a VDB property changed event should be fired */ public void setOverrideValue( TranslatorPropertyDefinition propDefn, String newValue, boolean firePropertyEvent ) { assert (propDefn != null); assert (this.overrideProps.containsKey(propDefn.getId())); TranslatorOverrideProperty prop = this.overrideProps.get(propDefn.getId()); String oldValue = prop.getOverriddenValue(); // don't set if nothing has changed if (StringUtilities.equals(newValue, oldValue)) { return; } prop.setValue(newValue); if (firePropertyEvent) { setModified(this, Event.TRANSLATOR_PROPERTY, null, prop); } } /** * Updates the property definition and fires a VDB property changed event. * * @param propertyName the property whose definition is being updated (may not be <code>null</code> or empty) * @param newServerPropDefn the new definition (may not be <code>null</code>) */ public void updatePropertyDefinition( String propertyName, PropertyDefinition newServerPropDefn ) { updatePropertyDefinition(propertyName, newServerPropDefn, true); } /** * @param propertyName the property whose definition is being updated (may not be <code>null</code> or empty) * @param newServerPropDefn the new definition (may not be <code>null</code>) * @param firePropertyEvent <code>true</code> if a VDB property changed event should be fired */ public void updatePropertyDefinition( String propertyName, PropertyDefinition newServerPropDefn, boolean firePropertyEvent ) { assert (!StringUtilities.isEmpty(propertyName)); assert (newServerPropDefn != null); TranslatorOverrideProperty prop = this.overrideProps.get(propertyName); if (prop != null) { prop.setDefinition(newServerPropDefn); if (firePropertyEvent) { setModified(this, Event.TRANSLATOR_PROPERTY, null, prop); } } } @Override public TranslatorOverride clone() { TranslatorOverride clone = new TranslatorOverride(getVdb(), getName(), getType(), getDescription()); cloneVdbObject(clone); for (TranslatorOverrideProperty property : overrideProps.values()) { TranslatorPropertyDefinition definition = property.getDefinition(); TranslatorPropertyDefinition cloneDefn = new TranslatorPropertyDefinition(definition.getId(), definition.getDefaultValue()); TranslatorOverrideProperty cloneProp = new TranslatorOverrideProperty(cloneDefn, property.getOverriddenValue()); clone.addProperty(cloneProp, false); } return clone; } }