Added: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/comphelper/PropertySetAdapter.java URL: http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/comphelper/PropertySetAdapter.java?rev=1805579&view=auto ============================================================================== --- openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/comphelper/PropertySetAdapter.java (added) +++ openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/comphelper/PropertySetAdapter.java Sun Aug 20 19:16:28 2017 @@ -0,0 +1,411 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.star.sdbcx.comp.postgresql.comphelper; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import com.sun.star.beans.Property; +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.beans.PropertyChangeEvent; +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XFastPropertySet; +import com.sun.star.beans.XMultiPropertySet; +import com.sun.star.beans.XPropertiesChangeListener; +import com.sun.star.beans.XPropertyChangeListener; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.XPropertySetInfo; +import com.sun.star.beans.XVetoableChangeListener; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lib.uno.helper.InterfaceContainer; +import com.sun.star.lib.uno.helper.MultiTypeInterfaceContainer; +import com.sun.star.uno.Any; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Type; +import com.sun.star.uno.TypeClass; +import com.sun.star.uno.XInterface; + +public class PropertySetAdapter implements XPropertySet, XFastPropertySet, XMultiPropertySet { + private final Object lock; + private final Object eventSource; + // after registerListeners(), these are read-only: + private final Map<String,PropertyData> propertiesByName = new HashMap<String,PropertyData>(); + private final Map<Integer,PropertyData> propertiesByHandle = new HashMap<Integer,PropertyData>(); + private int nextHandle = 1; + // interface containers are locked internally: + protected final MultiTypeInterfaceContainer boundListeners = new MultiTypeInterfaceContainer(); + protected final MultiTypeInterfaceContainer vetoableListeners = new MultiTypeInterfaceContainer(); + protected final InterfaceContainer propertiesChangeListeners = new InterfaceContainer(); + private final PropertySetInfo propertySetInfo = new PropertySetInfo(); + + public static interface PropertyGetter { + Object getValue(); + } + + public static interface PropertySetter { + void setValue(Object value); + } + + private static class PropertyData { + Property property; + PropertyGetter getter; + PropertySetter setter; + + PropertyData(Property property, PropertyGetter getter, PropertySetter setter) { + this.property = property; + this.getter = getter; + this.setter = setter; + } + } + + private static final Comparator<Property> propertyNameComparator = new Comparator<Property>() { + @Override + public int compare(Property first, Property second) { + return first.Name.compareTo(second.Name); + } + }; + + private class PropertySetInfo implements XPropertySetInfo { + @Override + public Property[] getProperties() { + Property[] properties = new Property[propertiesByName.size()]; + int next = 0; + for (Map.Entry<String,PropertyData> entry : propertiesByName.entrySet()) { + properties[next++] = entry.getValue().property; + } + Arrays.sort(properties, propertyNameComparator); + return properties; + } + + @Override + public Property getPropertyByName(String propertyName) throws UnknownPropertyException { + PropertyData propertyData = getPropertyData(propertyName); + return propertyData.property; + } + + @Override + public boolean hasPropertyByName(String propertyName) { + return propertiesByName.containsKey(propertyName); + } + } + + /** + * Creates a new instance. + * @param lock the lock that will be held while calling the getters and setters + * @param eventSource the com.sun.star.lang.EventObject Source field, to use in events sent to listeners + */ + public PropertySetAdapter(Object lock, Object eventSource) { + this.lock = lock; + this.eventSource = eventSource; + } + + public void dispose() { + // Create an event with this as sender + EventObject event = new EventObject(eventSource); + + // inform all listeners to release this object + boundListeners.disposeAndClear(event); + vetoableListeners.disposeAndClear(event); + } + + public void registerProperty(String propertyName, int handle, Type type, short attributes, + PropertyGetter getter, PropertySetter setter) { + Property property = new Property(propertyName, handle, type, attributes); + PropertyData propertyData = new PropertyData(property, getter, setter); + propertiesByName.put(propertyName, propertyData); + propertiesByHandle.put(property.Handle, propertyData); + } + + public void registerProperty(String propertyName, Type type, short attributes, + PropertyGetter getter, PropertySetter setter) { + int handle; + // registerProperty() should only be called from one thread, but just in case: + synchronized (lock) { + handle = nextHandle++; + } + registerProperty(propertyName, handle, type, attributes, getter, setter); + } + + @Override + public void addPropertyChangeListener( + String propertyName, XPropertyChangeListener listener) throws UnknownPropertyException, WrappedTargetException { + PropertyData propertyData = getPropertyData(propertyName); + if ((propertyData.property.Attributes & PropertyAttribute.BOUND) != 0) { + boundListeners.addInterface(propertyName, listener); + } // else ignore silently + } + + @Override + public void addVetoableChangeListener( + String propertyName, XVetoableChangeListener listener) throws UnknownPropertyException, WrappedTargetException { + PropertyData propertyData = getPropertyData(propertyName); + if ((propertyData.property.Attributes & PropertyAttribute.CONSTRAINED) != 0) { + vetoableListeners.addInterface(propertyName, listener); + } // else ignore silently + } + + @Override + public void addPropertiesChangeListener(String[] propertyNames, XPropertiesChangeListener listener) { + propertiesChangeListeners.add(listener); + } + + @Override + public XPropertySetInfo getPropertySetInfo() { + return propertySetInfo; + } + + private PropertyData getPropertyData(String propertyName) throws UnknownPropertyException { + PropertyData propertyData = propertiesByName.get(propertyName); + if (propertyData == null) { + throw new UnknownPropertyException(propertyName); + } + return propertyData; + } + + private PropertyData getPropertyData(int handle) throws UnknownPropertyException { + PropertyData propertyData = propertiesByHandle.get(handle); + if (propertyData == null) { + throw new UnknownPropertyException(Integer.toString(handle)); + } + return propertyData; + } + + private Object getPropertyValue(PropertyData propertyData) { + Object ret; + synchronized (lock) { + ret = propertyData.getter.getValue(); + } + + // null must not be returned. Either a void any is returned or an any containing + // an interface type and a null reference. + if (ret == null) { + if (propertyData.property.Type.getTypeClass() == TypeClass.INTERFACE) { + ret = new Any(propertyData.property.Type, null); + } else { + ret = new Any(new Type(void.class), null); + } + } + return ret; + } + + @Override + public Object getPropertyValue(String propertyName) throws UnknownPropertyException, WrappedTargetException { + PropertyData propertyData = getPropertyData(propertyName); + return getPropertyValue(propertyData); + } + + @Override + public Object getFastPropertyValue(int handle) throws UnknownPropertyException, WrappedTargetException { + PropertyData propertyData = getPropertyData(handle); + return getPropertyValue(propertyData); + } + + @Override + public Object[] getPropertyValues(String[] propertyNames) { + Object[] values = new Object[propertyNames.length]; + for (int i = 0; i < propertyNames.length; i++) { + Object value = null; + try { + value = getPropertyValue(propertyNames[i]); + } catch (UnknownPropertyException unknownPropertyException) { + } catch (WrappedTargetException wrappedTargetException) { + } + values[i] = value; + } + return values; + } + + @Override + public void removePropertyChangeListener( + String propertyName, XPropertyChangeListener listener) throws UnknownPropertyException, WrappedTargetException { + // check existence: + getPropertyData(propertyName); + boundListeners.removeInterface(propertyName, listener); + } + + @Override + public synchronized void removeVetoableChangeListener( + String propertyName, XVetoableChangeListener listener) throws UnknownPropertyException, WrappedTargetException { + // check existence: + getPropertyData(propertyName); + vetoableListeners.removeInterface(propertyName, listener); + } + + @Override + public void removePropertiesChangeListener(XPropertiesChangeListener listener) { + propertiesChangeListeners.remove(listener); + } + + @Override + public void setPropertyValue(String propertyName, Object value) + throws UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException { + PropertyData propertyData = getPropertyData(propertyName); + setPropertyValue(propertyData, value); + } + + @Override + public void setFastPropertyValue(int handle, Object value) + throws UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException { + PropertyData propertyData = getPropertyData(handle); + setPropertyValue(propertyData, value); + } + + private void setPropertyValue(PropertyData propertyData, Object value) + throws UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException { + if ((propertyData.property.Attributes & PropertyAttribute.READONLY) != 0) { + throw new PropertyVetoException(); + } + // The value may be null only if MAYBEVOID attribute is set + boolean isVoid = false; + if (value instanceof Any) { + isVoid = ((Any) value).getObject() == null; + } else { + isVoid = value == null; + } + if (isVoid && (propertyData.property.Attributes & PropertyAttribute.MAYBEVOID) == 0) { + throw new IllegalArgumentException("The property must have a value; the MAYBEVOID attribute is not set!"); + } + + // Check if the argument is allowed + boolean isValueOk = false; + if (value instanceof Any) { + isValueOk = checkType(((Any) value).getObject()); + } else { + isValueOk = checkType(value); + } + if (!isValueOk) { + throw new IllegalArgumentException("No valid UNO type"); + } + + Object[] futureValue = new Object[] { AnyConverter.toObject(propertyData.property.Type, value) }; + Object[] currentValue = new Object[] { getPropertyValue(propertyData.property.Name) }; + Property[] properties = new Property[] { propertyData.property }; + + fire(properties, currentValue, futureValue, false); + synchronized (lock) { + propertyData.setter.setValue(futureValue[0]); + } + fire(properties, currentValue, futureValue, true); + } + + @Override + public void setPropertyValues(String[] propertyNames, Object[] values) throws PropertyVetoException, IllegalArgumentException, WrappedTargetException { + for (int i = 0; i < propertyNames.length; i++) { + try { + setPropertyValue(propertyNames[i], values[i]); + } catch (UnknownPropertyException e) { + continue; + } + } + } + + private boolean checkType(Object obj) { + if (obj == null + || obj instanceof Boolean + || obj instanceof Character + || obj instanceof Number + || obj instanceof String + || obj instanceof XInterface + || obj instanceof Type + || obj instanceof com.sun.star.uno.Enum + || obj.getClass().isArray()) + return true; + return false; + } + + @Override + public void firePropertiesChangeEvent(String[] propertyNames, XPropertiesChangeListener listener) { + PropertyChangeEvent[] events = new PropertyChangeEvent[propertyNames.length]; + int eventCount = 0; + for (int i = 0; i < propertyNames.length; i++) { + try { + PropertyData propertyData = getPropertyData(propertyNames[i]); + Object value = getPropertyValue(propertyNames[i]); + events[eventCount++] = new PropertyChangeEvent(eventSource, propertyNames[i], + false, propertyData.property.Handle, value, value); + } catch (UnknownPropertyException unknownPropertyException) { + } catch (WrappedTargetException wrappedTargetException) { + } + } + if (eventCount > 0) { + if (events.length != eventCount) { + PropertyChangeEvent[] tmp = new PropertyChangeEvent[eventCount]; + System.arraycopy(events, 0, tmp, 0, eventCount); + events = tmp; + } + listener.propertiesChange(events); + } + } + + private void fire(Property[] properties, Object[] oldValues, Object[] newValues, boolean hasChanged) throws PropertyVetoException { + PropertyChangeEvent[] events = new PropertyChangeEvent[properties.length]; + int eventCount = 0; + for (int i = 0; i < properties.length; i++) { + if ((!hasChanged && (properties[i].Attributes & PropertyAttribute.CONSTRAINED) != 0) || + (hasChanged && (properties[i].Attributes & PropertyAttribute.BOUND) != 0)) { + events[eventCount++] = new PropertyChangeEvent( + eventSource, properties[i].Name, false, properties[i].Handle, oldValues[i], newValues[i]); + } + } + for (int i = 0; i < eventCount; i++) { + fireListeners(hasChanged, events[i].PropertyName, events[i]); + fireListeners(hasChanged, "", events[i]); + } + if (hasChanged && eventCount > 0) { + if (eventCount != events.length) { + PropertyChangeEvent[] tmp = new PropertyChangeEvent[eventCount]; + System.arraycopy(events, 0, tmp, 0, eventCount); + events = tmp; + } + for (Iterator<?> it = propertiesChangeListeners.iterator(); it.hasNext();) { + XPropertiesChangeListener listener = (XPropertiesChangeListener) it.next(); + listener.propertiesChange(events); + } + } + } + + private void fireListeners(boolean hasChanged, String key, PropertyChangeEvent event) throws PropertyVetoException { + InterfaceContainer listeners; + if (hasChanged) { + listeners = boundListeners.getContainer(key); + } else { + listeners = vetoableListeners.getContainer(key); + } + if (listeners != null) { + Iterator<?> it = listeners.iterator(); + while (it.hasNext()) { + Object listener = it.next(); + if (hasChanged) { + ((XPropertyChangeListener)listener).propertyChange(event); + } else { + ((XVetoableChangeListener)listener).vetoableChange(event); + } + } + } + } +}
Propchange: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/comphelper/PropertySetAdapter.java ------------------------------------------------------------------------------ svn:eol-style = native Added: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/ISQLStatementHelper.java URL: http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/ISQLStatementHelper.java?rev=1805579&view=auto ============================================================================== --- openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/ISQLStatementHelper.java (added) +++ openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/ISQLStatementHelper.java Sun Aug 20 19:16:28 2017 @@ -0,0 +1,28 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.star.sdbcx.comp.postgresql.sdbcx; + +import com.sun.star.beans.XPropertySet; + +public interface ISQLStatementHelper { + void addComment(XPropertySet propertySet, StringBuilder sql); +} Propchange: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/ISQLStatementHelper.java ------------------------------------------------------------------------------ svn:eol-style = native Added: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OCatalog.java URL: http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OCatalog.java?rev=1805579&view=auto ============================================================================== --- openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OCatalog.java (added) +++ openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OCatalog.java Sun Aug 20 19:16:28 2017 @@ -0,0 +1,169 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.star.sdbcx.comp.postgresql.sdbcx; + +import com.sun.star.container.XNameAccess; +import com.sun.star.lang.DisposedException; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lib.uno.helper.ComponentBase; +import com.sun.star.sdbc.SQLException; +import com.sun.star.sdbc.XDatabaseMetaData; +import com.sun.star.sdbc.XRow; +import com.sun.star.sdbcx.XGroupsSupplier; +import com.sun.star.sdbcx.XTablesSupplier; +import com.sun.star.sdbcx.XUsersSupplier; +import com.sun.star.sdbcx.XViewsSupplier; +import com.sun.star.sdbcx.comp.postgresql.util.ComposeRule; +import com.sun.star.sdbcx.comp.postgresql.util.DbTools; + +public abstract class OCatalog extends ComponentBase + implements XTablesSupplier, XViewsSupplier, XUsersSupplier, XGroupsSupplier, XServiceInfo { + + private static final String[] services = { + "com.sun.star.sdbcx.DatabaseDefinition" + }; + + protected final Object lock = new Object(); + // Deleted on destruction, weakly held by caller: + protected OContainer tables; + protected OContainer views; + protected OContainer groups; + protected OContainer users; + protected XDatabaseMetaData metadata; + + public OCatalog(XDatabaseMetaData metadata) { + this.metadata = metadata; + } + + private void checkDisposed() throws DisposedException { + if (bInDispose || bDisposed) { + throw new DisposedException(); + } + } + + @Override + protected void postDisposing() { + synchronized (lock) { + if (tables != null) { + tables.dispose(); + } + if (views != null) { + views.dispose(); + } + if (groups != null) { + groups.dispose(); + } + if (users != null) { + users.dispose(); + } + } + } + + // XServiceInfo + + @Override + public String getImplementationName() { + return "com.sun.star.comp.connectivity.OCatalog"; + } + + @Override + public String[] getSupportedServiceNames() { + return services.clone(); + } + + @Override + public boolean supportsService(String serviceName) { + for (String service : getSupportedServiceNames()) { + if (service.equals(serviceName)) { + return true; + } + } + return false; + } + + // X(Tables/Views/Groups/Users)Supplier + + @Override + public XNameAccess getTables() { + checkDisposed(); + synchronized (lock) { + if (tables == null) { + tables = refreshTables(); + } + return tables; + } + } + + @Override + public XNameAccess getViews() { + checkDisposed(); + synchronized (lock) { + if (views == null) { + views = refreshViews(); + } + return views; + } + } + + @Override + public XNameAccess getGroups() { + checkDisposed(); + synchronized (lock) { + if (groups == null) { + groups = refreshGroups(); + } + return groups; + } + } + + @Override + public XNameAccess getUsers() { + checkDisposed(); + synchronized (lock) { + if (users == null) { + users = refreshUsers(); + } + return users; + } + } + + protected String buildName(XRow row) throws SQLException { + String catalog = row.getString(1); + if (row.wasNull()) { + catalog = ""; + } + String schema = row.getString(2); + if (row.wasNull()) { + schema = null; + } + String table = row.getString(3); + if (row.wasNull()) { + table = ""; + } + return DbTools.composeTableName(metadata, catalog, schema, table, false, ComposeRule.InDataManipulation); + } + + public abstract OContainer refreshTables(); + public abstract OContainer refreshViews(); + public abstract OContainer refreshGroups(); + public abstract OContainer refreshUsers(); +} Propchange: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OCatalog.java ------------------------------------------------------------------------------ svn:eol-style = native Added: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OColumn.java URL: http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OColumn.java?rev=1805579&view=auto ============================================================================== --- openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OColumn.java (added) +++ openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OColumn.java Sun Aug 20 19:16:28 2017 @@ -0,0 +1,279 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.star.sdbcx.comp.postgresql.sdbcx; + +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XNamed; +import com.sun.star.lang.DisposedException; +import com.sun.star.sdbc.ColumnValue; +import com.sun.star.sdbcx.XDataDescriptorFactory; +import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper; +import com.sun.star.sdbcx.comp.postgresql.comphelper.PropertySetAdapter.PropertyGetter; +import com.sun.star.sdbcx.comp.postgresql.comphelper.PropertySetAdapter.PropertySetter; +import com.sun.star.sdbcx.comp.postgresql.sdbcx.descriptors.SdbcxColumnDescriptor; +import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds; +import com.sun.star.uno.Type; + +public class OColumn extends ODescriptor implements XNamed, XDataDescriptorFactory { + private String typeName; + private String description; + private String defaultValue; + private int isNullable; + private int precision; + private int scale; + private int type; + private boolean isAutoIncrement; + private boolean isRowVersion; + private boolean isCurrency; + + protected OColumn(final Object lock, final boolean isCaseSensitive) { + super(lock, "", isCaseSensitive); + this.isNullable = ColumnValue.NULLABLE; + this.precision = 0; + this.scale = 0; + this.type = 0; + this.isAutoIncrement = false; + this.isRowVersion = false; + this.isCurrency = false; + registerProperties(); + } + + public static OColumn create(final boolean isCaseSensitive) { + final Object lock = new Object(); + return new OColumn(lock, isCaseSensitive); + } + + protected OColumn( + final Object lock, + final String name, + final String typeName, + final String defaultValue, + final String description, + final int isNullable, + final int precision, + final int scale, + final int type, + final boolean isAutoIncrement, + final boolean isRowVersion, + final boolean isCurrency, + final boolean isCaseSensitive) { + super(lock, name, isCaseSensitive); + this.typeName = typeName; + this.description = description; + this.defaultValue = defaultValue; + this.isNullable = isNullable; + this.precision = precision; + this.scale = scale; + this.type = type; + this.isAutoIncrement = isAutoIncrement; + this.isRowVersion = isRowVersion; + this.isCurrency = isCurrency; + registerProperties(); + } + + public static OColumn create( + final String name, + final String typeName, + final String defaultValue, + final String description, + final int isNullable, + final int precision, + final int scale, + final int type, + final boolean isAutoIncrement, + final boolean isRowVersion, + final boolean isCurrency, + final boolean isCaseSensitive) { + final Object lock = new Object(); + return new OColumn(lock, name, typeName, defaultValue, description, + isNullable, precision, scale, type, isAutoIncrement, isRowVersion, + isCurrency, isCaseSensitive); + } + + private void registerProperties() { + registerProperty(PropertyIds.TYPENAME.name, PropertyIds.TYPENAME.id, Type.STRING, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return typeName; + + } + }, + new PropertySetter() { + @Override + public void setValue(Object value) { + typeName = (String) value; + } + }); + registerProperty(PropertyIds.DESCRIPTION.name, PropertyIds.DESCRIPTION.id, Type.STRING, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return description; + + } + }, + new PropertySetter() { + @Override + public void setValue(Object value) { + description = (String) value; + } + }); + registerProperty(PropertyIds.DEFAULTVALUE.name, PropertyIds.DEFAULTVALUE.id, Type.STRING, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return defaultValue; + + } + }, + new PropertySetter() { + @Override + public void setValue(Object value) { + defaultValue = (String) value; + } + }); + registerProperty(PropertyIds.PRECISION.name, PropertyIds.PRECISION.id, Type.LONG, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return precision; + + } + }, + new PropertySetter() { + @Override + public void setValue(Object value) { + precision = (Integer) value; + } + }); + registerProperty(PropertyIds.TYPE.name, PropertyIds.TYPE.id, Type.LONG, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return type; + + } + }, + new PropertySetter() { + @Override + public void setValue(Object value) { + type = (Integer) value; + } + }); + registerProperty(PropertyIds.SCALE.name, PropertyIds.SCALE.id, Type.LONG, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return scale; + + } + }, + new PropertySetter() { + @Override + public void setValue(Object value) { + scale = (Integer) value; + } + }); + registerProperty(PropertyIds.ISNULLABLE.name, PropertyIds.ISNULLABLE.id, Type.LONG, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return isNullable; + + } + }, + new PropertySetter() { + @Override + public void setValue(Object value) { + isNullable = (Integer) value; + } + }); + registerProperty(PropertyIds.ISAUTOINCREMENT.name, PropertyIds.ISAUTOINCREMENT.id, Type.BOOLEAN, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return isAutoIncrement; + + } + }, + new PropertySetter() { + @Override + public void setValue(Object value) { + isAutoIncrement = (Boolean) value; + } + }); + registerProperty(PropertyIds.ISROWVERSION.name, PropertyIds.ISROWVERSION.id, Type.BOOLEAN, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return isRowVersion; + + } + }, + new PropertySetter() { + @Override + public void setValue(Object value) { + isRowVersion = (Boolean) value; + } + }); + registerProperty(PropertyIds.ISCURRENCY.name, PropertyIds.ISCURRENCY.id, Type.BOOLEAN, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return isCurrency; + + } + }, + new PropertySetter() { + @Override + public void setValue(Object value) { + isCurrency = (Boolean) value; + } + }); + } + + // XComponent + + @Override + protected void postDisposing() { + super.postDisposing(); + } + + private void checkDisposed() { + if (bDisposed) { + throw new DisposedException(); + } + } + + // XDataDescriptorFactory + + @Override + public XPropertySet createDataDescriptor() { + SdbcxColumnDescriptor descriptor = SdbcxColumnDescriptor.create(isCaseSensitive()); + synchronized (lock) { + CompHelper.copyProperties(this, descriptor); + } + return descriptor; + } +} Propchange: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OColumn.java ------------------------------------------------------------------------------ svn:eol-style = native Added: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OColumnContainer.java URL: http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OColumnContainer.java?rev=1805579&view=auto ============================================================================== --- openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OColumnContainer.java (added) +++ openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OColumnContainer.java Sun Aug 20 19:16:28 2017 @@ -0,0 +1,123 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.star.sdbcx.comp.postgresql.sdbcx; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XNameAccess; +import com.sun.star.sdbc.ColumnValue; +import com.sun.star.sdbc.DataType; +import com.sun.star.sdbc.SQLException; +import com.sun.star.sdbc.XDatabaseMetaData; +import com.sun.star.sdbcx.comp.postgresql.sdbcx.SqlTableHelper.ColumnDescription; +import com.sun.star.sdbcx.comp.postgresql.sdbcx.descriptors.SdbcxColumnDescriptor; +import com.sun.star.sdbcx.comp.postgresql.util.DbTools; +import com.sun.star.uno.UnoRuntime; + +public class OColumnContainer extends OContainer { + private OTable table; + private XDatabaseMetaData metadata; + private Map<String,ColumnDescription> columnDescriptions = new HashMap<>(); + private Map<String,ExtraColumnInfo> extraColumnInfo = new HashMap<>(); + + /// The XDatabaseMetaData.getColumns() data stored in columnDescriptions doesn't provide everything we need, so this class stores the rest. + public static class ExtraColumnInfo { + public boolean isAutoIncrement; + public boolean isCurrency; + public int dataType; + } + + public OColumnContainer(Object lock, boolean isCaseSensitive, List<ColumnDescription> columnDescriptions, OTable table, XDatabaseMetaData metadata) { + super(lock, isCaseSensitive, toColumnNames(columnDescriptions)); + this.table = table; + this.metadata = metadata; + for (ColumnDescription columnDescription : columnDescriptions) { + this.columnDescriptions.put(columnDescription.columnName, columnDescription); + } + } + + private static List<String> toColumnNames(List<ColumnDescription> columns) { + List<String> columnNames = new ArrayList<>(columns.size()); + for (ColumnDescription columnDescription : columns) { + columnNames.add(columnDescription.columnName); + } + return columnNames; + } + + @Override + public XPropertySet createObject(String name) throws SQLException { + boolean queryInfo = true; + boolean isAutoIncrement = false; + boolean isCurrency = false; + int dataType = DataType.OTHER; + ExtraColumnInfo columnInfo = extraColumnInfo.get(name); + if (columnInfo == null) { + String composedName = DbTools.composeTableNameForSelect(metadata.getConnection(), table); + extraColumnInfo = DbTools.collectColumnInformation(metadata.getConnection(), composedName, "*"); + columnInfo = extraColumnInfo.get(name); + } + if (columnInfo != null) { + queryInfo = false; + isAutoIncrement = columnInfo.isAutoIncrement; + isCurrency = columnInfo.isCurrency; + dataType = columnInfo.dataType; + } + ColumnDescription columnDescription = columnDescriptions.get(name); + if (columnDescription != null) { + XNameAccess primaryKeyColumns = DbTools.getPrimaryKeyColumns(UnoRuntime.queryInterface(XPropertySet.class, table)); + int nullable = columnDescription.nullable; + if (nullable != ColumnValue.NO_NULLS && primaryKeyColumns != null && primaryKeyColumns.hasByName(name)) { + nullable = ColumnValue.NO_NULLS; + } + return OColumn.create(name, columnDescription.typeName, columnDescription.defaultValue, columnDescription.remarks, + nullable, columnDescription.columnSize, columnDescription.decimalDigits, columnDescription.type, + isAutoIncrement, false, isCurrency, isCaseSensitive()); + } else { + // FIXME: do something like the C++ implementation does? + throw new SQLException(); + } + } + + @Override + public XPropertySet createDescriptor() { + return SdbcxColumnDescriptor.create(isCaseSensitive()); + } + + @Override + public void impl_refresh() { + extraColumnInfo.clear(); + table.refreshColumns(); + } + + @Override + public XPropertySet appendObject(String _rForName, XPropertySet descriptor) throws SQLException { + return null; + } + + @Override + public void dropObject(int index, String name) throws SQLException { + } +} Propchange: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OColumnContainer.java ------------------------------------------------------------------------------ svn:eol-style = native Added: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OContainer.java URL: http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OContainer.java?rev=1805579&view=auto ============================================================================== --- openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OContainer.java (added) +++ openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OContainer.java Sun Aug 20 19:16:28 2017 @@ -0,0 +1,461 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.star.sdbcx.comp.postgresql.sdbcx; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.ContainerEvent; +import com.sun.star.container.ElementExistException; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.container.XContainer; +import com.sun.star.container.XContainerListener; +import com.sun.star.container.XEnumeration; +import com.sun.star.container.XEnumerationAccess; +import com.sun.star.container.XIndexAccess; +import com.sun.star.container.XNameAccess; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.IndexOutOfBoundsException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lib.uno.helper.InterfaceContainer; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.sdbc.SQLException; +import com.sun.star.sdbc.XColumnLocate; +import com.sun.star.sdbcx.XAppend; +import com.sun.star.sdbcx.XDataDescriptorFactory; +import com.sun.star.sdbcx.XDrop; +import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper; +import com.sun.star.sdbcx.comp.postgresql.comphelper.OEnumerationByIndex; +import com.sun.star.sdbcx.comp.postgresql.util.StandardSQLState; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Type; +import com.sun.star.util.XRefreshListener; +import com.sun.star.util.XRefreshable; + +public abstract class OContainer extends WeakBase implements + XNameAccess, XIndexAccess, XEnumerationAccess, + XContainer, XColumnLocate, XRefreshable, XDataDescriptorFactory, + XAppend, XDrop, XServiceInfo { + + private static String[] services = new String[] { + "com.sun.star.sdbcx.Container" + }; + + protected final Object lock; + private final boolean isCaseSensitive; + private TreeMap<String,HashMap<Long,XPropertySet>> entriesByNameAndId; + private ArrayList<PropertyInfo> entriesByIndex; + private long nextId; + private InterfaceContainer containerListeners = new InterfaceContainer(); + private InterfaceContainer refreshListeners = new InterfaceContainer(); + + /// Names aren't necessarily unique, we have to de-duplicate by id. + private static class PropertyInfo { + String name; + long id; + + PropertyInfo(String name, long id) { + this.name = name; + this.id = id; + } + } + + private Comparator<String> caseSensitiveComparator = new Comparator<String>() { + @Override + public int compare(String x, String y) { + if (isCaseSensitive) { + return x.compareTo(y); + } else { + return x.compareToIgnoreCase(y); + } + } + }; + + public OContainer(Object lock, boolean isCaseSensitive, List<String> names) { + this.lock = lock; + this.isCaseSensitive = isCaseSensitive; + this.entriesByNameAndId = new TreeMap<String,HashMap<Long,XPropertySet>>(caseSensitiveComparator); + this.entriesByIndex = new ArrayList<>(names.size()); + for (String name : names) { + HashMap<Long,XPropertySet> entriesById = entriesByNameAndId.get(name); + if (entriesById == null) { + entriesById = new HashMap<>(); + entriesByNameAndId.put(name, entriesById); + } + entriesById.put(nextId, null); + + entriesByIndex.add(new PropertyInfo(name, nextId)); + ++nextId; + } + } + + // Would be from XComponent ;) + + public void dispose() { + EventObject event = new EventObject(this); + containerListeners.disposeAndClear(event); + refreshListeners.disposeAndClear(event); + + synchronized (lock) { + for (Map<Long,XPropertySet> entriesById : entriesByNameAndId.values()) { + for (XPropertySet propertySet : entriesById.values()) { + CompHelper.disposeComponent(propertySet); + } + } + entriesByNameAndId.clear(); + entriesByIndex.clear(); + } + } + + // XServiceInfo + + public String getImplementationName() { + return "com.sun.star.sdbcx.VContainer"; + } + + @Override + public String[] getSupportedServiceNames() { + return services.clone(); + } + + @Override + public boolean supportsService(String serviceName) { + for (String service : services) { + if (service.equals(serviceName)) { + return true; + } + } + return false; + } + + // XIndexAccess + + @Override + public Object getByIndex(int index) throws IndexOutOfBoundsException, WrappedTargetException { + synchronized (lock) { + if (index < 0 || index >= entriesByIndex.size()) { + throw new IndexOutOfBoundsException(Integer.toString(index), this); + } + return getObject(index); + } + } + + @Override + public int getCount() { + synchronized (lock) { + return entriesByIndex.size(); + } + } + + // XNameAccess + + @Override + public boolean hasByName(String name) { + synchronized (lock) { + return entriesByNameAndId.containsKey(name); + } + } + + @Override + public Object getByName(String name) throws NoSuchElementException, WrappedTargetException { + synchronized (lock) { + if (!entriesByNameAndId.containsKey(name)) { + String error = SharedResources.getInstance().getResourceStringWithSubstitution( + Resources.STR_NO_ELEMENT_NAME, "$name$", name); + throw new NoSuchElementException(error, this); + } + return getObject(indexOf(name)); + } + } + + @Override + public String[] getElementNames() { + synchronized (lock) { + String[] names = new String[entriesByIndex.size()]; + int next = 0; + for (PropertyInfo propertyInfo : entriesByIndex) { + names[next++] = propertyInfo.name; + } + return names; + } + } + + // XRefreshable + + @Override + public void refresh() { + Iterator iterator; + synchronized (lock) { + for (Map<Long,XPropertySet> entriesById : entriesByNameAndId.values()) { + for (XPropertySet propertySet : entriesById.values()) { + CompHelper.disposeComponent(propertySet); + } + } + entriesByNameAndId.clear(); + entriesByIndex.clear(); + + impl_refresh(); + + iterator = refreshListeners.iterator(); + } + EventObject event = new EventObject(this); + while (iterator.hasNext()) { + XRefreshListener listener = (XRefreshListener) iterator.next(); + listener.refreshed(event); + } + } + + // XDataDescriptorFactory + + @Override + public XPropertySet createDataDescriptor() { + synchronized (lock) { + return createDescriptor(); + } + } + + protected String getNameForObject(XPropertySet object) { + try { + Object ret = object.getPropertyValue("Name"); + return AnyConverter.toString(ret); + } catch (WrappedTargetException wrappedTargetException) { + } catch (UnknownPropertyException unknownPropertyException) { + } catch (IllegalArgumentException illegalArgumentException) { + } + return null; + } + + // XAppend + + @Override + public void appendByDescriptor(XPropertySet descriptor) throws SQLException, ElementExistException { + Iterator iterator; + ContainerEvent event; + synchronized (lock) { + String name = getNameForObject(descriptor); + + if (entriesByNameAndId.containsKey(name)) { + throw new ElementExistException(name, this); + } + + XPropertySet newlyCreated = appendObject(name, descriptor); + if (newlyCreated == null) { + throw new RuntimeException(); + } + + name = getNameForObject(newlyCreated); + HashMap<Long,XPropertySet> entriesById = entriesByNameAndId.get(name); + if (entriesById == null) { // this may happen when the derived class included it itself + entriesById = new HashMap<>(); + entriesById.put(nextId, newlyCreated); + entriesByNameAndId.put(name, entriesById); + entriesByIndex.add(new PropertyInfo(name, nextId)); + nextId++; + } + + // notify our container listeners + event = new ContainerEvent(this, name, newlyCreated, null); + iterator = containerListeners.iterator(); + } + while (iterator.hasNext()) { + XContainerListener listener = (XContainerListener) iterator.next(); + listener.elementInserted(event); + } + + } + + // XDrop + + @Override + public void dropByName(String name) throws SQLException, NoSuchElementException { + synchronized (lock) { + if (!entriesByNameAndId.containsKey(name)) { + throw new NoSuchElementException(name, this); + } + dropImpl(indexOf(name)); + } + } + + @Override + public void dropByIndex(int index) throws SQLException, IndexOutOfBoundsException { + synchronized (lock) { + if (index < 0 || index >= entriesByIndex.size()) { + throw new IndexOutOfBoundsException(Integer.toString(index), this); + } + dropImpl(index); + } + } + + + private void dropImpl(int index) throws SQLException { + dropImpl(index, true); + } + + private void dropImpl(int index, boolean reallyDrop) throws SQLException { + PropertyInfo propertyInfo = entriesByIndex.get(index); + if (reallyDrop) { + dropObject(index, propertyInfo.name); + } + HashMap<Long,XPropertySet> entriesById = entriesByNameAndId.get(propertyInfo.name); + XPropertySet propertySet = entriesById.remove(propertyInfo.id); + if (entriesById.isEmpty()) { + entriesByNameAndId.remove(propertyInfo.name); + } + CompHelper.disposeComponent(propertySet); + entriesByIndex.remove(index); + + ContainerEvent event = new ContainerEvent(this, propertyInfo.name, null, null); + for (Iterator iterator = containerListeners.iterator(); iterator.hasNext(); ) { + XContainerListener listener = (XContainerListener) iterator.next(); + listener.elementRemoved(event); + } + } + + // XColumnLocate + + @Override + public int findColumn(String name) throws SQLException { + if (!entriesByNameAndId.containsKey(name)) { + String error = SharedResources.getInstance().getResourceStringWithSubstitution( + Resources.STR_UNKNOWN_COLUMN_NAME, "$columnname$", name); + throw new SQLException(error, this, StandardSQLState.SQL_COLUMN_NOT_FOUND.text(), 0, null); + } + return indexOf(name) + 1; // because columns start at one + } + + + // XEnumerationAccess + + @Override + public XEnumeration createEnumeration() { + return new OEnumerationByIndex(this); + } + + @Override + public void addContainerListener(XContainerListener listener) { + containerListeners.add(listener); + } + + @Override + public void removeContainerListener(XContainerListener listener) { + containerListeners.remove(listener); + } + + @Override + public Type getElementType() { + return new Type(XPropertySet.class); + } + + @Override + public boolean hasElements() { + synchronized (lock) { + return !entriesByNameAndId.isEmpty(); + } + } + + @Override + public void addRefreshListener(XRefreshListener listener) { + synchronized (lock) { + refreshListeners.add(listener); + } + } + + @Override + public void removeRefreshListener(XRefreshListener listener) { + synchronized (lock) { + refreshListeners.remove(listener); + } + } + + protected int indexOf(String name) { + for (int i = 0; i < entriesByIndex.size(); i++) { + if (entriesByIndex.get(i).name.equals(name)) { + return i; + } + } + return -1; + } + + protected Object getObject(int index) throws WrappedTargetException { + PropertyInfo propertyInfo = entriesByIndex.get(index); + HashMap<Long,XPropertySet> entriesById = entriesByNameAndId.get(propertyInfo.name); + XPropertySet propertySet = entriesById.get(propertyInfo.id); + if (propertySet == null) { + try { + propertySet = createObject(propertyInfo.name); + } catch (SQLException e) { + try { + dropImpl(index, false); + } catch (Exception ignored) { + } + throw new WrappedTargetException(e.getMessage(), this, e); + } + entriesById.put(propertyInfo.id, propertySet); + } + return propertySet; + } + + protected XPropertySet cloneDescriptor(XPropertySet descriptor) { + XPropertySet newDescriptor = createDescriptor(); + CompHelper.copyProperties(descriptor, newDescriptor); + return newDescriptor; + } + + protected boolean isCaseSensitive() { + return isCaseSensitive; + } + + // will be called when a object was requested by one of the accessing methods like getByIndex + public abstract XPropertySet createObject(final String name) throws SQLException; + + public abstract void dropObject(int index, String name) throws SQLException; + + // the implementing class should refresh their elements + public abstract void impl_refresh(); + + // will be called when a new object should be generated by a call of createDataDescriptor + // the returned object is empty will be filled outside and added to the collection + public abstract XPropertySet createDescriptor(); + + /** appends an object described by a descriptor, under a given name + @param _rForName + is the name under which the object should be appended. Guaranteed to not be empty. + This is passed for convenience only, since it's the result of a call of + getNameForObject for the given descriptor + @param descriptor + describes the object to append + @return + the new object which is to be inserted into the collection. This might be the result + of a call of <code>createObject( _rForName )</code>, or a clone of the descriptor. + */ + public abstract XPropertySet appendObject(String _rForName, XPropertySet descriptor) throws SQLException; + +} Propchange: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OContainer.java ------------------------------------------------------------------------------ svn:eol-style = native Added: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/ODescriptor.java URL: http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/ODescriptor.java?rev=1805579&view=auto ============================================================================== --- openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/ODescriptor.java (added) +++ openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/ODescriptor.java Sun Aug 20 19:16:28 2017 @@ -0,0 +1,76 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.star.sdbcx.comp.postgresql.sdbcx; + +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.sdbcx.comp.postgresql.comphelper.PropertySet; +import com.sun.star.sdbcx.comp.postgresql.comphelper.PropertySetAdapter.PropertyGetter; +import com.sun.star.sdbcx.comp.postgresql.comphelper.PropertySetAdapter.PropertySetter; +import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds; +import com.sun.star.uno.Type; + +public class ODescriptor extends PropertySet { + private String name; + private final boolean isCaseSensitive; + protected final Object lock; + + public ODescriptor(Object lock, String name, boolean isCaseSensitive, boolean isReadOnly) { + super(lock); + this.lock = lock; + this.name = name; + this.isCaseSensitive = isCaseSensitive; + registerProperties(isReadOnly); + } + + public ODescriptor(Object lock, String name, boolean isCaseSensitive) { + this(lock, name, isCaseSensitive, true); + } + + private void registerProperties(boolean isReadOnly) { + registerProperty(PropertyIds.NAME.name, PropertyIds.NAME.id, Type.STRING, isReadOnly ? PropertyAttribute.READONLY : 0, + new PropertyGetter() { + @Override + public Object getValue() { + return name; + + } + }, + isReadOnly ? null : new PropertySetter() { + @Override + public void setValue(Object value) { + name = (String) value; + } + }); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isCaseSensitive() { + return isCaseSensitive; + } +} Propchange: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/ODescriptor.java ------------------------------------------------------------------------------ svn:eol-style = native Added: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndex.java URL: http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndex.java?rev=1805579&view=auto ============================================================================== --- openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndex.java (added) +++ openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndex.java Sun Aug 20 19:16:28 2017 @@ -0,0 +1,121 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.star.sdbcx.comp.postgresql.sdbcx; + +import java.util.List; + +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XNameAccess; +import com.sun.star.sdbc.SQLException; +import com.sun.star.sdbcx.XColumnsSupplier; +import com.sun.star.sdbcx.XDataDescriptorFactory; +import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper; +import com.sun.star.sdbcx.comp.postgresql.comphelper.PropertySetAdapter.PropertyGetter; +import com.sun.star.sdbcx.comp.postgresql.sdbcx.descriptors.SdbcxIndexDescriptor; +import com.sun.star.sdbcx.comp.postgresql.util.DbTools; +import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds; +import com.sun.star.uno.Type; + +public class OIndex extends ODescriptor implements XColumnsSupplier, XDataDescriptorFactory { + protected String catalogName; + protected boolean isUnique; + protected boolean isPrimaryKeyIndex; + protected boolean isClustered; + private OTable table; + private OContainer columns; + + protected OIndex(Object lock, String name, boolean isCaseSensitive, String catalogName, + boolean isUnique, boolean isPrimaryKeyIndex, boolean isClustered, List<String> columnNames, OTable table) { + super(lock, name, isCaseSensitive); + this.catalogName = catalogName; + this.isUnique = isUnique; + this.isPrimaryKeyIndex = isPrimaryKeyIndex; + this.isClustered = isClustered; + this.table = table; + columns = new OIndexColumnContainer(lock, this, columnNames); + registerProperties(); + } + + public static OIndex create(String name, boolean isCaseSensitive, String catalogName, + boolean isUnique, boolean isPrimaryKeyIndex, boolean isClustered, List<String> columnNames, OTable table) { + final Object lock = new Object(); + return new OIndex(lock, name, isCaseSensitive, catalogName, isUnique, isPrimaryKeyIndex, isClustered, columnNames, table); + } + + private void registerProperties() { + registerProperty(PropertyIds.CATALOG.name, PropertyIds.CATALOG.id, Type.STRING, (short)PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return catalogName; + } + }, null); + registerProperty(PropertyIds.ISPRIMARYKEYINDEX.name, PropertyIds.ISPRIMARYKEYINDEX.id, Type.BOOLEAN, (short)PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return isPrimaryKeyIndex; + } + }, null); + registerProperty(PropertyIds.ISCLUSTERED.name, PropertyIds.ISCLUSTERED.id, Type.BOOLEAN, (short)PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return isClustered; + } + }, null); + registerProperty(PropertyIds.ISUNIQUE.name, PropertyIds.ISUNIQUE.id, Type.BOOLEAN, (short)PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return isUnique; + } + }, null); + } + + @Override + public XPropertySet createDataDescriptor() { + SdbcxIndexDescriptor descriptor = SdbcxIndexDescriptor.create(isCaseSensitive()); + CompHelper.copyProperties(this, descriptor); + try { + DbTools.cloneDescriptorColumns(this, descriptor); + } catch (SQLException sqlException) { + } + return descriptor; + } + + @Override + public XNameAccess getColumns() { + return columns; + } + + public OTable getTable() { + return table; + } + + @Override + public String toString() { + return "OIndex [catalogName=" + catalogName + ", isUnique=" + isUnique + ", isPrimaryKeyIndex=" + isPrimaryKeyIndex + ", isClustered=" + isClustered + + ", name=" + getName() + "]"; + } +} Propchange: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndex.java ------------------------------------------------------------------------------ svn:eol-style = native Added: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexColumn.java URL: http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexColumn.java?rev=1805579&view=auto ============================================================================== --- openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexColumn.java (added) +++ openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexColumn.java Sun Aug 20 19:16:28 2017 @@ -0,0 +1,96 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.star.sdbcx.comp.postgresql.sdbcx; + +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.beans.XPropertySet; +import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper; +import com.sun.star.sdbcx.comp.postgresql.comphelper.PropertySetAdapter.PropertyGetter; +import com.sun.star.sdbcx.comp.postgresql.sdbcx.descriptors.SdbcxIndexColumnDescriptor; +import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds; +import com.sun.star.uno.Type; + +public class OIndexColumn extends OColumn { + protected boolean isAscending; + + protected OIndexColumn( + final Object lock, + final boolean isAscending, + final String name, + final String typeName, + final String defaultValue, + final String description, + final int isNullable, + final int precision, + final int scale, + final int type, + final boolean isAutoIncrement, + final boolean isRowVersion, + final boolean isCurrency, + final boolean isCaseSensitive) { + super(lock, name, typeName, defaultValue, description, isNullable, + precision, scale, type, isAutoIncrement, isRowVersion, isCurrency, isCaseSensitive); + this.isAscending = isAscending; + registerProperties(); + } + + public static OIndexColumn create( + final boolean isAscending, + final String name, + final String typeName, + final String defaultValue, + final int isNullable, + final int precision, + final int scale, + final int type, + final boolean isAutoIncrement, + final boolean isRowVersion, + final boolean isCurrency, + final boolean isCaseSensitive) { + final Object lock = new Object(); + return new OIndexColumn(lock, isAscending, name, typeName, + defaultValue, "", isNullable, precision, scale, + type, isAutoIncrement, isRowVersion, isCurrency, isCaseSensitive); + } + + private void registerProperties() { + registerProperty(PropertyIds.ISASCENDING.name, PropertyIds.ISASCENDING.id, Type.BOOLEAN, PropertyAttribute.READONLY, + new PropertyGetter() { + @Override + public Object getValue() { + return isAscending; + + } + }, null); + } + + // XDataDescriptorFactory + + @Override + public XPropertySet createDataDescriptor() { + SdbcxIndexColumnDescriptor descriptor = SdbcxIndexColumnDescriptor.create(isCaseSensitive()); + synchronized (lock) { + CompHelper.copyProperties(this, descriptor); + } + return descriptor; + } +} Propchange: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexColumn.java ------------------------------------------------------------------------------ svn:eol-style = native Added: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexColumnContainer.java URL: http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexColumnContainer.java?rev=1805579&view=auto ============================================================================== --- openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexColumnContainer.java (added) +++ openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexColumnContainer.java Sun Aug 20 19:16:28 2017 @@ -0,0 +1,121 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.star.sdbcx.comp.postgresql.sdbcx; + +import java.util.List; + +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertySet; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.sdbc.SQLException; +import com.sun.star.sdbc.XResultSet; +import com.sun.star.sdbc.XRow; +import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper; +import com.sun.star.sdbcx.comp.postgresql.sdbcx.descriptors.SdbcxIndexColumnDescriptor; +import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds; +import com.sun.star.sdbcx.comp.postgresql.util.StandardSQLState; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.UnoRuntime; + +public class OIndexColumnContainer extends OContainer { + private OIndex index; + + public OIndexColumnContainer(Object lock, OIndex index, List<String> columnNames) { + super(lock, true, columnNames); + this.index = index; + } + + @Override + public XPropertySet createDescriptor() { + return SdbcxIndexColumnDescriptor.create(isCaseSensitive()); + } + + @Override + public XPropertySet createObject(String name) throws SQLException { + try { + Object catalog = index.getTable().getPropertyValue(PropertyIds.CATALOGNAME.name); + String schema = AnyConverter.toString(index.getTable().getPropertyValue(PropertyIds.SCHEMANAME.name)); + String table = AnyConverter.toString(index.getTable().getPropertyValue(PropertyIds.NAME.name)); + + boolean isAscending = true; + XResultSet results = null; + try { + results = index.getTable().getConnection().getMetaData().getIndexInfo(catalog, schema, table, false, false); + if (results != null) { + XRow row = UnoRuntime.queryInterface(XRow.class, results); + while (results.next()) { + if (row.getString(9).equals(name)) { + isAscending = !row.getString(10).equals("D"); + } + } + } + } finally { + CompHelper.disposeComponent(results); + } + + XPropertySet ret = null; + results = null; + try { + results = index.getTable().getConnection().getMetaData().getColumns(catalog, schema, table, name); + if (results != null) { + XRow row = UnoRuntime.queryInterface(XRow.class, results); + while (results.next()) { + if (row.getString(4).equals(name)) { + int dataType = row.getInt(5); + String typeName = row.getString(6); + int size = row.getInt(7); + int dec = row.getInt(9); + int nul = row.getInt(11); + String columnDef = row.getString(13); + + ret = OIndexColumn.create(isAscending, name, typeName, columnDef, + nul, size, dec, dataType, false, false, false, isCaseSensitive()); + break; + } + } + } + } finally { + CompHelper.disposeComponent(results); + } + + return ret; + } catch (WrappedTargetException | UnknownPropertyException | IllegalArgumentException exception) { + throw new SQLException("Error", this, StandardSQLState.SQL_GENERAL_ERROR.text(), 0, exception); + } + } + + @Override + public void impl_refresh() { + // FIXME + } + + @Override + public XPropertySet appendObject(String _rForName, XPropertySet descriptor) throws SQLException { + throw new SQLException("Unsupported"); + } + + @Override + public void dropObject(int index, String name) throws SQLException { + throw new SQLException("Unsupported"); + } +} Propchange: openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexColumnContainer.java ------------------------------------------------------------------------------ svn:eol-style = native